Revision 8bdd9b6795f6a78ffca1f4e0649531d71fa51f88 authored by Marge Bot on 13 September 2022, 10:56:47 UTC, committed by Marge Bot on 13 September 2022, 10:56:47 UTC
Co-authored-by: Ole Krüger <ole.kruger@trili.tech>

Approved-by: Swann Moreau <evertedsphere@gmail.com>
Approved-by: Emma Turner <1623821-emturner@users.noreply.gitlab.com>
Approved-by: Nicolas Ayache <nicolas.ayache@nomadic-labs.com>
Approved-by: Andrea Cerone <andrea.cerone@trili.tech>

See merge request https://gitlab.com/tezos/tezos/-/merge_requests/6285
2 parent s 67f2631 + 7f53a77
Raw File
test_p2p.py
import time
import pytest
from tools import constants
from launchers.sandbox import Sandbox


NUM_NODES = 5
NUM_RETRIES = 20  # empirical values for testing a liveness property
POLLING_TIME = 10  # NUM_RETRY * POLLING_TIME = 200s, should be conservative


@pytest.mark.multinode
@pytest.mark.incremental
class TestTrustedRing:
    """This test sets up a network of public peers (running the default
    p2p protocol), with no initial bootstrap peers. It initializes a
    trusted ring relationship, and checks that points are advertised
    correctly to the whole network."""

    def test_init(self, sandbox: Sandbox):
        for i in range(NUM_NODES):
            sandbox.add_node(
                i,
                private=False,
                peers=[],
                params=constants.NODE_PARAMS,
                config_client=False,
            )

    def test_no_peers(self, sandbox: Sandbox):
        """Initially, nobody knows other peers."""
        for client in sandbox.all_clients():
            res = client.p2p_stat()
            assert not res.peers

    def test_add_peers(self, sandbox: Sandbox):
        """Set up a trusted ring topology."""
        base_p2p = sandbox.p2p
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            client.trust_peer(base_p2p + ((i + 1) % NUM_NODES))

    def test_check_clique(self, sandbox: Sandbox):
        """Everyone should be connected to everyone else. This is a
        liveness property. Its realization depends on the timing of the
        p2p maintenance process. The check is repeated up to NUM_RETRIES
        times with a POLLING_TIME seconds wait."""
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            for _ in range(NUM_RETRIES):
                points = client.p2p_stat().points.values()
                num_connected = len(
                    [point for point in points if point.is_connected]
                )
                if num_connected == NUM_NODES - 1:
                    break
                time.sleep(POLLING_TIME)
            assert num_connected == NUM_NODES - 1

    def test_check_tables(self, sandbox: Sandbox):
        """Test various assumptions on the point/peer tables.
        Each peer has exactly one trusted neighbor. Tables don't
        contain their own peer/point id and contain exactly NUM_NODES - 1
        values.

        The previous test should guarantee that maintenance has been
        performed when this test is run."""
        base_p2p = sandbox.p2p
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            point_id = f'127.0.0.1:{base_p2p + i}'
            peer_id = client.rpc('get', '/network/self')
            res = client.p2p_stat()
            assert peer_id not in res.peers
            assert point_id not in res.points
            num_trusted = 0
            for point_id, point in res.points.items():
                num_trusted += point.is_trusted
            assert num_trusted == 1
            assert len(res.peers) == NUM_NODES - 1
            assert len(res.points) == NUM_NODES - 1

    def test_set_expected_peers(self, sandbox: Sandbox):
        """For all nodes, we add one expected peer_id
        for the successor node."""
        peers_id = {}
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            peers_id[i] = client.rpc('get', '/network/self')

        for i in range(NUM_NODES):
            client = sandbox.client(i)
            client.set_expected_peer_id(
                sandbox.p2p + ((i + 1) % NUM_NODES),
                peers_id[(i + 1) % NUM_NODES],
            )

    def test_expected_peers(self, sandbox: Sandbox):
        """For all nodes, we check that expected peer_id was
        set properly."""
        peers_id = {}
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            peers_id[i] = client.rpc('get', '/network/self')

        for i in range(NUM_NODES):
            client = sandbox.client(i)
            expected_id = client.get_expected_peer_id(
                sandbox.p2p + ((i + 1) % NUM_NODES)
            )
            assert expected_id == peers_id[(i + 1) % NUM_NODES]

    def test_wrong_expected_peer(self, sandbox: Sandbox):
        """We change the expected peer_id set previously to a wrong
        expected peer_id."""
        peers_id = {}
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            peers_id[i] = client.rpc('get', '/network/self')

        for i in range(NUM_NODES):
            client = sandbox.client(i)
            client.set_expected_peer_id(
                sandbox.p2p + ((i + 2) % NUM_NODES), peers_id[i]
            )

    def test_check_stat_with_wrong_expected_peers(self, sandbox: Sandbox):
        """All nodes are public, everyone should be connected. But
        only one neighbor should be trusted."""
        base_p2p = sandbox.p2p
        for i in range(NUM_NODES):
            client = sandbox.client(i)
            point_id = '127.0.0.1:' + str(base_p2p + i)
            peer_id = client.rpc('get', '/network/self')
            res = client.p2p_stat()
            assert peer_id not in res.peers
            assert point_id not in res.points
            num_trusted = 0
            num_connected = 0
            for point_id, point in res.points.items():
                num_trusted += point.is_trusted
                num_connected += point.is_connected
            assert len(res.peers) == NUM_NODES - 1
            assert len(res.points) == NUM_NODES - 1
            assert num_trusted == 1
            # We lost two connections
            assert num_connected == NUM_NODES - 1 - 2
back to top