Skip to content

Commit f2e5a78

Browse files
authored
Merge pull request #8190 from onflow/taras/7157-optimize-access-integration-tests-runtime
Optimize access integration tests runtime
2 parents 26270d4 + cc897ce commit f2e5a78

15 files changed

+582
-631
lines changed

integration/tests/access/cohort1/access_api_test.go

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,50 @@ type AccessAPISuite struct {
9696
serviceClient *testnet.Client
9797
}
9898

99+
func (s *AccessAPISuite) TestAccessAPIs() {
100+
// Deploy the test contract once for both AN1 and AN2 tests
101+
_ = s.deployContract(lib.CounterContract, false)
102+
txResult := s.deployCounter()
103+
targetHeight := txResult.BlockHeight + 1
104+
s.waitUntilIndexed(targetHeight)
105+
106+
s.T().Run("Script execution and get accounts using execution nodes", func(t *testing.T) {
107+
s.testScriptExecutionAndGetAccountsAN1(targetHeight)
108+
})
109+
110+
s.T().Run("Script execution and get accounts using local data", func(t *testing.T) {
111+
s.testScriptExecutionAndGetAccountsAN2(targetHeight)
112+
})
113+
114+
s.T().Run("MVP script execution with local storage", func(t *testing.T) {
115+
s.testMVPScriptExecutionLocalStorage()
116+
})
117+
118+
s.T().Run("Send and subscribe transaction statuses", func(t *testing.T) {
119+
s.testSendAndSubscribeTransactionStatuses()
120+
})
121+
122+
s.T().Run("Contract update", func(t *testing.T) {
123+
s.testContractUpdate()
124+
})
125+
126+
s.T().Run("Transaction signature with plain extension data", func(t *testing.T) {
127+
s.testTransactionSignaturePlainExtensionData()
128+
})
129+
130+
s.T().Run("Transaction signature with WebAuthn extension data", func(t *testing.T) {
131+
s.testTransactionSignatureWebAuthnExtensionData()
132+
})
133+
134+
s.T().Run("Extension data preservation", func(t *testing.T) {
135+
s.testExtensionDataPreservation()
136+
})
137+
138+
s.T().Run("Rejected invalid signature format", func(t *testing.T) {
139+
s.testRejectedInvalidSignatureFormat()
140+
})
141+
}
142+
99143
func (s *AccessAPISuite) TearDownTest() {
100144
s.log.Info().Msg("================> Start TearDownTest")
101145
s.net.Remove()
@@ -193,50 +237,38 @@ func (s *AccessAPISuite) SetupTest() {
193237
}, 30*time.Second, 1*time.Second)
194238
}
195239

196-
// TestScriptExecutionAndGetAccountsAN1 test the Access API endpoints for executing scripts and getting
240+
// testScriptExecutionAndGetAccountsAN1 test the Access API endpoints for executing scripts and getting
197241
// accounts using execution nodes.
198242
//
199243
// Note: not combining AN1, AN2 tests together because that causes a drastic increase in test run times. test cases are read-only
200244
// and should not interfere with each other.
201-
func (s *AccessAPISuite) TestScriptExecutionAndGetAccountsAN1() {
202-
// deploy the test contract
203-
_ = s.deployContract(lib.CounterContract, false)
204-
txResult := s.deployCounter()
205-
targetHeight := txResult.BlockHeight + 1
206-
s.waitUntilIndexed(targetHeight)
207-
245+
func (s *AccessAPISuite) testScriptExecutionAndGetAccountsAN1(targetHeight uint64) {
208246
// Run tests against Access 1, which uses the execution node
209247
s.testGetAccount(s.an1Client)
210248
s.testExecuteScriptWithSimpleScript(s.an1Client)
211249
s.testExecuteScriptWithSimpleContract(s.an1Client, targetHeight)
212250
}
213251

214-
// TestScriptExecutionAndGetAccountsAN2 test the Access API endpoints for executing scripts and getting
252+
// testScriptExecutionAndGetAccountsAN2 test the Access API endpoints for executing scripts and getting
215253
// accounts using local storage.
216254
//
217255
// Note: not combining AN1, AN2 tests together because that causes a drastic increase in test run times. test cases are read-only
218256
// and should not interfere with each other.
219-
func (s *AccessAPISuite) TestScriptExecutionAndGetAccountsAN2() {
220-
// deploy the test contract
221-
_ = s.deployContract(lib.CounterContract, false)
222-
txResult := s.deployCounter()
223-
targetHeight := txResult.BlockHeight + 1
224-
s.waitUntilIndexed(targetHeight)
225-
257+
func (s *AccessAPISuite) testScriptExecutionAndGetAccountsAN2(targetHeight uint64) {
226258
// Run tests against Access 2, which uses local storage
227259
s.testGetAccount(s.an2Client)
228260
s.testExecuteScriptWithSimpleScript(s.an2Client)
229261
s.testExecuteScriptWithSimpleContract(s.an2Client, targetHeight)
230262
}
231263

232-
func (s *AccessAPISuite) TestMVPScriptExecutionLocalStorage() {
264+
func (s *AccessAPISuite) testMVPScriptExecutionLocalStorage() {
233265
// this is a specialized test that creates accounts, deposits funds, deploys contracts, etc, and
234266
// uses the provided access node to handle the Access API calls. there is an existing test that
235267
// covers the default config, so we only need to test with local storage.
236268
mvp.RunMVPTest(s.T(), s.ctx, s.net, s.accessNode2)
237269
}
238270

239-
// TestSendAndSubscribeTransactionStatuses tests the functionality of sending and subscribing to transaction statuses.
271+
// testSendAndSubscribeTransactionStatuses tests the functionality of sending and subscribing to transaction statuses.
240272
//
241273
// This test verifies that a transaction can be created, signed, sent to the access API, and then the status of the transaction
242274
// can be subscribed to. It performs the following steps:
@@ -245,7 +277,7 @@ func (s *AccessAPISuite) TestMVPScriptExecutionLocalStorage() {
245277
// 3. Signs the transaction.
246278
// 4. Sends and subscribes to the transaction status using the access API.
247279
// 5. Verifies the received transaction statuses, ensuring they are received in order and the final status is "SEALED".
248-
func (s *AccessAPISuite) TestSendAndSubscribeTransactionStatuses() {
280+
func (s *AccessAPISuite) testSendAndSubscribeTransactionStatuses() {
249281
accessNodeContainer := s.net.ContainerByName(testnet.PrimaryAN)
250282

251283
// Establish a gRPC connection to the access API
@@ -350,11 +382,20 @@ func (s *AccessAPISuite) TestSendAndSubscribeTransactionStatuses() {
350382

351383
// Check, if the final transaction status is sealed.
352384
s.Assert().Equal(entities.TransactionStatus_SEALED, lastReportedTxStatus)
385+
386+
// Refresh the suite's service client to sync sequence number.
387+
// This test created a fresh local serviceClient and submitted a transaction,
388+
// which incremented the on-chain sequence number. The suite's s.serviceClient
389+
// still has the old cached sequence number, so we refresh it here.
390+
s.Require().Eventually(func() bool {
391+
s.serviceClient, err = s.accessNode2.TestnetClient()
392+
return err == nil
393+
}, 30*time.Second, 1*time.Second)
353394
}
354395

355-
// TestContractUpdate tests that the Access API can index contract updates, and that the program cache
396+
// testContractUpdate tests that the Access API can index contract updates, and that the program cache
356397
// is invalidated when a contract is updated.
357-
func (s *AccessAPISuite) TestContractUpdate() {
398+
func (s *AccessAPISuite) testContractUpdate() {
358399
txResult := s.deployContract(OriginalContract, false)
359400
targetHeight := txResult.BlockHeight + 1
360401
s.waitUntilIndexed(targetHeight)
@@ -610,9 +651,9 @@ func convertToMessageSigWithExtensionData(sigs []sdk.TransactionSignature, exten
610651
return msgSigs
611652
}
612653

613-
// TestTransactionSignaturePlainExtensionData tests that the Access API properly handles the ExtensionData field
654+
// testTransactionSignaturePlainExtensionData tests that the Access API properly handles the ExtensionData field
614655
// in transaction signatures for different authentication schemes.
615-
func (s *AccessAPISuite) TestTransactionSignaturePlainExtensionData() {
656+
func (s *AccessAPISuite) testTransactionSignaturePlainExtensionData() {
616657
accessNodeContainer := s.net.ContainerByName(testnet.PrimaryAN)
617658

618659
// Establish a gRPC connection to the access API
@@ -757,8 +798,8 @@ func (s *AccessAPISuite) TestTransactionSignaturePlainExtensionData() {
757798
}
758799
}
759800

760-
// TestTransactionSignatureWebAuthnExtensionData tests the WebAuthn authentication scheme with properly constructed extension data.
761-
func (s *AccessAPISuite) TestTransactionSignatureWebAuthnExtensionData() {
801+
// testTransactionSignatureWebAuthnExtensionData tests the WebAuthn authentication scheme with properly constructed extension data.
802+
func (s *AccessAPISuite) testTransactionSignatureWebAuthnExtensionData() {
762803
accessNodeContainer := s.net.ContainerByName(testnet.PrimaryAN)
763804

764805
// Establish a gRPC connection to the access API
@@ -920,9 +961,9 @@ func (s *AccessAPISuite) TestTransactionSignatureWebAuthnExtensionData() {
920961
}
921962
}
922963

923-
// TestExtensionDataPreservation tests that the ExtensionData field is properly preserved
964+
// testExtensionDataPreservation tests that the ExtensionData field is properly preserved
924965
// when transactions are submitted and retrieved through the Access API.
925-
func (s *AccessAPISuite) TestExtensionDataPreservation() {
966+
func (s *AccessAPISuite) testExtensionDataPreservation() {
926967
accessNodeContainer := s.net.ContainerByName(testnet.PrimaryAN)
927968

928969
// Establish a gRPC connection to the access API
@@ -1063,9 +1104,9 @@ func (s *AccessAPISuite) TestExtensionDataPreservation() {
10631104
}
10641105
}
10651106

1066-
// TestInvalidTransactionSignature tests that the access API performs sanity checks
1107+
// testRejectedInvalidSignatureFormat tests that the access API performs sanity checks
10671108
// on the transaction signature format and rejects invalid formats
1068-
func (s *AccessAPISuite) TestRejectedInvalidSignatureFormat() {
1109+
func (s *AccessAPISuite) testRejectedInvalidSignatureFormat() {
10691110
accessNodeContainer := s.net.ContainerByName(testnet.PrimaryAN)
10701111

10711112
// Establish a gRPC connection to the access API

integration/tests/access/cohort2/observer_indexer_enabled_test.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ type ObserverIndexerEnabledSuite struct {
4444
ObserverSuite
4545
}
4646

47+
func (s *ObserverIndexerEnabledSuite) TestObserverIndexerEnabled() {
48+
s.T().Run("Observer indexed RPCs happy path", s.testObserverIndexedRPCsHappyPath)
49+
s.T().Run("All observer indexed RPCs happy path", s.testAllObserverIndexedRPCsHappyPath)
50+
}
51+
4752
// SetupTest sets up the test suite by starting the network and preparing the observers client.
4853
// By overriding this function, we can ensure that the observers are started with correct parameters and select
4954
// the RPCs and REST endpoints that are tested.
@@ -141,17 +146,15 @@ func (s *ObserverIndexerEnabledSuite) SetupTest() {
141146
s.net.Start(ctx)
142147
}
143148

144-
// TestObserverIndexedRPCsHappyPath tests RPCs that are handled by the observer by using a dedicated indexer for the events.
149+
// testObserverIndexedRPCsHappyPath tests RPCs that are handled by the observer by using a dedicated indexer for the events.
145150
// To ensure that the observer is handling these RPCs, we stop the upstream access node and verify that the observer client
146151
// returns success for valid requests and errors for invalid ones.
147-
func (s *ObserverIndexerEnabledSuite) TestObserverIndexedRPCsHappyPath() {
148-
unittest.SkipUnless(s.T(), unittest.TEST_FLAKY, "flaky")
152+
func (s *ObserverIndexerEnabledSuite) testObserverIndexedRPCsHappyPath(t *testing.T) {
153+
unittest.SkipUnless(t, unittest.TEST_FLAKY, "flaky")
149154

150155
ctx, cancel := context.WithCancel(context.Background())
151156
defer cancel()
152157

153-
t := s.T()
154-
155158
// prepare environment to create a new account
156159
serviceAccountClient, err := s.net.ContainerByName(testnet.PrimaryAN).TestnetClient()
157160
require.NoError(t, err)
@@ -271,7 +274,7 @@ func (s *ObserverIndexerEnabledSuite) TestObserverIndexedRPCsHappyPath() {
271274
require.True(t, found)
272275
}
273276

274-
// TestAllObserverIndexedRPCsHappyPath tests the observer with the indexer enabled,
277+
// testAllObserverIndexedRPCsHappyPath tests the observer with the indexer enabled,
275278
// observer configured to proxy requests to an access node and access node itself. All responses are compared
276279
// to ensure all of the endpoints are working as expected.
277280
// For now the observer only supports the following RPCs:
@@ -288,12 +291,10 @@ func (s *ObserverIndexerEnabledSuite) TestObserverIndexedRPCsHappyPath() {
288291
// -GetTransaction
289292
// -GetTransactionResult
290293
// -GetTransactionResultByIndex
291-
func (s *ObserverIndexerEnabledSuite) TestAllObserverIndexedRPCsHappyPath() {
294+
func (s *ObserverIndexerEnabledSuite) testAllObserverIndexedRPCsHappyPath(t *testing.T) {
292295
ctx, cancel := context.WithCancel(context.Background())
293296
defer cancel()
294297

295-
t := s.T()
296-
297298
// prepare environment to create a new account
298299
serviceAccountClient, err := s.net.ContainerByName(testnet.PrimaryAN).TestnetClient()
299300
require.NoError(t, err)

integration/tests/access/cohort3/access_circuit_breaker_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ func (s *AccessCircuitBreakerSuite) TearDownTest() {
4949
s.log.Info().Msg("================> Finish TearDownTest")
5050
}
5151

52+
// SetupTest initializes the test suite with a minimal network configuration for circuit breaker testing.
53+
//
54+
// Network Configuration:
55+
// - 1 Access node with circuit breaker enabled (max-requests=1, max-failures=1, restore-timeout=6s, request-timeout=1.5s)
56+
// - 1 Execution node (standard configuration)
57+
// - 1 Verification node (ghost - lightweight, unused)
58+
// - 1 Collection node (controllable, with 100ms proposal duration)
59+
// - 3 Consensus nodes (ghosts - lightweight, unused)
60+
//
61+
// The access node is configured with aggressive circuit breaker settings to allow testing the breaker's
62+
// open/close behavior within a short test timeframe. The collection node can be disconnected to trigger
63+
// circuit breaker activation.
5264
func (s *AccessCircuitBreakerSuite) SetupTest() {
5365
s.log = unittest.LoggerForTest(s.Suite.T(), zerolog.InfoLevel)
5466
s.log.Info().Msg("================> SetupTest")

integration/tests/access/cohort3/collection_indexing_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ type CollectionIndexingSuite struct {
2828
cancel context.CancelFunc
2929
}
3030

31+
// SetupTest initializes the test suite with a network configuration for testing collection indexing.
32+
//
33+
// Network Configuration:
34+
// - 2 Access nodes with different collection indexing strategies:
35+
// - access_1: Uses ingestion engine for collection indexing (execution-data-sync-enabled=true, NO indexer)
36+
// - access_2: Uses execution data indexer for collection indexing (execution-data-indexing-enabled=true)
37+
// - 2 Collection nodes (standard configuration)
38+
// - 2 Execution nodes (standard configuration)
39+
// - 3 Consensus nodes (standard configuration)
40+
// - 1 Verification node (standard configuration)
41+
//
42+
// This setup allows testing that both collection indexing approaches (ingestion engine vs dedicated indexer)
43+
// work correctly. The test verifies that access_2 can catch up on collections by syncing from the indexer
44+
// even when collection nodes are stopped.
3145
func (s *CollectionIndexingSuite) SetupTest() {
3246
// access_1 is not running the indexer, so all collections are indexed using the ingestion engine
3347
defaultAccessOpts := []func(config *testnet.NodeConfig){

integration/tests/access/cohort3/consensus_follower_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ func (s *ConsensusFollowerSuite) TearDownTest() {
4949
s.log.Info().Msgf("================> Finish TearDownTest")
5050
}
5151

52+
// SetupTest initializes the test suite with a network configuration for testing consensus followers.
53+
//
54+
// Network Configuration:
55+
// - 1 Staked Access node (supports-observer=true) that consensus followers connect to
56+
// - 1 Standard Access node (standard configuration)
57+
// - 2 Collection nodes (ghosts - lightweight, unused)
58+
// - 3 Consensus nodes (with custom timing: 100ms proposal duration, reduced seal approvals)
59+
// - 2 Consensus Followers (unstaked nodes with generated networking keys)
60+
// - 2 Execution nodes (standard configuration)
61+
// - 1 Verification node (standard configuration)
62+
//
63+
// The staked access node acts as the entry point for consensus followers. The two consensus followers
64+
// are configured to follow the chain through this staked node, allowing testing of chain following
65+
// and catch-up behavior.
5266
func (s *ConsensusFollowerSuite) SetupTest() {
5367
s.log = unittest.LoggerForTest(s.Suite.T(), zerolog.InfoLevel)
5468
s.log.Info().Msg("================> SetupTest")

integration/tests/access/cohort3/execution_state_sync_test.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ type ExecutionStateSyncSuite struct {
5252
executionDataDBMode execution_data.ExecutionDataDBMode
5353
}
5454

55+
// SetupTest initializes the test suite with a network configuration for testing execution state sync.
56+
//
57+
// Network Configuration:
58+
// - 1 Bridge Access node (supports-observer=true, execution-data-sync-enabled, public-network-sync-enabled, Pebble DB)
59+
// - 1 Ghost Access node (lightweight, for tracking block state)
60+
// - 1 Observer node (execution-data-sync-enabled, execution-data-indexing-enabled, event-query-mode=execution-nodes-only)
61+
// - 2 Collection nodes (standard configuration)
62+
// - 2 Execution nodes (standard configuration)
63+
// - 3 Consensus nodes (with custom timing: 100ms proposal duration, reduced seal approvals)
64+
// - 1 Verification node (standard configuration)
65+
//
66+
// The bridge access node and observer both sync execution data from execution nodes and verify that
67+
// execution state is properly synced and can be retrieved. Uses Pebble DB as the execution data store.
5568
func (s *ExecutionStateSyncSuite) SetupTest() {
5669
s.setup(execution_data.ExecutionDataDBModePebble)
5770
}
@@ -143,9 +156,9 @@ func (s *ExecutionStateSyncSuite) buildNetworkConfig() {
143156
s.net = testnet.PrepareFlowNetwork(s.T(), conf, flow.Localnet)
144157
}
145158

146-
// TestBadgerDBHappyPath tests that Execution Nodes generate execution data, and Access Nodes are able to
159+
// TestPebbleDBHappyPath tests that Execution Nodes generate execution data, and Access Nodes are able to
147160
// successfully sync the data to badger DB
148-
func (s *ExecutionStateSyncSuite) TestBadgerDBHappyPath() {
161+
func (s *ExecutionStateSyncSuite) TestPebbleDBHappyPath() {
149162
s.executionStateSyncTest()
150163
}
151164

integration/tests/access/cohort3/pebble_execution_state_sync_test.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)