Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[P2P] [Testing] Parallelize P2P tests #735

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions internal/testutil/mockdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import (
"fmt"
"net"
"net/url"
"testing"

"github.com/foxcpp/go-mockdns"
"github.com/stretchr/testify/require"
)

func PrepareDNSMockFromServiceURLs(t *testing.T, serviceURLs []string) (done func()) {
func PrepareDNSMockFromServiceURLs(serviceURLs []string) (done func(), err error) {
zones := make(map[string]mockdns.Zone)
for i, u := range serviceURLs {
// Perpend `scheme://` as serviceURLs are currently scheme-less.
// Required for parsing to produce useful results.
// (see: https://pkg.go.dev/net/[email protected]#URL)
serviceURL, err := url.Parse(fmt.Sprintf("scheme://%s", u))
require.NoError(t, err)
if err != nil {
return nil, err
}

ipStr := fmt.Sprintf("10.0.0.%d", i+1)

Expand All @@ -30,7 +30,7 @@ func PrepareDNSMockFromServiceURLs(t *testing.T, serviceURLs []string) (done fun
}
}

return PrepareDNSMock(zones)
return PrepareDNSMock(zones), nil
}

func PrepareDNSMock(zones map[string]mockdns.Zone) (done func()) {
Expand Down
32 changes: 30 additions & 2 deletions p2p/module_raintree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ import (
// TODO(#314): Add the tooling and instructions on how to generate unit tests in this file.

func TestMain(m *testing.M) {
// build a slice of serviceURLs `validatorId(<num>)` for `<num>` in [1, <largest validator ID>]
var serviceURLs []string
for i := 1; i <= 27; i++ {
serviceURLs = append(serviceURLs, validatorId(i))
}

dnsMockDone, err := testutil.PrepareDNSMockFromServiceURLs(serviceURLs)
if err != nil {
log.Fatalf("Error preparing DNS mock: %v", err)
}
defer dnsMockDone()

exitCode := m.Run()
files, err := filepath.Glob("*.json")
if err != nil {
Expand All @@ -36,6 +48,8 @@ func TestMain(m *testing.M) {

// ### RainTree Unit Tests ###
func TestRainTreeNetworkCompleteOneNodes(t *testing.T) {
t.Parallel()

// val_1
originatorNode := validatorId(1)
expectedCalls := TestNetworkSimulationConfig{
Expand All @@ -45,6 +59,8 @@ func TestRainTreeNetworkCompleteOneNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteTwoNodes(t *testing.T) {
t.Parallel()

// val_1
// └───────┐
// val_2
Expand All @@ -61,6 +77,8 @@ func TestRainTreeNetworkCompleteTwoNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteThreeNodes(t *testing.T) {
t.Parallel()

// val_1
// ┌───────┴────┬─────────┐
// val_2 val_1 val_3
Expand All @@ -74,6 +92,8 @@ func TestRainTreeNetworkCompleteThreeNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteFourNodes(t *testing.T) {
t.Parallel()

// Test configurations (visualization retrieved from simulator)
// val_1
// ┌───────────────┴────┬─────────────────┐
Expand All @@ -91,6 +111,8 @@ func TestRainTreeNetworkCompleteFourNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteNineNodes(t *testing.T) {
t.Parallel()

// val_1
// ┌──────────────────────┴────────────┬────────────────────────────────┐
// val_4 val_1 val_7
Expand Down Expand Up @@ -120,6 +142,8 @@ func TestRainTreeNetworkCompleteNineNodes(t *testing.T) {
// val_8 val_7 val_10 val_6 val_5 val_8 val_11 val_10 val_5 val_4 val_3 val_6 val_2 val_1 val_4 val_7 val_6 val_1 val_12 val_11 val_2 val_10 val_9 val_12 val_3 val_2 val_9

func TestRainTreeCompleteTwelveNodes(t *testing.T) {
t.Parallel()

originatorNode := validatorId(1)
expectedCalls := TestNetworkSimulationConfig{
originatorNode: {1, 6},
Expand All @@ -139,6 +163,8 @@ func TestRainTreeCompleteTwelveNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteEighteenNodes(t *testing.T) {
t.Parallel()

// val_1
// ┌──────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
// val_7 val_1 val_13
Expand Down Expand Up @@ -171,6 +197,8 @@ func TestRainTreeNetworkCompleteEighteenNodes(t *testing.T) {
}

func TestRainTreeNetworkCompleteTwentySevenNodes(t *testing.T) {
t.Parallel()

// val_1
// ┌────────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┐
// val_10 val_1 val_19
Expand Down Expand Up @@ -217,6 +245,8 @@ func TestRainTreeNetworkCompleteTwentySevenNodes(t *testing.T) {
// 1. It creates and configures a "real" P2P module where all the other components of the node are mocked.
// 2. It then triggers a single message and waits for all of the expected messages transmission to complete before announcing failure.
func testRainTreeCalls(t *testing.T, origNode string, networkSimulationConfig TestNetworkSimulationConfig) {
t.Helper()

// Configure & prepare test module
numValidators := len(networkSimulationConfig)
runtimeConfigs := createMockRuntimeMgrs(t, numValidators)
Expand All @@ -234,8 +264,6 @@ func testRainTreeCalls(t *testing.T, origNode string, networkSimulationConfig Te
return iId < jId
})

testutil.PrepareDNSMockFromServiceURLs(t, valIds)

// Create connection and bus mocks along with a shared WaitGroup to track the number of expected
// reads and writes throughout the mocked local network
var wg sync.WaitGroup
Expand Down
18 changes: 14 additions & 4 deletions p2p/raintree/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
var testLocalServiceURL = fmt.Sprintf("127.0.0.1:%d", defaults.DefaultP2PPort)

func TestRainTreeRouter_AddPeer(t *testing.T) {
t.Parallel()

ctrl := gomock.NewController(t)

// Start with a peerstore containing self.
Expand Down Expand Up @@ -79,7 +81,7 @@ func TestRainTreeRouter_AddPeer(t *testing.T) {
require.NoError(t, err)
expectedPStoreSize++

peerAddrs, peers := getPeersViewParts(rtRouter.peersManager)
peerAddrs, peers := getPeersViewParts(t, rtRouter.peersManager)

// Ensure size / lengths are consistent.
require.Equal(t, expectedPStoreSize, router.GetPeerstore().Size())
Expand All @@ -97,6 +99,8 @@ func TestRainTreeRouter_AddPeer(t *testing.T) {
}

func TestRainTreeRouter_RemovePeer(t *testing.T) {
t.Parallel()

ctrl := gomock.NewController(t)

// Start with a peerstore which contains self and some number of peers: the
Expand Down Expand Up @@ -129,7 +133,7 @@ func TestRainTreeRouter_RemovePeer(t *testing.T) {
rainTree := router.(*rainTreeRouter)

// Ensure expected starting size / lengths are consistent.
peerAddrs, peers := getPeersViewParts(rainTree.peersManager)
peerAddrs, peers := getPeersViewParts(t, rainTree.peersManager)
require.Equal(t, expectedPStoreSize, pstore.Size())
require.Equal(t, expectedPStoreSize, len(peerAddrs))
require.Equal(t, expectedPStoreSize, len(peers))
Expand All @@ -154,7 +158,7 @@ func TestRainTreeRouter_RemovePeer(t *testing.T) {
require.NoError(t, err)
expectedPStoreSize--

peerAddrs, peers = getPeersViewParts(rainTree.peersManager)
peerAddrs, peers = getPeersViewParts(t, rainTree.peersManager)
removedAddr := peerToRemove.GetAddress()
getPeer := func(addr cryptoPocket.Address) typesP2P.Peer {
return rainTree.GetPeerstore().GetPeer(addr)
Expand All @@ -169,10 +173,12 @@ func TestRainTreeRouter_RemovePeer(t *testing.T) {
require.Nil(t, getPeer(removedAddr), "Peerstore contains removed peer")
}

func getPeersViewParts(pm typesP2P.PeerManager) (
func getPeersViewParts(t *testing.T, pm typesP2P.PeerManager) (
addrs []string,
peers typesP2P.PeerList,
) {
t.Helper()

view := pm.GetPeersView()
addrs = view.GetAddrs()
peers = view.GetPeers()
Expand All @@ -181,6 +187,8 @@ func getPeersViewParts(pm typesP2P.PeerManager) (
}

func newTestPeer(t *testing.T) (*typesP2P.NetworkPeer, libp2pHost.Host) {
t.Helper()

selfPrivKey, err := cryptoPocket.GeneratePrivateKey()
require.NoError(t, err)

Expand All @@ -195,6 +203,8 @@ func newTestPeer(t *testing.T) (*typesP2P.NetworkPeer, libp2pHost.Host) {

// TECHDEBT(#609): move & de-duplicate
func newLibp2pMockNetHost(t *testing.T, privKey cryptoPocket.PrivateKey, peer *typesP2P.NetworkPeer) libp2pHost.Host {
t.Helper()

libp2pPrivKey, err := libp2pCrypto.UnmarshalEd25519PrivateKey(privKey.Bytes())
require.NoError(t, err)

Expand Down