Skip to content

Commit 63797fa

Browse files
ecPablocursoragent
andcommitted
Speed up Solana integration tests by avoiding redundant container setup.
Use mock environments for precondition-only tests, fix nested subtest deadlocks in PreloadMCMS isolation, and reuse an existing chain in fund-mcm-pdas instead of spinning a second validator. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 7ea96db commit 63797fa

4 files changed

Lines changed: 79 additions & 11 deletions

File tree

legacy/pkg/family/solana/testutils/preload.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,35 @@ import (
1212
"github.com/smartcontractkit/cld-changesets/legacy/pkg/family/solana/solutils"
1313
)
1414

15-
// programIDMu serializes Solana integration tests that mutate global gobinding
16-
// program IDs via SetProgramID. solana-go bindings use process-wide state, so
17-
// parallel package tests otherwise race and fail with "Program is not deployed".
18-
var programIDMu sync.Mutex
15+
// solTestExclusive serializes top-level Solana integration tests that mutate global
16+
// gobinding program IDs via SetProgramID. solTestDepth allows nested subtests in
17+
// the same test to re-enter without deadlocking.
18+
var (
19+
solTestExclusive sync.Mutex
20+
solTestCountMu sync.Mutex
21+
solTestDepth int
22+
)
23+
24+
func acquireSolanaTestIsolation(t *testing.T) {
25+
t.Helper()
26+
27+
solTestCountMu.Lock()
28+
if solTestDepth == 0 {
29+
solTestExclusive.Lock()
30+
}
31+
solTestDepth++
32+
solTestCountMu.Unlock()
33+
34+
t.Cleanup(func() {
35+
solTestCountMu.Lock()
36+
solTestDepth--
37+
release := solTestDepth == 0
38+
solTestCountMu.Unlock()
39+
if release {
40+
solTestExclusive.Unlock()
41+
}
42+
})
43+
}
1944

2045
var (
2146
mcmsProgramsOnce sync.Once
@@ -59,8 +84,7 @@ func copyProgramIDs(src map[string]string) map[string]string {
5984
func PreloadMCMS(t *testing.T, selector uint64) (string, map[string]string, *cldf.AddressBookMap) {
6085
t.Helper()
6186

62-
programIDMu.Lock()
63-
t.Cleanup(programIDMu.Unlock)
87+
acquireSolanaTestIsolation(t)
6488

6589
programsPath, programIDs := sharedMCMSPrograms(t)
6690
ab := PreloadAddressBookWithMCMSPrograms(t, selector)

mcms/changesets/set-config/changeset_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ func TestChangeset_VerifyPreconditions(t *testing.T) {
176176
}
177177
}
178178

179-
//nolint:paralleltest // global mcm.SetProgramID state and shared Solana CTF container setup
180179
func TestChangeset_VerifyPreconditions_Solana(t *testing.T) {
180+
t.Parallel()
181+
181182
selector := chain_selectors.TEST_22222222222222222222222222222222222222222222.Selector
182-
rt := newSolanaRuntimeWithDeploy(t, selector)
183-
env := rt.Environment()
183+
env := newSolanaVerifyPreconditionsEnv(t, selector)
184184

185185
validCfg := cldftesthelpers.SingleGroupMCMS(t)
186186
validTargets := mcmsTargets(selector, validCfg, validCfg, validCfg)

mcms/changesets/set-config/helpers_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package setconfig_test
22

33
import (
4+
"context"
45
"crypto/ecdsa"
56
"testing"
67
"time"
78

9+
"github.com/Masterminds/semver/v3"
810
"github.com/ethereum/go-ethereum/common"
911
"github.com/stretchr/testify/require"
1012

13+
cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
1114
cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
15+
cldfsol "github.com/smartcontractkit/chainlink-deployments-framework/chain/solana"
1216
cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
17+
"github.com/smartcontractkit/chainlink-deployments-framework/datastore"
1318
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
1419
mcmscontracts "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/contracts/mcms"
1520
cldfproposalutils "github.com/smartcontractkit/chainlink-deployments-framework/engine/cld/mcms/proposalutils"
@@ -146,6 +151,42 @@ func evmMCMSChainState(t *testing.T, rt *runtime.Runtime, selector uint64) (*evm
146151
return mcmsState, chain
147152
}
148153

154+
// newSolanaVerifyPreconditionsEnv builds a mock Solana environment for VerifyPreconditions
155+
// only — no CTF container or on-chain deploy.
156+
func newSolanaVerifyPreconditionsEnv(t *testing.T, selector uint64) cldf.Environment {
157+
t.Helper()
158+
159+
ds := datastore.NewMemoryDataStore()
160+
version := semver.MustParse("1.0.0")
161+
for _, ref := range []struct {
162+
contractType cldf.ContractType
163+
address string
164+
}{
165+
{mcmscontracts.RBACTimelock, "timelock-address"},
166+
{mcmscontracts.ProposerManyChainMultisig, "proposer-address"},
167+
{mcmscontracts.CancellerManyChainMultisig, "canceller-address"},
168+
{mcmscontracts.BypasserManyChainMultisig, "bypasser-address"},
169+
} {
170+
require.NoError(t, ds.Addresses().Add(datastore.AddressRef{
171+
Address: ref.address,
172+
ChainSelector: selector,
173+
Type: datastore.ContractType(ref.contractType),
174+
Version: version,
175+
}))
176+
}
177+
178+
return cldf.Environment{
179+
Logger: logger.Test(t),
180+
DataStore: ds.Seal(),
181+
GetContext: func() context.Context {
182+
return t.Context()
183+
},
184+
BlockChains: cldf_chain.NewBlockChains(map[uint64]cldf_chain.BlockChain{
185+
selector: cldfsol.Chain{Selector: selector},
186+
}),
187+
}
188+
}
189+
149190
func newSolanaRuntimeWithDeploy(t *testing.T, selector uint64) *runtime.Runtime {
150191
t.Helper()
151192

mcms/solana/changesets/fund-mcm-pdas/changeset_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,11 @@ func TestChangeset(t *testing.T) {
138138
}
139139

140140
t.Run("mcms contracts not deployed", func(t *testing.T) {
141-
rt2 := testRuntime(t, selector2)
142-
env := configureFundMCMSignersEnv(t, rt2.Environment(), selector2, rpcWithBalance(t, 1_000), false)
141+
chain := rt1.Environment().BlockChains.SolanaChains()[selector1]
142+
chain.Client = rpcWithBalance(t, 1_000)
143+
env := cldf.Environment{DataStore: newMCMSDataStore(t, selector2, false)}
144+
env.BlockChains = cldf_chain.NewBlockChains(map[uint64]cldf_chain.BlockChain{selector2: chain})
145+
143146
err := cs.VerifyPreconditions(env, Config{
144147
FundingPerChain: map[uint64]FundingConfig{selector2: {
145148
ProposeMCM: 100,

0 commit comments

Comments
 (0)