Skip to content

Commit 81c754a

Browse files
committed
[antithesis] Enable reuse of banff e2e test for antithesis testing
1 parent 5cf58be commit 81c754a

File tree

9 files changed

+382
-158
lines changed

9 files changed

+382
-158
lines changed

tests/antithesis/avalanchego/main.go

Lines changed: 84 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/ava-labs/avalanchego/ids"
2121
"github.com/ava-labs/avalanchego/tests"
2222
"github.com/ava-labs/avalanchego/tests/antithesis"
23+
"github.com/ava-labs/avalanchego/tests/e2e/banff"
2324
"github.com/ava-labs/avalanchego/tests/fixture/e2e"
2425
"github.com/ava-labs/avalanchego/tests/fixture/tmpnet"
2526
"github.com/ava-labs/avalanchego/utils/constants"
@@ -44,10 +45,13 @@ import (
4445

4546
const NumKeys = 5
4647

48+
// TODO(marun) Switch to using zap for logging
49+
// TODO(marun) Extract the common elements of test execution for reuse across test setups
50+
4751
func main() {
4852
// TODO(marun) Support choosing the log format
49-
tc := tests.NewTestContext(tests.NewDefaultLogger(""))
50-
defer tc.Cleanup()
53+
tc := antithesis.NewInstrumentedTestContext(tests.NewDefaultLogger(""))
54+
defer tc.RecoverAndExit()
5155
require := require.New(tc)
5256

5357
c := antithesis.NewConfig(
@@ -57,15 +61,12 @@ func main() {
5761
},
5862
)
5963
ctx := tests.DefaultNotifyContext(c.Duration, tc.DeferCleanup)
64+
// Ensure contexts sourced from the test context use the notify context as their parent
65+
tc.SetDefaultContextParent(ctx)
6066

6167
kc := secp256k1fx.NewKeychain(genesis.EWOQKey)
6268
walletSyncStartTime := time.Now()
63-
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
64-
URI: c.URIs[0],
65-
AVAXKeychain: kc,
66-
EthKeychain: kc,
67-
})
68-
require.NoError(err, "failed to initialize wallet")
69+
wallet := e2e.NewWallet(tc, kc, tmpnet.NodeURI{URI: c.URIs[0]})
6970
tc.Log().Info("synced wallet",
7071
zap.Duration("duration", time.Since(walletSyncStartTime)),
7172
)
@@ -120,12 +121,7 @@ func main() {
120121
uri := c.URIs[i%len(c.URIs)]
121122
kc := secp256k1fx.NewKeychain(key)
122123
walletSyncStartTime := time.Now()
123-
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
124-
URI: uri,
125-
AVAXKeychain: kc,
126-
EthKeychain: kc,
127-
})
128-
require.NoError(err, "failed to initialize wallet")
124+
wallet := e2e.NewWallet(tc, kc, tmpnet.NodeURI{URI: uri})
129125
tc.Log().Info("synced wallet",
130126
zap.Duration("duration", time.Since(walletSyncStartTime)),
131127
)
@@ -158,12 +154,25 @@ type workload struct {
158154
uris []string
159155
}
160156

157+
// newTestContext returns a test context that ensures that log output and assertions are
158+
// associated with this worker.
159+
func (w *workload) newTestContext(ctx context.Context) *tests.SimpleTestContext {
160+
return antithesis.NewInstrumentedTestContextWithArgs(
161+
ctx,
162+
w.log,
163+
map[string]any{
164+
"worker": w.id,
165+
},
166+
)
167+
}
168+
161169
func (w *workload) run(ctx context.Context) {
162170
timer := timerpkg.StoppedTimer()
163171

164-
tc := tests.NewTestContext(w.log)
165-
defer tc.Cleanup()
166-
require := require.New(tc)
172+
tc := w.newTestContext(ctx)
173+
// Any assertion failure from this test context will result in process exit due to the
174+
// panic being rethrown. This ensures that failures in test setup are fatal.
175+
defer tc.Recover(true /* rethrow */)
167176

168177
xAVAX, pAVAX := e2e.GetWalletBalances(tc, w.wallet)
169178
assert.Reachable("wallet starting", map[string]any{
@@ -172,32 +181,30 @@ func (w *workload) run(ctx context.Context) {
172181
"pBalance": pAVAX,
173182
})
174183

184+
defaultExecutionDelay := big.NewInt(int64(time.Second))
175185
for {
176-
val, err := rand.Int(rand.Reader, big.NewInt(5))
177-
require.NoError(err, "failed to read randomness")
186+
w.executeTest(ctx)
178187

179-
flowID := val.Int64()
180-
w.log.Info("executing test",
181-
zap.Int("workerID", w.id),
182-
zap.Int64("flowID", flowID),
183-
)
184-
switch flowID {
185-
case 0:
186-
w.issueXChainBaseTx(ctx)
187-
case 1:
188-
w.issueXChainCreateAssetTx(ctx)
189-
case 2:
190-
w.issueXChainOperationTx(ctx)
191-
case 3:
192-
w.issueXToPTransfer(ctx)
193-
case 4:
194-
w.issuePToXTransfer(ctx)
188+
// Delay execution of the next test by a random duration
189+
rawExecutionDelay, err := rand.Int(rand.Reader, defaultExecutionDelay)
190+
// Avoid using require.NoError since the execution delay is not critical and an
191+
// assertion failure in this function is fatal.
192+
if err != nil {
193+
w.log.Error("failed to read randomness",
194+
zap.Error(err),
195+
)
196+
assert.Unreachable("failed to read randomness", map[string]any{
197+
"worker": w.id,
198+
"err": err,
199+
})
200+
rawExecutionDelay = defaultExecutionDelay
195201
}
202+
executionDelay := time.Duration(rawExecutionDelay.Int64())
203+
w.log.Info("waiting",
204+
zap.Duration("duration", executionDelay),
205+
)
206+
timer.Reset(executionDelay)
196207

197-
val, err = rand.Int(rand.Reader, big.NewInt(int64(time.Second)))
198-
require.NoError(err, "failed to read randomness")
199-
200-
timer.Reset(time.Duration(val.Int64()))
201208
select {
202209
case <-ctx.Done():
203210
return
@@ -206,6 +213,44 @@ func (w *workload) run(ctx context.Context) {
206213
}
207214
}
208215

216+
// executeTest executes a test at random.
217+
func (w *workload) executeTest(ctx context.Context) {
218+
tc := w.newTestContext(ctx)
219+
// Panics will be recovered without being rethrown, ensuring that test failures are not fatal.
220+
defer tc.Recover(false /* rethrow */)
221+
require := require.New(tc)
222+
223+
val, err := rand.Int(rand.Reader, big.NewInt(6))
224+
require.NoError(err, "failed to read randomness")
225+
226+
// TODO(marun)
227+
flowID := val.Int64()
228+
switch flowID {
229+
case 0:
230+
// TODO(marun) Create abstraction for a test that supports a name e.g. `aTest{name: "foo", mytestfunc}`
231+
w.log.Info("executing issueXChainBaseTx")
232+
w.issueXChainBaseTx(ctx)
233+
case 1:
234+
w.log.Info("executing issueXChainCreateAssetTx")
235+
w.issueXChainCreateAssetTx(ctx)
236+
case 2:
237+
w.log.Info("executing issueXChainOperationTx")
238+
w.issueXChainOperationTx(ctx)
239+
case 3:
240+
w.log.Info("executing issueXToPTransfer")
241+
w.issueXToPTransfer(ctx)
242+
case 4:
243+
w.log.Info("executing issuePToXTransfer")
244+
w.issuePToXTransfer(ctx)
245+
case 5:
246+
w.log.Info("executing banff.TestCustomAssetTransfer")
247+
addr, _ := w.addrs.Peek()
248+
banff.TestCustomAssetTransfer(tc, w.wallet, addr)
249+
case 6:
250+
w.log.Info("sleeping")
251+
}
252+
}
253+
209254
func (w *workload) issueXChainBaseTx(ctx context.Context) {
210255
var (
211256
xWallet = w.wallet.X()

tests/antithesis/context.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package antithesis
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"maps"
10+
11+
"github.com/antithesishq/antithesis-sdk-go/assert"
12+
13+
"github.com/ava-labs/avalanchego/tests"
14+
"github.com/ava-labs/avalanchego/utils/logging"
15+
)
16+
17+
// NewInstrumentedTestContext returns a test context that makes antithesis SDK assertions.
18+
func NewInstrumentedTestContext(log logging.Logger) *tests.SimpleTestContext {
19+
return NewInstrumentedTestContextWithArgs(context.Background(), log, nil)
20+
}
21+
22+
// NewInstrumentedTestContextWithArgs returns a test context that makes antithesis SDK assertions.
23+
func NewInstrumentedTestContextWithArgs(
24+
ctx context.Context,
25+
log logging.Logger,
26+
details map[string]any,
27+
) *tests.SimpleTestContext {
28+
return tests.NewTestContextWithArgs(
29+
ctx,
30+
log,
31+
func(format string, args ...any) {
32+
assert.Unreachable(fmt.Sprintf("Assertion failure: "+format, args...), details)
33+
},
34+
func(r any) {
35+
detailsClone := maps.Clone(details)
36+
details["panic"] = r
37+
assert.Unreachable("unexpected panic", detailsClone)
38+
},
39+
)
40+
}

tests/antithesis/xsvm/main.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ const (
3939

4040
func main() {
4141
// TODO(marun) Support choosing the log format
42-
tc := tests.NewTestContext(tests.NewDefaultLogger(""))
43-
defer tc.Cleanup()
42+
tc := antithesis.NewInstrumentedTestContext(tests.NewDefaultLogger(""))
43+
defer tc.RecoverAndExit()
4444
require := require.New(tc)
4545

4646
c := antithesis.NewConfigWithSubnets(
@@ -55,6 +55,8 @@ func main() {
5555
},
5656
)
5757
ctx := tests.DefaultNotifyContext(c.Duration, tc.DeferCleanup)
58+
// Ensure contexts sourced from the test context use the notify context as their parent
59+
tc.SetDefaultContextParent(ctx)
5860

5961
require.Len(c.ChainIDs, 1)
6062
tc.Log().Debug("raw chain ID",
@@ -140,8 +142,16 @@ type workload struct {
140142
func (w *workload) run(ctx context.Context) {
141143
timer := timerpkg.StoppedTimer()
142144

143-
tc := tests.NewTestContext(w.log)
144-
defer tc.Cleanup()
145+
tc := antithesis.NewInstrumentedTestContextWithArgs(
146+
ctx,
147+
w.log,
148+
map[string]any{
149+
"worker": w.id,
150+
},
151+
)
152+
// Any assertion failure from this test context will result in process exit due to the
153+
// panic being rethrown. This ensures that failures in test setup are fatal.
154+
defer tc.Recover(true /* rethrow */)
145155
require := require.New(tc)
146156

147157
uri := w.uris[w.id%len(w.uris)]

tests/context_helpers.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ const DefaultTimeout = 2 * time.Minute
1616

1717
// Helper simplifying use of a timed context by canceling the context with the test context.
1818
func ContextWithTimeout(tc TestContext, duration time.Duration) context.Context {
19-
ctx, cancel := context.WithTimeout(context.Background(), duration)
19+
parent := tc.GetDefaultContextParent()
20+
if parent == nil {
21+
parent = context.Background()
22+
}
23+
ctx, cancel := context.WithTimeout(parent, duration)
2024
tc.DeferCleanup(cancel)
2125
return ctx
2226
}

0 commit comments

Comments
 (0)