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