Skip to content

Commit 07fa89f

Browse files
committed
Add E2E tests for AN backup hosts switch functionality
1 parent 2883e0e commit 07fa89f

File tree

4 files changed

+134
-18
lines changed

4 files changed

+134
-18
lines changed

tests/helpers.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,23 +67,18 @@ func testLogWriter() io.Writer {
6767
return zerolog.NewConsoleWriter()
6868
}
6969

70-
func startEmulator(createTestAccounts bool) (*server.EmulatorServer, error) {
70+
func defaultServerConfig() *server.Config {
7171
pkey, err := crypto.DecodePrivateKeyHex(sigAlgo, servicePrivateKey)
7272
if err != nil {
73-
return nil, err
73+
panic(err)
7474
}
7575

7676
genesisToken, err := cadence.NewUFix64("10000.0")
7777
if err != nil {
78-
return nil, err
78+
panic(err)
7979
}
8080

81-
log := logger.With().Timestamp().Str("component", "emulator").Logger().Level(zerolog.DebugLevel)
82-
if logOutput == "false" {
83-
log = zerolog.Nop()
84-
}
85-
86-
srv := server.NewEmulatorServer(&log, &server.Config{
81+
return &server.Config{
8782
ServicePrivateKey: pkey,
8883
ServiceKeySigAlgo: sigAlgo,
8984
ServiceKeyHashAlgo: hashAlgo,
@@ -94,7 +89,19 @@ func startEmulator(createTestAccounts bool) (*server.EmulatorServer, error) {
9489
TransactionMaxGasLimit: flow.DefaultMaxTransactionGasLimit,
9590
SetupEVMEnabled: true,
9691
SetupVMBridgeEnabled: false,
97-
})
92+
}
93+
}
94+
95+
func startEmulator(createTestAccounts bool, conf *server.Config) (
96+
*server.EmulatorServer,
97+
error,
98+
) {
99+
log := logger.With().Timestamp().Str("component", "emulator").Logger().Level(zerolog.DebugLevel)
100+
if logOutput == "false" {
101+
log = zerolog.Nop()
102+
}
103+
104+
srv := server.NewEmulatorServer(&log, conf)
98105

99106
go func() {
100107
srv.Start()
@@ -133,7 +140,7 @@ func runWeb3TestWithSetup(
133140
// servicesSetup starts up an emulator and the gateway
134141
// engines required for operation of the evm gateway.
135142
func servicesSetup(t *testing.T) (emulator.Emulator, func()) {
136-
srv, err := startEmulator(true)
143+
srv, err := startEmulator(true, defaultServerConfig())
137144
require.NoError(t, err)
138145

139146
ctx, cancel := context.WithCancel(context.Background())

tests/integration_test.go

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030
// This is using the TxSealValidation mechanism for validating submitted
3131
// transactions, which blocks until it receives the Flow transaction result.
3232
func Test_ConcurrentTransactionSubmissionWithTxSeal(t *testing.T) {
33-
srv, err := startEmulator(true)
33+
srv, err := startEmulator(true, defaultServerConfig())
3434
require.NoError(t, err)
3535

3636
ctx, cancel := context.WithCancel(context.Background())
@@ -141,7 +141,7 @@ func Test_ConcurrentTransactionSubmissionWithTxSeal(t *testing.T) {
141141
// This is using the LocalIndexValidation mechanism for validating submitted
142142
// transactions, which is non-blocking and validates based on the local state.
143143
func Test_ConcurrentTransactionSubmissionWithLocalIndex(t *testing.T) {
144-
srv, err := startEmulator(true)
144+
srv, err := startEmulator(true, defaultServerConfig())
145145
require.NoError(t, err)
146146

147147
ctx, cancel := context.WithCancel(context.Background())
@@ -246,7 +246,7 @@ func Test_ConcurrentTransactionSubmissionWithLocalIndex(t *testing.T) {
246246
}
247247

248248
func Test_EthClientTest(t *testing.T) {
249-
srv, err := startEmulator(true)
249+
srv, err := startEmulator(true, defaultServerConfig())
250250
require.NoError(t, err)
251251

252252
ctx, cancel := context.WithCancel(context.Background())
@@ -325,7 +325,7 @@ func Test_CloudKMSConcurrentTransactionSubmission(t *testing.T) {
325325
t.Skip()
326326
}
327327

328-
srv, err := startEmulator(true)
328+
srv, err := startEmulator(true, defaultServerConfig())
329329
require.NoError(t, err)
330330

331331
ctx, cancel := context.WithCancel(context.Background())
@@ -449,7 +449,7 @@ func Test_CloudKMSConcurrentTransactionSubmission(t *testing.T) {
449449
// 2. No transactions are lost
450450
// 3. The state remains consistent
451451
func Test_ForceStartHeightIdempotency(t *testing.T) {
452-
srv, err := startEmulator(true)
452+
srv, err := startEmulator(true, defaultServerConfig())
453453
require.NoError(t, err)
454454

455455
ctx, cancel := context.WithCancel(context.Background())
@@ -592,3 +592,112 @@ func Test_ForceStartHeightIdempotency(t *testing.T) {
592592
return true
593593
}, time.Second*15, time.Second*1, "all transactions were not executed")
594594
}
595+
596+
// Test_AccessNodeBackupFunctionality verifies that the specified AccessNode
597+
// backup hosts, are used when the primary `AccessNodeHost` is unavailable
598+
// or whatever reason.
599+
func Test_AccessNodeBackupFunctionality(t *testing.T) {
600+
srv, err := startEmulator(true, defaultServerConfig())
601+
require.NoError(t, err)
602+
603+
ctx, cancel := context.WithCancel(context.Background())
604+
defer func() {
605+
cancel()
606+
srv.Stop()
607+
}()
608+
609+
backupConfg := defaultServerConfig()
610+
backupConfg.GRPCPort = 3599
611+
backupConfg.RESTPort = 9999
612+
backupConfg.AdminPort = 9090
613+
backupConfg.DebuggerPort = 3456
614+
backupSrv, err := startEmulator(true, backupConfg)
615+
require.NoError(t, err)
616+
617+
_, backupCancel := context.WithCancel(context.Background())
618+
defer func() {
619+
backupCancel()
620+
backupSrv.Stop()
621+
}()
622+
623+
grpcHost := "localhost:3569"
624+
emu := srv.Emulator()
625+
service := emu.ServiceKey()
626+
627+
client, err := grpc.NewClient(grpcHost)
628+
require.NoError(t, err)
629+
630+
time.Sleep(500 * time.Millisecond) // some time to startup
631+
632+
// create new account with keys used for key-rotation
633+
keyCount := 5
634+
createdAddr, privateKey, err := bootstrap.CreateMultiKeyAccount(
635+
client,
636+
keyCount,
637+
service.Address,
638+
sc.FungibleToken.Address.HexWithPrefix(),
639+
sc.FlowToken.Address.HexWithPrefix(),
640+
service.PrivateKey,
641+
)
642+
require.NoError(t, err)
643+
644+
backupAccessNodeHost := fmt.Sprintf("localhost:%d", backupConfg.GRPCPort)
645+
646+
cfg := config.Config{
647+
DatabaseDir: t.TempDir(),
648+
AccessNodeHost: grpcHost,
649+
AccessNodeBackupHosts: []string{backupAccessNodeHost},
650+
RPCPort: 8545,
651+
RPCHost: "127.0.0.1",
652+
FlowNetworkID: "flow-emulator",
653+
EVMNetworkID: types.FlowEVMPreviewNetChainID,
654+
Coinbase: eoaTestAccount,
655+
COAAddress: *createdAddr,
656+
COAKey: privateKey,
657+
GasPrice: new(big.Int).SetUint64(0),
658+
EnforceGasPrice: true,
659+
LogLevel: zerolog.DebugLevel,
660+
LogWriter: testLogWriter(),
661+
TxStateValidation: config.LocalIndexValidation,
662+
}
663+
664+
boot, err := bootstrap.New(cfg)
665+
require.NoError(t, err)
666+
defer func() {
667+
// Stop the EVM GW service
668+
boot.Stop()
669+
}()
670+
671+
ready := make(chan struct{})
672+
go func() {
673+
err = boot.Run(ctx, cfg, func() {
674+
close(ready)
675+
})
676+
require.NoError(t, err)
677+
}()
678+
679+
<-ready
680+
681+
time.Sleep(3 * time.Second) // some time to startup
682+
683+
ethClient, err := ethclient.Dial("http://127.0.0.1:8545")
684+
require.NoError(t, err)
685+
686+
// This endpoint (`eth_syncing`), will make the following gRPC call,
687+
// `ExecuteScriptAtLatestBlock`. This gRPC call is served by the
688+
// first Emulator process, that is configured as the `AccessNodeHost`.
689+
_, err = ethClient.SyncProgress(context.Background())
690+
require.NoError(t, err)
691+
692+
// Shutdown the first Emulator process, that is configured as the
693+
// `AccessNodeHost`
694+
cancel()
695+
srv.Stop()
696+
697+
// This endpoint (`eth_syncing`), will make the following gRPC call,
698+
// `ExecuteScriptAtLatestBlock`. This gRPC call is served by the
699+
// first-available AccessNode specified in `AccessNodeBackupHosts`.
700+
// In this E2E test, that would be the second Emulator process.
701+
_, err = ethClient.SyncProgress(context.Background())
702+
require.NoError(t, err)
703+
}

tests/key_store_release_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
)
2121

2222
func Test_KeyStoreSigningKeysRelease(t *testing.T) {
23-
srv, err := startEmulator(true)
23+
srv, err := startEmulator(true, defaultServerConfig())
2424
require.NoError(t, err)
2525

2626
ctx, cancel := context.WithCancel(context.Background())

tests/tx_batching_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ func Test_MultipleTransactionSubmissionsWithinNonRecentInterval(t *testing.T) {
515515
}
516516

517517
func setupGatewayNode(t *testing.T) (emulator.Emulator, config.Config, func()) {
518-
srv, err := startEmulator(true)
518+
srv, err := startEmulator(true, defaultServerConfig())
519519
require.NoError(t, err)
520520

521521
ctx, cancel := context.WithCancel(context.Background())

0 commit comments

Comments
 (0)