Skip to content

Commit c13deef

Browse files
Ehsan-saradarclaude
andcommitted
test(state): make accessor subtests order-independent
Give each subtest its own StateDB (and StateReader for history) so they no longer share mutable state or depend on execution order. Rename the contract-writing helper to storeContract to avoid shadowing the package-level writeContract function. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f355c21 commit c13deef

1 file changed

Lines changed: 63 additions & 26 deletions

File tree

core/state/accessors_test.go

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,22 @@ import (
1111
)
1212

1313
func TestContractAccessors(t *testing.T) {
14-
stateDB := newTestStateDB()
1514
addr := felt.NewUnsafeFromString[felt.Felt]("0x123")
1615

16+
// storeContract stores a contract with the given values and fails the test on error.
17+
storeContract := func(t *testing.T, stateDB *StateDB, nonce, classHash string, height uint64) {
18+
t.Helper()
19+
require.NoError(t, WriteContract(
20+
stateDB.disk, addr,
21+
felt.UnsafeFromString[felt.Felt](nonce),
22+
felt.UnsafeFromString[felt.Felt](classHash),
23+
height,
24+
))
25+
}
26+
1727
t.Run("absent before write", func(t *testing.T) {
28+
stateDB := newTestStateDB()
29+
1830
exists, err := HasContract(stateDB.disk, addr)
1931
require.NoError(t, err)
2032
assert.False(t, exists)
@@ -24,12 +36,8 @@ func TestContractAccessors(t *testing.T) {
2436
})
2537

2638
t.Run("write then read round-trip", func(t *testing.T) {
27-
require.NoError(t, WriteContract(
28-
stateDB.disk, addr,
29-
felt.UnsafeFromString[felt.Felt]("0x1"), // nonce
30-
felt.UnsafeFromString[felt.Felt]("0xabc"), // classHash
31-
42, // deployHeight
32-
))
39+
stateDB := newTestStateDB()
40+
storeContract(t, stateDB, "0x1", "0xabc", 42)
3341

3442
exists, err := HasContract(stateDB.disk, addr)
3543
require.NoError(t, err)
@@ -43,12 +51,9 @@ func TestContractAccessors(t *testing.T) {
4351
})
4452

4553
t.Run("overwrite reflects latest values", func(t *testing.T) {
46-
require.NoError(t, WriteContract(
47-
stateDB.disk, addr,
48-
felt.UnsafeFromString[felt.Felt]("0x2"),
49-
felt.UnsafeFromString[felt.Felt]("0xdef"),
50-
99,
51-
))
54+
stateDB := newTestStateDB()
55+
storeContract(t, stateDB, "0x1", "0xabc", 42)
56+
storeContract(t, stateDB, "0x2", "0xdef", 99)
5257

5358
contract, err := GetContract(stateDB.disk, addr)
5459
require.NoError(t, err)
@@ -58,6 +63,9 @@ func TestContractAccessors(t *testing.T) {
5863
})
5964

6065
t.Run("delete removes the contract", func(t *testing.T) {
66+
stateDB := newTestStateDB()
67+
storeContract(t, stateDB, "0x1", "0xabc", 42)
68+
6169
require.NoError(t, DeleteContract(stateDB.disk, addr))
6270

6371
exists, err := HasContract(stateDB.disk, addr)
@@ -70,17 +78,20 @@ func TestContractAccessors(t *testing.T) {
7078
}
7179

7280
func TestClassAccessors(t *testing.T) {
73-
stateDB := newTestStateDB()
7481
classHash := felt.NewUnsafeFromString[felt.Felt]("0xabc")
75-
class := &core.DeclaredClassDefinition{
76-
At: 12,
77-
Class: &core.SierraClass{
78-
SemanticVersion: "0.1.0",
79-
Program: []*felt.Felt{felt.NewUnsafeFromString[felt.Felt]("0x1")},
80-
},
82+
newClass := func() *core.DeclaredClassDefinition {
83+
return &core.DeclaredClassDefinition{
84+
At: 12,
85+
Class: &core.SierraClass{
86+
SemanticVersion: "0.1.0",
87+
Program: []*felt.Felt{felt.NewUnsafeFromString[felt.Felt]("0x1")},
88+
},
89+
}
8190
}
8291

8392
t.Run("absent before write", func(t *testing.T) {
93+
stateDB := newTestStateDB()
94+
8495
exists, err := HasClass(stateDB.disk, classHash)
8596
require.NoError(t, err)
8697
assert.False(t, exists)
@@ -90,6 +101,8 @@ func TestClassAccessors(t *testing.T) {
90101
})
91102

92103
t.Run("write then read round-trips the encoded class", func(t *testing.T) {
104+
stateDB := newTestStateDB()
105+
class := newClass()
93106
require.NoError(t, WriteClass(stateDB.disk, classHash, class))
94107

95108
exists, err := HasClass(stateDB.disk, classHash)
@@ -106,6 +119,9 @@ func TestClassAccessors(t *testing.T) {
106119
})
107120

108121
t.Run("delete removes the class", func(t *testing.T) {
122+
stateDB := newTestStateDB()
123+
require.NoError(t, WriteClass(stateDB.disk, classHash, newClass()))
124+
109125
require.NoError(t, DeleteClass(stateDB.disk, classHash))
110126

111127
exists, err := HasClass(stateDB.disk, classHash)
@@ -181,31 +197,46 @@ func TestHistoryAccessors(t *testing.T) {
181197

182198
for _, k := range kinds {
183199
t.Run(k.name, func(t *testing.T) {
184-
stateDB := newTestStateDB()
185-
reader, err := NewStateReader(&felt.Zero, stateDB)
186-
require.NoError(t, err)
187-
188-
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
200+
// newReader returns a fresh state and a reader over it, so each subtest
201+
// starts from an empty history and is independent of execution order.
202+
newReader := func(t *testing.T) (*StateDB, *StateReader) {
203+
t.Helper()
204+
stateDB := newTestStateDB()
205+
reader, err := NewStateReader(&felt.Zero, stateDB)
206+
require.NoError(t, err)
207+
return stateDB, reader
208+
}
189209

190210
t.Run("reads the written value at its block", func(t *testing.T) {
211+
stateDB, reader := newReader(t)
212+
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
213+
191214
got, err := k.readAt(reader, blockOne)
192215
require.NoError(t, err)
193216
assert.Equal(t, *k.valueOne, got)
194217
})
195218

196219
t.Run("steps back to the last entry for a later block", func(t *testing.T) {
220+
stateDB, reader := newReader(t)
221+
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
222+
197223
got, err := k.readAt(reader, blockOne+3)
198224
require.NoError(t, err)
199225
assert.Equal(t, *k.valueOne, got)
200226
})
201227

202228
t.Run("reads zero before the first entry", func(t *testing.T) {
229+
stateDB, reader := newReader(t)
230+
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
231+
203232
got, err := k.readAt(reader, blockOne-1)
204233
require.NoError(t, err)
205234
assert.Equal(t, felt.Zero, got)
206235
})
207236

208237
t.Run("honours block boundaries across two entries", func(t *testing.T) {
238+
stateDB, reader := newReader(t)
239+
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
209240
require.NoError(t, k.write(stateDB.disk, blockTwo, k.valueTwo))
210241

211242
between, err := k.readAt(reader, blockTwo-1)
@@ -218,6 +249,10 @@ func TestHistoryAccessors(t *testing.T) {
218249
})
219250

220251
t.Run("delete drops the entry", func(t *testing.T) {
252+
stateDB, reader := newReader(t)
253+
require.NoError(t, k.write(stateDB.disk, blockOne, k.valueOne))
254+
require.NoError(t, k.write(stateDB.disk, blockTwo, k.valueTwo))
255+
221256
require.NoError(t, k.del(stateDB.disk, blockOne))
222257
require.NoError(t, k.del(stateDB.disk, blockTwo))
223258

@@ -230,15 +265,17 @@ func TestHistoryAccessors(t *testing.T) {
230265
}
231266

232267
func TestGetStateObject(t *testing.T) {
233-
stateDB := newTestStateDB()
234268
addr := felt.NewUnsafeFromString[felt.Felt]("0x123")
235269

236270
t.Run("propagates not-found for a missing contract", func(t *testing.T) {
271+
stateDB := newTestStateDB()
272+
237273
_, err := GetStateObject(stateDB.disk, nil, addr)
238274
assert.ErrorIs(t, err, db.ErrKeyNotFound)
239275
})
240276

241277
t.Run("wraps the stored contract on success", func(t *testing.T) {
278+
stateDB := newTestStateDB()
242279
require.NoError(t, WriteContract(stateDB.disk, addr,
243280
felt.UnsafeFromString[felt.Felt]("0x1"),
244281
felt.UnsafeFromString[felt.Felt]("0xabc"),

0 commit comments

Comments
 (0)