Skip to content

Commit b74eedb

Browse files
Ehsan-saradarclaude
andcommitted
test(state): exercise accessors through the public API
Move accessors_test.go to package state_test so it compiles against the exported accessors only, instead of reaching into unexported internals (stateDB.disk, newTestStateDB). Contract/class tests now write through a plain memory store, and history tests build a StateDB/StateReader via the exported constructors. Drop the "wraps the stored contract on success" case from TestGetStateObject: it only asserted, via unexported fields, that the constructor copied its inputs (a tautological test). The not-found case, which is the actual behavior of GetStateObject, is kept. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b2230fa commit b74eedb

1 file changed

Lines changed: 68 additions & 79 deletions

File tree

core/state/accessors_test.go

Lines changed: 68 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
package state
1+
package state_test
22

33
import (
44
"testing"
55

66
"github.com/NethermindEth/juno/core"
77
"github.com/NethermindEth/juno/core/felt"
8+
"github.com/NethermindEth/juno/core/state"
9+
"github.com/NethermindEth/juno/core/trie2/triedb"
810
"github.com/NethermindEth/juno/db"
11+
"github.com/NethermindEth/juno/db/memory"
12+
_ "github.com/NethermindEth/juno/encoder/registry"
913
"github.com/stretchr/testify/assert"
1014
"github.com/stretchr/testify/require"
1115
)
@@ -14,65 +18,65 @@ func TestContractAccessors(t *testing.T) {
1418
addr := felt.NewUnsafeFromString[felt.Felt]("0x123")
1519

1620
// 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) {
21+
storeContract := func(t *testing.T, disk db.KeyValueWriter, nonce, classHash string, height uint64) {
1822
t.Helper()
19-
require.NoError(t, WriteContract(
20-
stateDB.disk, addr,
23+
require.NoError(t, state.WriteContract(
24+
disk, addr,
2125
felt.UnsafeFromString[felt.Felt](nonce),
2226
felt.UnsafeFromString[felt.Felt](classHash),
2327
height,
2428
))
2529
}
2630

2731
t.Run("absent before write", func(t *testing.T) {
28-
stateDB := newTestStateDB()
32+
disk := memory.New()
2933

30-
exists, err := HasContract(stateDB.disk, addr)
34+
exists, err := state.HasContract(disk, addr)
3135
require.NoError(t, err)
3236
assert.False(t, exists)
3337

34-
_, err = GetContract(stateDB.disk, addr)
38+
_, err = state.GetContract(disk, addr)
3539
assert.ErrorIs(t, err, db.ErrKeyNotFound)
3640
})
3741

3842
t.Run("write then read round-trip", func(t *testing.T) {
39-
stateDB := newTestStateDB()
40-
storeContract(t, stateDB, "0x1", "0xabc", 42)
43+
disk := memory.New()
44+
storeContract(t, disk, "0x1", "0xabc", 42)
4145

42-
exists, err := HasContract(stateDB.disk, addr)
46+
exists, err := state.HasContract(disk, addr)
4347
require.NoError(t, err)
4448
assert.True(t, exists)
4549

46-
contract, err := GetContract(stateDB.disk, addr)
50+
contract, err := state.GetContract(disk, addr)
4751
require.NoError(t, err)
4852
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0x1"), contract.Nonce)
4953
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0xabc"), contract.ClassHash)
5054
assert.Equal(t, uint64(42), contract.DeployedHeight)
5155
})
5256

5357
t.Run("overwrite reflects latest values", func(t *testing.T) {
54-
stateDB := newTestStateDB()
55-
storeContract(t, stateDB, "0x1", "0xabc", 42)
56-
storeContract(t, stateDB, "0x2", "0xdef", 99)
58+
disk := memory.New()
59+
storeContract(t, disk, "0x1", "0xabc", 42)
60+
storeContract(t, disk, "0x2", "0xdef", 99)
5761

58-
contract, err := GetContract(stateDB.disk, addr)
62+
contract, err := state.GetContract(disk, addr)
5963
require.NoError(t, err)
6064
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0x2"), contract.Nonce)
6165
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0xdef"), contract.ClassHash)
6266
assert.Equal(t, uint64(99), contract.DeployedHeight)
6367
})
6468

6569
t.Run("delete removes the contract", func(t *testing.T) {
66-
stateDB := newTestStateDB()
67-
storeContract(t, stateDB, "0x1", "0xabc", 42)
70+
disk := memory.New()
71+
storeContract(t, disk, "0x1", "0xabc", 42)
6872

69-
require.NoError(t, DeleteContract(stateDB.disk, addr))
73+
require.NoError(t, state.DeleteContract(disk, addr))
7074

71-
exists, err := HasContract(stateDB.disk, addr)
75+
exists, err := state.HasContract(disk, addr)
7276
require.NoError(t, err)
7377
assert.False(t, exists)
7478

75-
_, err = GetContract(stateDB.disk, addr)
79+
_, err = state.GetContract(disk, addr)
7680
assert.ErrorIs(t, err, db.ErrKeyNotFound)
7781
})
7882
}
@@ -90,26 +94,26 @@ func TestClassAccessors(t *testing.T) {
9094
}
9195

9296
t.Run("absent before write", func(t *testing.T) {
93-
stateDB := newTestStateDB()
97+
disk := memory.New()
9498

95-
exists, err := HasClass(stateDB.disk, classHash)
99+
exists, err := state.HasClass(disk, classHash)
96100
require.NoError(t, err)
97101
assert.False(t, exists)
98102

99-
_, err = GetClass(stateDB.disk, classHash)
103+
_, err = state.GetClass(disk, classHash)
100104
assert.ErrorIs(t, err, db.ErrKeyNotFound)
101105
})
102106

103107
t.Run("write then read round-trips the encoded class", func(t *testing.T) {
104-
stateDB := newTestStateDB()
108+
disk := memory.New()
105109
class := newClass()
106-
require.NoError(t, WriteClass(stateDB.disk, classHash, class))
110+
require.NoError(t, state.WriteClass(disk, classHash, class))
107111

108-
exists, err := HasClass(stateDB.disk, classHash)
112+
exists, err := state.HasClass(disk, classHash)
109113
require.NoError(t, err)
110114
assert.True(t, exists)
111115

112-
got, err := GetClass(stateDB.disk, classHash)
116+
got, err := state.GetClass(disk, classHash)
113117
require.NoError(t, err)
114118
assert.Equal(t, class.At, got.At)
115119
sierra, ok := got.Class.(*core.SierraClass)
@@ -119,16 +123,16 @@ func TestClassAccessors(t *testing.T) {
119123
})
120124

121125
t.Run("delete removes the class", func(t *testing.T) {
122-
stateDB := newTestStateDB()
123-
require.NoError(t, WriteClass(stateDB.disk, classHash, newClass()))
126+
disk := memory.New()
127+
require.NoError(t, state.WriteClass(disk, classHash, newClass()))
124128

125-
require.NoError(t, DeleteClass(stateDB.disk, classHash))
129+
require.NoError(t, state.DeleteClass(disk, classHash))
126130

127-
exists, err := HasClass(stateDB.disk, classHash)
131+
exists, err := state.HasClass(disk, classHash)
128132
require.NoError(t, err)
129133
assert.False(t, exists)
130134

131-
_, err = GetClass(stateDB.disk, classHash)
135+
_, err = state.GetClass(disk, classHash)
132136
assert.ErrorIs(t, err, db.ErrKeyNotFound)
133137
})
134138
}
@@ -143,7 +147,7 @@ func TestHistoryAccessors(t *testing.T) {
143147
name string
144148
write func(w db.KeyValueWriter, blockNum uint64, value *felt.Felt) error
145149
del func(w db.KeyValueWriter, blockNum uint64) error
146-
readAt func(r *StateReader, blockNum uint64) (felt.Felt, error)
150+
readAt func(r *state.StateReader, blockNum uint64) (felt.Felt, error)
147151
valueOne *felt.Felt
148152
valueTwo *felt.Felt
149153
}
@@ -152,12 +156,12 @@ func TestHistoryAccessors(t *testing.T) {
152156
{
153157
name: "nonce",
154158
write: func(w db.KeyValueWriter, blockNum uint64, value *felt.Felt) error {
155-
return WriteNonceHistory(w, addr, blockNum, value)
159+
return state.WriteNonceHistory(w, addr, blockNum, value)
156160
},
157161
del: func(w db.KeyValueWriter, blockNum uint64) error {
158-
return DeleteNonceHistory(w, addr, blockNum)
162+
return state.DeleteNonceHistory(w, addr, blockNum)
159163
},
160-
readAt: func(r *StateReader, blockNum uint64) (felt.Felt, error) {
164+
readAt: func(r *state.StateReader, blockNum uint64) (felt.Felt, error) {
161165
return r.ContractNonceAt(addr, blockNum)
162166
},
163167
valueOne: felt.NewUnsafeFromString[felt.Felt]("0x7"),
@@ -166,12 +170,12 @@ func TestHistoryAccessors(t *testing.T) {
166170
{
167171
name: "class hash",
168172
write: func(w db.KeyValueWriter, blockNum uint64, value *felt.Felt) error {
169-
return WriteClassHashHistory(w, addr, blockNum, value)
173+
return state.WriteClassHashHistory(w, addr, blockNum, value)
170174
},
171175
del: func(w db.KeyValueWriter, blockNum uint64) error {
172-
return DeleteClassHashHistory(w, addr, blockNum)
176+
return state.DeleteClassHashHistory(w, addr, blockNum)
173177
},
174-
readAt: func(r *StateReader, blockNum uint64) (felt.Felt, error) {
178+
readAt: func(r *state.StateReader, blockNum uint64) (felt.Felt, error) {
175179
return r.ContractClassHashAt(addr, blockNum)
176180
},
177181
valueOne: felt.NewUnsafeFromString[felt.Felt]("0xaaa"),
@@ -180,12 +184,12 @@ func TestHistoryAccessors(t *testing.T) {
180184
{
181185
name: "storage",
182186
write: func(w db.KeyValueWriter, blockNum uint64, value *felt.Felt) error {
183-
return WriteStorageHistory(w, addr, storageKey, blockNum, value)
187+
return state.WriteStorageHistory(w, addr, storageKey, blockNum, value)
184188
},
185189
del: func(w db.KeyValueWriter, blockNum uint64) error {
186-
return DeleteStorageHistory(w, addr, storageKey, blockNum)
190+
return state.DeleteStorageHistory(w, addr, storageKey, blockNum)
187191
},
188-
readAt: func(r *StateReader, blockNum uint64) (felt.Felt, error) {
192+
readAt: func(r *state.StateReader, blockNum uint64) (felt.Felt, error) {
189193
return r.ContractStorageAt(addr, storageKey, blockNum)
190194
},
191195
valueOne: felt.NewUnsafeFromString[felt.Felt]("0xdef"),
@@ -197,47 +201,48 @@ func TestHistoryAccessors(t *testing.T) {
197201

198202
for _, k := range kinds {
199203
t.Run(k.name, func(t *testing.T) {
200-
// newReader returns a fresh state and a reader over it, so each subtest
204+
// newReader returns a fresh disk store and a reader over it, so each subtest
201205
// starts from an empty history and is independent of execution order.
202-
newReader := func(t *testing.T) (*StateDB, *StateReader) {
206+
newReader := func(t *testing.T) (db.KeyValueStore, *state.StateReader) {
203207
t.Helper()
204-
stateDB := newTestStateDB()
205-
reader, err := NewStateReader(&felt.Zero, stateDB)
208+
disk := memory.New()
209+
stateDB := state.NewStateDB(disk, triedb.New(disk, nil))
210+
reader, err := state.NewStateReader(&felt.Zero, stateDB)
206211
require.NoError(t, err)
207-
return stateDB, reader
212+
return disk, reader
208213
}
209214

210215
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))
216+
disk, reader := newReader(t)
217+
require.NoError(t, k.write(disk, blockOne, k.valueOne))
213218

214219
got, err := k.readAt(reader, blockOne)
215220
require.NoError(t, err)
216221
assert.Equal(t, *k.valueOne, got)
217222
})
218223

219224
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))
225+
disk, reader := newReader(t)
226+
require.NoError(t, k.write(disk, blockOne, k.valueOne))
222227

223228
got, err := k.readAt(reader, blockOne+3)
224229
require.NoError(t, err)
225230
assert.Equal(t, *k.valueOne, got)
226231
})
227232

228233
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))
234+
disk, reader := newReader(t)
235+
require.NoError(t, k.write(disk, blockOne, k.valueOne))
231236

232237
got, err := k.readAt(reader, blockOne-1)
233238
require.NoError(t, err)
234239
assert.Equal(t, felt.Zero, got)
235240
})
236241

237242
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))
240-
require.NoError(t, k.write(stateDB.disk, blockTwo, k.valueTwo))
243+
disk, reader := newReader(t)
244+
require.NoError(t, k.write(disk, blockOne, k.valueOne))
245+
require.NoError(t, k.write(disk, blockTwo, k.valueTwo))
241246

242247
between, err := k.readAt(reader, blockTwo-1)
243248
require.NoError(t, err)
@@ -249,12 +254,12 @@ func TestHistoryAccessors(t *testing.T) {
249254
})
250255

251256
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))
257+
disk, reader := newReader(t)
258+
require.NoError(t, k.write(disk, blockOne, k.valueOne))
259+
require.NoError(t, k.write(disk, blockTwo, k.valueTwo))
255260

256-
require.NoError(t, k.del(stateDB.disk, blockOne))
257-
require.NoError(t, k.del(stateDB.disk, blockTwo))
261+
require.NoError(t, k.del(disk, blockOne))
262+
require.NoError(t, k.del(disk, blockTwo))
258263

259264
got, err := k.readAt(reader, blockTwo+1)
260265
require.NoError(t, err)
@@ -268,25 +273,9 @@ func TestGetStateObject(t *testing.T) {
268273
addr := felt.NewUnsafeFromString[felt.Felt]("0x123")
269274

270275
t.Run("propagates not-found for a missing contract", func(t *testing.T) {
271-
stateDB := newTestStateDB()
276+
disk := memory.New()
272277

273-
_, err := GetStateObject(stateDB.disk, nil, addr)
278+
_, err := state.GetStateObject(disk, nil, addr)
274279
assert.ErrorIs(t, err, db.ErrKeyNotFound)
275280
})
276-
277-
t.Run("wraps the stored contract on success", func(t *testing.T) {
278-
stateDB := newTestStateDB()
279-
require.NoError(t, WriteContract(stateDB.disk, addr,
280-
felt.UnsafeFromString[felt.Felt]("0x1"),
281-
felt.UnsafeFromString[felt.Felt]("0xabc"),
282-
42,
283-
))
284-
285-
obj, err := GetStateObject(stateDB.disk, nil, addr)
286-
require.NoError(t, err)
287-
assert.Equal(t, *addr, obj.addr)
288-
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0x1"), obj.contract.Nonce)
289-
assert.Equal(t, felt.UnsafeFromString[felt.Felt]("0xabc"), obj.contract.ClassHash)
290-
assert.Equal(t, uint64(42), obj.contract.DeployedHeight)
291-
})
292281
}

0 commit comments

Comments
 (0)