def addNodeBackAndCheck(nodeIdx: int, expectedStatus: Status):
     logger.info("Add back the {} node and see status of {}".
                 format(ordinal(nodeIdx + 1), expectedStatus))
     addNodeBack(
         current_node_set, looper,
         get_node_by_name(txnPoolNodeSet, nodeNames[nodeIdx]),
         tconf, tdir)
     looper.run(checkNodesConnected(current_node_set))
     timeout = waits.expectedNodeStartUpTimeout() + \
               waits.expectedPoolInterconnectionTime(len(current_node_set))
     # TODO: Probably it's better to modify waits.* functions
     timeout *= 1.5
     looper.run(eventually(checkNodeStatusRemotesAndF,
                           expectedStatus,
                           nodeIdx,
                           retryWait=1, timeout=timeout))
 def addNodeBackAndCheck(nodeIdx: int, expectedStatus: Status):
     logger.info("Add back the {} node and see status of {}".
                 format(ordinal(nodeIdx + 1), expectedStatus))
     addNodeBack(
         current_node_set, looper,
         get_node_by_name(txnPoolNodeSet, nodeNames[nodeIdx]),
         tconf, tdir)
     looper.run(checkNodesConnected(current_node_set))
     timeout = waits.expectedNodeStartUpTimeout() + \
               waits.expectedPoolInterconnectionTime(len(current_node_set))
     # TODO: Probably it's better to modify waits.* functions
     timeout *= 1.5
     looper.run(eventually(checkNodeStatusRemotesAndF,
                           expectedStatus,
                           nodeIdx,
                           retryWait=1, timeout=timeout))
def testProtocolInstanceCannotBecomeActiveWithLessThanFourServers(
        txnPoolNodeSet, looper, tconf, tdir):
    """
    A protocol instance must have at least 4 nodes to come up.
    The status of the nodes will change from starting to started only after the
    addition of the fourth node to the system.
    """

    nodeNames = genNodeNames(nodeCount)
    current_node_set = list(txnPoolNodeSet)

    def genExpectedStates(connecteds: Iterable[str]):
        return {
            nn: CONNECTED if nn in connecteds else JOINED_NOT_ALLOWED
            for nn in nodeNames}

    def checkNodeStatusRemotesAndF(expectedStatus: Status,
                                   nodeIdx: int):
        for node in current_node_set:
            checkNodeRemotes(node,
                             genExpectedStates(nodeNames[:nodeIdx + 1]))
            assert node.status == expectedStatus

    def addNodeBackAndCheck(nodeIdx: int, expectedStatus: Status):
        logger.info("Add back the {} node and see status of {}".
                    format(ordinal(nodeIdx + 1), expectedStatus))
        addNodeBack(
            current_node_set, looper,
            get_node_by_name(txnPoolNodeSet, nodeNames[nodeIdx]),
            tconf, tdir)
        looper.run(checkNodesConnected(current_node_set))
        timeout = waits.expectedNodeStartUpTimeout() + \
                  waits.expectedPoolInterconnectionTime(len(current_node_set))
        # TODO: Probably it's better to modify waits.* functions
        timeout *= 1.5
        looper.run(eventually(checkNodeStatusRemotesAndF,
                              expectedStatus,
                              nodeIdx,
                              retryWait=1, timeout=timeout))

    logger.debug("Sharing keys")
    looper.run(checkNodesConnected(current_node_set))

    logger.debug("Remove all the nodes")
    for n in nodeNames:
        node_n = get_node_by_name(current_node_set, n)
        disconnect_node_and_ensure_disconnected(looper,
                                                current_node_set,
                                                node_n,
                                                timeout=nodeCount,
                                                stopNode=True)
        looper.removeProdable(node_n)
        current_node_set.remove(node_n)

    # looper.runFor(10)

    logger.debug("Add nodes back one at a time")
    for i in range(nodeCount):
        nodes = i + 1
        if nodes < minimumNodesToBeUp:
            expectedStatus = Status.starting
        elif nodes < nodeCount:
            expectedStatus = Status.started_hungry
        else:
            expectedStatus = Status.started
        addNodeBackAndCheck(i, expectedStatus)
def testProtocolInstanceCannotBecomeActiveWithLessThanFourServers(
        txnPoolNodeSet, looper, tconf, tdir):
    """
    A protocol instance must have at least 4 nodes to come up.
    The status of the nodes will change from starting to started only after the
    addition of the fourth node to the system.
    """

    nodeNames = genNodeNames(nodeCount)
    current_node_set = list(txnPoolNodeSet)

    def genExpectedStates(connecteds: Iterable[str]):
        return {
            nn: CONNECTED if nn in connecteds else JOINED_NOT_ALLOWED
            for nn in nodeNames}

    def checkNodeStatusRemotesAndF(expectedStatus: Status,
                                   nodeIdx: int):
        for node in current_node_set:
            checkNodeRemotes(node,
                             genExpectedStates(nodeNames[:nodeIdx + 1]))
            assert node.status == expectedStatus

    def addNodeBackAndCheck(nodeIdx: int, expectedStatus: Status):
        logger.info("Add back the {} node and see status of {}".
                    format(ordinal(nodeIdx + 1), expectedStatus))
        addNodeBack(
            current_node_set, looper,
            get_node_by_name(txnPoolNodeSet, nodeNames[nodeIdx]),
            tconf, tdir)
        looper.run(checkNodesConnected(current_node_set))
        timeout = waits.expectedNodeStartUpTimeout() + \
                  waits.expectedPoolInterconnectionTime(len(current_node_set))
        # TODO: Probably it's better to modify waits.* functions
        timeout *= 1.5
        looper.run(eventually(checkNodeStatusRemotesAndF,
                              expectedStatus,
                              nodeIdx,
                              retryWait=1, timeout=timeout))

    logger.debug("Sharing keys")
    looper.run(checkNodesConnected(current_node_set))

    logger.debug("Remove all the nodes")
    for n in nodeNames:
        node_n = get_node_by_name(current_node_set, n)
        disconnect_node_and_ensure_disconnected(looper,
                                                current_node_set,
                                                node_n,
                                                timeout=nodeCount,
                                                stopNode=True)
        looper.removeProdable(node_n)
        current_node_set.remove(node_n)

    # looper.runFor(10)

    logger.debug("Add nodes back one at a time")
    for i in range(nodeCount):
        nodes = i + 1
        if nodes < minimumNodesToBeUp:
            expectedStatus = Status.starting
        elif nodes < nodeCount:
            expectedStatus = Status.started_hungry
        else:
            expectedStatus = Status.started
        addNodeBackAndCheck(i, expectedStatus)