github.com/vipernet-xyz/tm@v0.34.24/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/vipernet-xyz/tm/rpc/client/http"
    13  	rpctypes "github.com/vipernet-xyz/tm/rpc/core/types"
    14  	e2e "github.com/vipernet-xyz/tm/test/e2e/pkg"
    15  	"github.com/vipernet-xyz/tm/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  	manifestFile := os.Getenv("E2E_MANIFEST")
    70  	if manifestFile == "" {
    71  		t.Skip("E2E_MANIFEST not set, not an end-to-end test run")
    72  	}
    73  	if !filepath.IsAbs(manifestFile) {
    74  		manifestFile = filepath.Join("..", manifestFile)
    75  	}
    76  
    77  	testnetCacheMtx.Lock()
    78  	defer testnetCacheMtx.Unlock()
    79  	if testnet, ok := testnetCache[manifestFile]; ok {
    80  		return testnet
    81  	}
    82  	m, err := e2e.LoadManifest(manifestFile)
    83  	require.NoError(t, err)
    84  	ifd, err := e2e.NewDockerInfrastructureData(m)
    85  	require.NoError(t, err)
    86  
    87  	testnet, err := e2e.LoadTestnet(m, manifestFile, ifd)
    88  	require.NoError(t, err)
    89  	testnetCache[manifestFile] = *testnet
    90  	return *testnet
    91  }
    92  
    93  // fetchBlockChain fetches a complete, up-to-date block history from
    94  // the freshest testnet archive node.
    95  func fetchBlockChain(t *testing.T) []*types.Block {
    96  	t.Helper()
    97  
    98  	testnet := loadTestnet(t)
    99  
   100  	// Find the freshest archive node
   101  	var (
   102  		client *rpchttp.HTTP
   103  		status *rpctypes.ResultStatus
   104  	)
   105  	for _, node := range testnet.ArchiveNodes() {
   106  		c, err := node.Client()
   107  		require.NoError(t, err)
   108  		s, err := c.Status(ctx)
   109  		require.NoError(t, err)
   110  		if status == nil || s.SyncInfo.LatestBlockHeight > status.SyncInfo.LatestBlockHeight {
   111  			client = c
   112  			status = s
   113  		}
   114  	}
   115  	require.NotNil(t, client, "couldn't find an archive node")
   116  
   117  	// Fetch blocks. Look for existing block history in the block cache, and
   118  	// extend it with any new blocks that have been produced.
   119  	blocksCacheMtx.Lock()
   120  	defer blocksCacheMtx.Unlock()
   121  
   122  	from := status.SyncInfo.EarliestBlockHeight
   123  	to := status.SyncInfo.LatestBlockHeight
   124  	blocks, ok := blocksCache[testnet.Name]
   125  	if !ok {
   126  		blocks = make([]*types.Block, 0, to-from+1)
   127  	}
   128  	if len(blocks) > 0 {
   129  		from = blocks[len(blocks)-1].Height + 1
   130  	}
   131  
   132  	for h := from; h <= to; h++ {
   133  		resp, err := client.Block(ctx, &(h))
   134  		require.NoError(t, err)
   135  		require.NotNil(t, resp.Block)
   136  		require.Equal(t, h, resp.Block.Height, "unexpected block height %v", resp.Block.Height)
   137  		blocks = append(blocks, resp.Block)
   138  	}
   139  	require.NotEmpty(t, blocks, "blockchain does not contain any blocks")
   140  	blocksCache[testnet.Name] = blocks
   141  
   142  	return blocks
   143  }