66 "encoding/binary"
77 "encoding/hex"
88 "math/rand/v2"
9+ "runtime"
910 "testing"
1011
1112 "lukechampine.com/blake3"
@@ -48,9 +49,8 @@ func testFullTree(t *testing.T, newStorage func(t *testing.T) Storage) {
4849 fatalIfErr (t , tree .Insert (t .Context (), label , value ))
4950 }
5051
51- root , err := store . Load (t .Context (), RootLabel )
52+ rootHash , err := tree . RootHash (t .Context ())
5253 fatalIfErr (t , err )
53- rootHash := root .Hash
5454
5555 store = newStorage (t )
5656 fatalIfErr (t , InitStorage (t .Context (), blake3 .Sum256 , store ))
@@ -63,10 +63,10 @@ func testFullTree(t *testing.T, newStorage func(t *testing.T) Storage) {
6363 fatalIfErr (t , tree .Insert (t .Context (), label , value ))
6464 }
6565
66- root , err = store . Load (t .Context (), RootLabel )
66+ rootHash1 , err := tree . RootHash (t .Context ())
6767 fatalIfErr (t , err )
68- if root . Hash != rootHash {
69- t .Fatalf ("after inserting in reverse order: got %x, want %x" , root . Hash , rootHash )
68+ if rootHash1 != rootHash {
69+ t .Fatalf ("after inserting in reverse order: got %x, want %x" , rootHash1 , rootHash )
7070 }
7171
7272 store = newStorage (t )
@@ -80,35 +80,39 @@ func testFullTree(t *testing.T, newStorage func(t *testing.T) Storage) {
8080 fatalIfErr (t , tree .Insert (t .Context (), label , value ))
8181 }
8282
83- root , err = store . Load (t .Context (), RootLabel )
83+ rootHash1 , err = tree . RootHash (t .Context ())
8484 fatalIfErr (t , err )
85- if root . Hash != rootHash {
86- t .Fatalf ("after inserting in random order: got %x, want %x" , root . Hash , rootHash )
85+ if rootHash1 != rootHash {
86+ t .Fatalf ("after inserting in random order: got %x, want %x" , rootHash1 , rootHash )
8787 }
8888}
8989
9090func TestAccumulated (t * testing.T ) {
9191 testAllStorage (t , testAccumulated )
9292}
9393func testAccumulated (t * testing.T , newStorage func (t * testing.T ) Storage ) {
94+ if _ , ok := newStorage (t ).(* prefixsqlite.Storage ); ok && testing .Short () {
95+ t .Skip ("skipping accumulated test for sqlite storage in short mode" )
96+ }
97+
9498 source := blake3 .New (0 , nil ).XOF ()
9599 sink := blake3 .New (32 , nil )
96100
97101 for range 100 {
98102 store := newStorage (t )
99103 fatalIfErr (t , InitStorage (t .Context (), blake3 .Sum256 , store ))
100104 tree := NewTree (blake3 .Sum256 , store )
101- root , err := store . Load (t .Context (), RootLabel )
105+ rootHash , err := tree . RootHash (t .Context ())
102106 fatalIfErr (t , err )
103- sink .Write (root . Hash [:])
107+ sink .Write (rootHash [:])
104108 for range 1000 {
105109 var label , value [32 ]byte
106110 source .Read (label [:])
107111 source .Read (value [:])
108112 fatalIfErr (t , tree .Insert (t .Context (), label , value ))
109- root , err := store . Load (t .Context (), RootLabel )
113+ rootHash , err := tree . RootHash (t .Context ())
110114 fatalIfErr (t , err )
111- sink .Write (root . Hash [:])
115+ sink .Write (rootHash [:])
112116 }
113117 }
114118
@@ -119,6 +123,66 @@ func testAccumulated(t *testing.T, newStorage func(t *testing.T) Storage) {
119123 }
120124}
121125
126+ func TestMemoryUsage (t * testing.T ) {
127+ if testing .Short () {
128+ t .Skip ("skipping memory usage test in short mode" )
129+ }
130+
131+ store := NewMemoryStorage ()
132+ fatalIfErr (t , InitStorage (t .Context (), blake3 .Sum256 , store ))
133+ tree := NewTree (blake3 .Sum256 , store )
134+
135+ runtime .GC ()
136+ var start runtime.MemStats
137+ runtime .ReadMemStats (& start )
138+
139+ source := blake3 .New (0 , nil ).XOF ()
140+ for n := range 1000000 {
141+ var label , value [32 ]byte
142+ source .Read (label [:])
143+ source .Read (value [:])
144+ fatalIfErr (t , tree .Insert (t .Context (), label , value ))
145+
146+ switch n + 1 {
147+ case 1000 , 10000 , 100000 , 1000000 :
148+ runtime .GC ()
149+ var m runtime.MemStats
150+ runtime .ReadMemStats (& m )
151+ t .Logf ("Memory usage after inserting % 8d nodes: % 10d bytes" , n + 1 , int64 (m .Alloc )- int64 (start .Alloc ))
152+ }
153+ }
154+ }
155+
156+ func TestMembershipProof (t * testing.T ) {
157+ testAllStorage (t , testMembershipProof )
158+ }
159+ func testMembershipProof (t * testing.T , newStorage func (t * testing.T ) Storage ) {
160+ store := newStorage (t )
161+ fatalIfErr (t , InitStorage (t .Context (), blake3 .Sum256 , store ))
162+ tree := NewTree (blake3 .Sum256 , store )
163+
164+ var entries [][32 ]byte
165+ for _ , n := range rand .Perm (100 ) {
166+ var label [32 ]byte
167+ binary .LittleEndian .PutUint16 (label [:], uint16 (n ))
168+ value := blake3 .Sum256 (label [:])
169+ fatalIfErr (t , tree .Insert (t .Context (), label , value ))
170+ entries = append (entries , label )
171+
172+ rootHash , err := tree .RootHash (t .Context ())
173+ fatalIfErr (t , err )
174+
175+ for _ , label := range entries {
176+ value := blake3 .Sum256 (label [:])
177+ proof , err := tree .Lookup (t .Context (), label )
178+ fatalIfErr (t , err )
179+ if err := VerifyMembershipProof (blake3 .Sum256 , label , value , proof , rootHash ); err != nil {
180+ t .Fatalf ("membership proof for %x with %d entries failed: %v" , label , len (entries ), err )
181+ }
182+ }
183+ }
184+ }
185+
122186func fatalIfErr (t * testing.T , err error ) {
123187 if err != nil {
124188 t .Helper ()
0 commit comments