github.com/consideritdone/landslidecore@v0.0.0-20230718131026-a8b21c5cf8a7/test/e2e/tests/e2e_test.go (about) 1 package e2e_test 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "sync" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 12 rpchttp "github.com/consideritdone/landslidecore/rpc/client/http" 13 rpctypes "github.com/consideritdone/landslidecore/rpc/core/types" 14 e2e "github.com/consideritdone/landslidecore/test/e2e/pkg" 15 "github.com/consideritdone/landslidecore/types" 16 ) 17 18 func init() { 19 // This can be used to manually specify a testnet manifest and/or node to 20 // run tests against. The testnet must have been started by the runner first. 21 // os.Setenv("E2E_MANIFEST", "networks/ci.toml") 22 // os.Setenv("E2E_NODE", "validator01") 23 } 24 25 var ( 26 ctx = context.Background() 27 testnetCache = map[string]e2e.Testnet{} 28 testnetCacheMtx = sync.Mutex{} 29 blocksCache = map[string][]*types.Block{} 30 blocksCacheMtx = sync.Mutex{} 31 ) 32 33 // testNode runs tests for testnet nodes. The callback function is given a 34 // single node to test, running as a subtest in parallel with other subtests. 35 // 36 // The testnet manifest must be given as the envvar E2E_MANIFEST. If not set, 37 // these tests are skipped so that they're not picked up during normal unit 38 // test runs. If E2E_NODE is also set, only the specified node is tested, 39 // otherwise all nodes are tested. 40 func testNode(t *testing.T, testFunc func(*testing.T, e2e.Node)) { 41 t.Helper() 42 43 testnet := loadTestnet(t) 44 nodes := testnet.Nodes 45 46 if name := os.Getenv("E2E_NODE"); name != "" { 47 node := testnet.LookupNode(name) 48 require.NotNil(t, node, "node %q not found in testnet %q", name, testnet.Name) 49 nodes = []*e2e.Node{node} 50 } 51 52 for _, node := range nodes { 53 if node.Stateless() { 54 continue 55 } 56 57 node := *node 58 t.Run(node.Name, func(t *testing.T) { 59 t.Parallel() 60 testFunc(t, node) 61 }) 62 } 63 } 64 65 // loadTestnet loads the testnet based on the E2E_MANIFEST envvar. 66 func loadTestnet(t *testing.T) e2e.Testnet { 67 t.Helper() 68 69 manifest := os.Getenv("E2E_MANIFEST") 70 if manifest == "" { 71 t.Skip("E2E_MANIFEST not set, not an end-to-end test run") 72 } 73 if !filepath.IsAbs(manifest) { 74 manifest = filepath.Join("..", manifest) 75 } 76 77 testnetCacheMtx.Lock() 78 defer testnetCacheMtx.Unlock() 79 if testnet, ok := testnetCache[manifest]; ok { 80 return testnet 81 } 82 83 testnet, err := e2e.LoadTestnet(manifest) 84 require.NoError(t, err) 85 testnetCache[manifest] = *testnet 86 return *testnet 87 } 88 89 // fetchBlockChain fetches a complete, up-to-date block history from 90 // the freshest testnet archive node. 91 func fetchBlockChain(t *testing.T) []*types.Block { 92 t.Helper() 93 94 testnet := loadTestnet(t) 95 96 // Find the freshest archive node 97 var ( 98 client *rpchttp.HTTP 99 status *rpctypes.ResultStatus 100 ) 101 for _, node := range testnet.ArchiveNodes() { 102 c, err := node.Client() 103 require.NoError(t, err) 104 s, err := c.Status(ctx) 105 require.NoError(t, err) 106 if status == nil || s.SyncInfo.LatestBlockHeight > status.SyncInfo.LatestBlockHeight { 107 client = c 108 status = s 109 } 110 } 111 require.NotNil(t, client, "couldn't find an archive node") 112 113 // Fetch blocks. Look for existing block history in the block cache, and 114 // extend it with any new blocks that have been produced. 115 blocksCacheMtx.Lock() 116 defer blocksCacheMtx.Unlock() 117 118 from := status.SyncInfo.EarliestBlockHeight 119 to := status.SyncInfo.LatestBlockHeight 120 blocks, ok := blocksCache[testnet.Name] 121 if !ok { 122 blocks = make([]*types.Block, 0, to-from+1) 123 } 124 if len(blocks) > 0 { 125 from = blocks[len(blocks)-1].Height + 1 126 } 127 128 for h := from; h <= to; h++ { 129 resp, err := client.Block(ctx, &(h)) 130 require.NoError(t, err) 131 require.NotNil(t, resp.Block) 132 require.Equal(t, h, resp.Block.Height, "unexpected block height %v", resp.Block.Height) 133 blocks = append(blocks, resp.Block) 134 } 135 require.NotEmpty(t, blocks, "blockchain does not contain any blocks") 136 blocksCache[testnet.Name] = blocks 137 138 return blocks 139 }