github.com/onflow/atree@v0.6.0/storage_test.go (about) 1 /* 2 * Atree - Scalable Arrays and Ordered Maps 3 * 4 * Copyright 2021-2022 Dapper Labs, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package atree 20 21 import ( 22 "errors" 23 "math/rand" 24 "runtime" 25 "strings" 26 "testing" 27 28 "github.com/fxamacker/cbor/v2" 29 "github.com/stretchr/testify/require" 30 ) 31 32 func TestStorageIndexNext(t *testing.T) { 33 index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 1} 34 want := StorageIndex{0, 0, 0, 0, 0, 0, 0, 2} 35 require.Equal(t, want, index.Next()) 36 } 37 38 func TestNewStorageID(t *testing.T) { 39 t.Run("temp address", func(t *testing.T) { 40 want := StorageID{Address: Address{}, Index: StorageIndex{1}} 41 require.Equal(t, want, NewStorageID(Address{}, StorageIndex{1})) 42 }) 43 t.Run("perm address", func(t *testing.T) { 44 want := StorageID{Address: Address{1}, Index: StorageIndex{1}} 45 require.Equal(t, want, NewStorageID(Address{1}, StorageIndex{1})) 46 }) 47 } 48 49 func TestNewStorageIDFromRawBytes(t *testing.T) { 50 t.Run("data length < storage id size", func(t *testing.T) { 51 var fatalError *FatalError 52 var storageIDError *StorageIDError 53 54 id, err := NewStorageIDFromRawBytes(nil) 55 require.Equal(t, StorageIDUndefined, id) 56 require.Equal(t, 1, errorCategorizationCount(err)) 57 require.ErrorAs(t, err, &fatalError) 58 require.ErrorAs(t, err, &storageIDError) 59 require.ErrorAs(t, fatalError, &storageIDError) 60 61 id, err = NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2}) 62 require.Equal(t, StorageIDUndefined, id) 63 require.Equal(t, 1, errorCategorizationCount(err)) 64 require.ErrorAs(t, err, &fatalError) 65 require.ErrorAs(t, err, &storageIDError) 66 require.ErrorAs(t, fatalError, &storageIDError) 67 }) 68 69 t.Run("data length == storage id size", func(t *testing.T) { 70 id, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2}) 71 72 want := StorageID{ 73 Address: Address{0, 0, 0, 0, 0, 0, 0, 1}, 74 Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, 75 } 76 require.Equal(t, want, id) 77 require.NoError(t, err) 78 }) 79 t.Run("data length > storage id size", func(t *testing.T) { 80 id, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 3, 4, 5, 6, 7, 8}) 81 82 want := StorageID{ 83 Address: Address{0, 0, 0, 0, 0, 0, 0, 1}, 84 Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, 85 } 86 require.Equal(t, want, id) 87 require.NoError(t, err) 88 }) 89 } 90 91 func TestStorageIDToRawBytes(t *testing.T) { 92 t.Run("buffer nil", func(t *testing.T) { 93 var fatalError *FatalError 94 var storageIDError *StorageIDError 95 96 size, err := StorageIDUndefined.ToRawBytes(nil) 97 require.Equal(t, 0, size) 98 require.Equal(t, 1, errorCategorizationCount(err)) 99 require.ErrorAs(t, err, &fatalError) 100 require.ErrorAs(t, err, &storageIDError) 101 require.ErrorAs(t, fatalError, &storageIDError) 102 }) 103 104 t.Run("buffer too short", func(t *testing.T) { 105 var fatalError *FatalError 106 var storageIDError *StorageIDError 107 108 b := make([]byte, 8) 109 size, err := StorageIDUndefined.ToRawBytes(b) 110 require.Equal(t, 0, size) 111 require.Equal(t, 1, errorCategorizationCount(err)) 112 require.ErrorAs(t, err, &fatalError) 113 require.ErrorAs(t, err, &storageIDError) 114 require.ErrorAs(t, fatalError, &storageIDError) 115 }) 116 117 t.Run("undefined", func(t *testing.T) { 118 b := make([]byte, storageIDSize) 119 size, err := StorageIDUndefined.ToRawBytes(b) 120 require.NoError(t, err) 121 122 want := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 123 require.Equal(t, want, b) 124 require.Equal(t, storageIDSize, size) 125 }) 126 127 t.Run("temp address", func(t *testing.T) { 128 id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 0}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}) 129 b := make([]byte, storageIDSize) 130 size, err := id.ToRawBytes(b) 131 require.NoError(t, err) 132 133 want := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} 134 require.Equal(t, want, b) 135 require.Equal(t, storageIDSize, size) 136 }) 137 138 t.Run("temp index", func(t *testing.T) { 139 id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 0}) 140 b := make([]byte, storageIDSize) 141 size, err := id.ToRawBytes(b) 142 require.NoError(t, err) 143 144 want := []byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0} 145 require.Equal(t, want, b) 146 require.Equal(t, storageIDSize, size) 147 }) 148 149 t.Run("perm", func(t *testing.T) { 150 id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}) 151 b := make([]byte, storageIDSize) 152 size, err := id.ToRawBytes(b) 153 require.NoError(t, err) 154 155 want := []byte{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2} 156 require.Equal(t, want, b) 157 require.Equal(t, storageIDSize, size) 158 }) 159 } 160 161 func TestStorageIDAddressAsUint64(t *testing.T) { 162 t.Run("temp", func(t *testing.T) { 163 id := NewStorageID(Address{}, StorageIndex{1}) 164 require.Equal(t, uint64(0), id.AddressAsUint64()) 165 }) 166 t.Run("perm", func(t *testing.T) { 167 id := NewStorageID(Address{0, 0, 0, 0, 0, 0, 0, 1}, StorageIndex{1}) 168 require.Equal(t, uint64(1), id.AddressAsUint64()) 169 }) 170 } 171 172 func TestStorageIDIndexAsUint64(t *testing.T) { 173 t.Run("temp", func(t *testing.T) { 174 id := NewStorageID(Address{}, StorageIndex{}) 175 require.Equal(t, uint64(0), id.IndexAsUint64()) 176 }) 177 t.Run("perm", func(t *testing.T) { 178 id := NewStorageID(Address{}, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}) 179 require.Equal(t, uint64(1), id.IndexAsUint64()) 180 }) 181 } 182 183 func TestStorageIDValid(t *testing.T) { 184 t.Run("undefined", func(t *testing.T) { 185 id := StorageIDUndefined 186 err := id.Valid() 187 188 var fatalError *FatalError 189 var storageIDError *StorageIDError 190 require.Equal(t, 1, errorCategorizationCount(err)) 191 require.ErrorAs(t, err, &fatalError) 192 require.ErrorAs(t, err, &storageIDError) 193 require.ErrorAs(t, fatalError, &storageIDError) 194 }) 195 t.Run("temp index", func(t *testing.T) { 196 id := StorageID{Address: Address{1}, Index: StorageIndexUndefined} 197 err := id.Valid() 198 199 var fatalError *FatalError 200 var storageIDError *StorageIDError 201 require.Equal(t, 1, errorCategorizationCount(err)) 202 require.ErrorAs(t, err, &fatalError) 203 require.ErrorAs(t, err, &storageIDError) 204 require.ErrorAs(t, fatalError, &storageIDError) 205 }) 206 t.Run("temp address", func(t *testing.T) { 207 id := StorageID{Address: AddressUndefined, Index: StorageIndex{1}} 208 require.NoError(t, id.Valid()) 209 }) 210 t.Run("valid", func(t *testing.T) { 211 id := StorageID{Address: Address{1}, Index: StorageIndex{2}} 212 require.NoError(t, id.Valid()) 213 }) 214 } 215 216 func TestStorageIDCompare(t *testing.T) { 217 t.Run("same", func(t *testing.T) { 218 id1 := NewStorageID(Address{1}, StorageIndex{1}) 219 id2 := NewStorageID(Address{1}, StorageIndex{1}) 220 require.Equal(t, 0, id1.Compare(id2)) 221 require.Equal(t, 0, id2.Compare(id1)) 222 }) 223 224 t.Run("different address", func(t *testing.T) { 225 id1 := NewStorageID(Address{1}, StorageIndex{1}) 226 id2 := NewStorageID(Address{2}, StorageIndex{1}) 227 require.Equal(t, -1, id1.Compare(id2)) 228 require.Equal(t, 1, id2.Compare(id1)) 229 }) 230 231 t.Run("different index", func(t *testing.T) { 232 id1 := NewStorageID(Address{1}, StorageIndex{1}) 233 id2 := NewStorageID(Address{1}, StorageIndex{2}) 234 require.Equal(t, -1, id1.Compare(id2)) 235 require.Equal(t, 1, id2.Compare(id1)) 236 }) 237 238 t.Run("different address and index", func(t *testing.T) { 239 id1 := NewStorageID(Address{1}, StorageIndex{1}) 240 id2 := NewStorageID(Address{2}, StorageIndex{2}) 241 require.Equal(t, -1, id1.Compare(id2)) 242 require.Equal(t, 1, id2.Compare(id1)) 243 }) 244 } 245 246 func TestLedgerBaseStorageStore(t *testing.T) { 247 ledger := newTestLedger() 248 baseStorage := NewLedgerBaseStorage(ledger) 249 250 bytesStored := 0 251 values := map[StorageID][]byte{ 252 {Address{1}, StorageIndex{1}}: {1, 2, 3}, 253 {Address{1}, StorageIndex{2}}: {4, 5, 6}, 254 } 255 256 // Store values 257 for id, value := range values { 258 err := baseStorage.Store(id, value) 259 bytesStored += len(value) 260 require.NoError(t, err) 261 } 262 263 // Overwrite stored values 264 for id := range values { 265 values[id] = append(values[id], []byte{1, 2, 3}...) 266 bytesStored += len(values[id]) 267 err := baseStorage.Store(id, values[id]) 268 require.NoError(t, err) 269 } 270 271 require.Equal(t, bytesStored, baseStorage.BytesStored()) 272 require.Equal(t, 0, baseStorage.BytesRetrieved()) 273 274 iterator := ledger.Iterator() 275 276 count := 0 277 for { 278 owner, key, value := iterator() 279 if owner == nil { 280 break 281 } 282 var id StorageID 283 copy(id.Address[:], owner) 284 copy(id.Index[:], key[1:]) 285 286 require.True(t, LedgerKeyIsSlabKey(string(key))) 287 require.Equal(t, values[id], value) 288 289 count++ 290 } 291 require.Equal(t, len(values), count) 292 } 293 294 func TestLedgerBaseStorageRetrieve(t *testing.T) { 295 ledger := newTestLedger() 296 baseStorage := NewLedgerBaseStorage(ledger) 297 298 id := StorageID{Address: Address{1}, Index: StorageIndex{1}} 299 value := []byte{1, 2, 3} 300 bytesStored := 0 301 bytesRetrieved := 0 302 303 // Retrieve value from empty storage 304 b, found, err := baseStorage.Retrieve(id) 305 require.NoError(t, err) 306 require.False(t, found) 307 require.Equal(t, 0, len(b)) 308 309 bytesStored += len(value) 310 err = baseStorage.Store(id, value) 311 require.NoError(t, err) 312 313 // Retrieve stored value 314 b, found, err = baseStorage.Retrieve(id) 315 bytesRetrieved += len(b) 316 require.NoError(t, err) 317 require.True(t, found) 318 require.Equal(t, value, b) 319 320 // Retrieve non-existent value 321 id = StorageID{Address: Address{1}, Index: StorageIndex{2}} 322 b, found, err = baseStorage.Retrieve(id) 323 require.NoError(t, err) 324 require.False(t, found) 325 require.Nil(t, b) 326 327 require.Equal(t, bytesStored, baseStorage.BytesStored()) 328 require.Equal(t, bytesRetrieved, baseStorage.BytesRetrieved()) 329 } 330 331 func TestLedgerBaseStorageRemove(t *testing.T) { 332 ledger := newTestLedger() 333 baseStorage := NewLedgerBaseStorage(ledger) 334 335 id := StorageID{Address: Address{1}, Index: StorageIndex{1}} 336 value := []byte{1, 2, 3} 337 338 // Remove value from empty storage 339 err := baseStorage.Remove(id) 340 require.NoError(t, err) 341 342 err = baseStorage.Store(id, value) 343 require.NoError(t, err) 344 345 // Remove stored value 346 err = baseStorage.Remove(id) 347 require.NoError(t, err) 348 349 // Remove removed value 350 err = baseStorage.Remove(id) 351 require.NoError(t, err) 352 353 // Remove non-existent value 354 err = baseStorage.Remove(StorageID{Address: id.Address, Index: id.Index.Next()}) 355 require.NoError(t, err) 356 357 // Retrieve removed value 358 slab, found, err := baseStorage.Retrieve(id) 359 require.NoError(t, err) 360 require.False(t, found) 361 require.Nil(t, slab) 362 363 iterator := ledger.Iterator() 364 365 count := 0 366 for { 367 owner, key, value := iterator() 368 if owner == nil { 369 break 370 } 371 var id StorageID 372 copy(id.Address[:], owner) 373 copy(id.Index[:], key[1:]) 374 375 require.True(t, LedgerKeyIsSlabKey(string(key))) 376 require.Nil(t, value) 377 378 count++ 379 } 380 require.Equal(t, 2, count) 381 } 382 383 func TestLedgerBaseStorageGenerateStorageID(t *testing.T) { 384 ledger := newTestLedger() 385 baseStorage := NewLedgerBaseStorage(ledger) 386 387 address1 := Address{1} 388 address2 := Address{2} 389 390 id, err := baseStorage.GenerateStorageID(address1) 391 require.NoError(t, err) 392 require.Equal(t, address1, id.Address) 393 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 394 395 id, err = baseStorage.GenerateStorageID(address1) 396 require.NoError(t, err) 397 require.Equal(t, address1, id.Address) 398 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index) 399 400 id, err = baseStorage.GenerateStorageID(address2) 401 require.NoError(t, err) 402 require.Equal(t, address2, id.Address) 403 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 404 } 405 406 func TestBasicSlabStorageStore(t *testing.T) { 407 storage := NewBasicSlabStorage(nil, nil, nil, nil) 408 409 r := newRand(t) 410 address := Address{1} 411 slabs := map[StorageID]Slab{ 412 {address, StorageIndex{1}}: generateRandomSlab(address, r), 413 {address, StorageIndex{2}}: generateRandomSlab(address, r), 414 } 415 416 // Store values 417 for id, slab := range slabs { 418 err := storage.Store(id, slab) 419 require.NoError(t, err) 420 } 421 422 // Overwrite stored values 423 for id := range slabs { 424 slab := generateRandomSlab(id.Address, r) 425 slabs[id] = slab 426 err := storage.Store(id, slab) 427 require.NoError(t, err) 428 } 429 430 require.Equal(t, len(slabs), storage.Count()) 431 432 // Retrieve slabs 433 for id, want := range slabs { 434 slab, found, err := storage.Retrieve(id) 435 require.NoError(t, err) 436 require.True(t, found) 437 require.Equal(t, want, slab) 438 } 439 } 440 441 func TestBasicSlabStorageRetrieve(t *testing.T) { 442 storage := NewBasicSlabStorage(nil, nil, nil, nil) 443 444 r := newRand(t) 445 id := StorageID{Address{1}, StorageIndex{1}} 446 slab := generateRandomSlab(id.Address, r) 447 448 // Retrieve value from empty storage 449 retrievedSlab, found, err := storage.Retrieve(id) 450 require.NoError(t, err) 451 require.False(t, found) 452 require.Nil(t, retrievedSlab) 453 454 err = storage.Store(id, slab) 455 require.NoError(t, err) 456 457 // Retrieve stored value 458 retrievedSlab, found, err = storage.Retrieve(id) 459 require.NoError(t, err) 460 require.True(t, found) 461 require.Equal(t, slab, retrievedSlab) 462 463 // Retrieve non-existent value 464 id = StorageID{Address: Address{1}, Index: StorageIndex{2}} 465 retrievedSlab, found, err = storage.Retrieve(id) 466 require.NoError(t, err) 467 require.False(t, found) 468 require.Nil(t, retrievedSlab) 469 } 470 471 func TestBasicSlabStorageRemove(t *testing.T) { 472 storage := NewBasicSlabStorage(nil, nil, nil, nil) 473 474 r := newRand(t) 475 id := StorageID{Address{1}, StorageIndex{1}} 476 slab := generateRandomSlab(id.Address, r) 477 478 // Remove value from empty storage 479 err := storage.Remove(id) 480 require.NoError(t, err) 481 482 err = storage.Store(id, slab) 483 require.NoError(t, err) 484 485 // Remove stored value 486 err = storage.Remove(id) 487 require.NoError(t, err) 488 489 // Remove removed value 490 err = storage.Remove(id) 491 require.NoError(t, err) 492 493 // Remove non-existent value 494 err = storage.Remove(StorageID{Address: id.Address, Index: id.Index.Next()}) 495 require.NoError(t, err) 496 497 // Retrieve removed value 498 slab, found, err := storage.Retrieve(id) 499 require.NoError(t, err) 500 require.False(t, found) 501 require.Nil(t, slab) 502 503 require.Equal(t, 0, storage.Count()) 504 } 505 506 func TestBasicSlabStorageGenerateStorageID(t *testing.T) { 507 storage := NewBasicSlabStorage(nil, nil, nil, nil) 508 509 address1 := Address{1} 510 address2 := Address{2} 511 512 id, err := storage.GenerateStorageID(address1) 513 require.NoError(t, err) 514 require.Equal(t, address1, id.Address) 515 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 516 517 id, err = storage.GenerateStorageID(address1) 518 require.NoError(t, err) 519 require.Equal(t, address1, id.Address) 520 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index) 521 522 id, err = storage.GenerateStorageID(address2) 523 require.NoError(t, err) 524 require.Equal(t, address2, id.Address) 525 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 526 } 527 528 func TestBasicSlabStorageStorageIDs(t *testing.T) { 529 r := newRand(t) 530 address := Address{1} 531 index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 0} 532 wantIDs := map[StorageID]bool{ 533 {Address: address, Index: index.Next()}: true, 534 {Address: address, Index: index.Next()}: true, 535 {Address: address, Index: index.Next()}: true, 536 } 537 538 storage := NewBasicSlabStorage(nil, nil, nil, nil) 539 540 // Get storage ids from empty storgae 541 ids := storage.StorageIDs() 542 require.Equal(t, 0, len(ids)) 543 544 // Store values 545 for id := range wantIDs { 546 err := storage.Store(id, generateRandomSlab(id.Address, r)) 547 require.NoError(t, err) 548 } 549 550 // Get storage ids from non-empty storgae 551 ids = storage.StorageIDs() 552 require.Equal(t, len(wantIDs), len(ids)) 553 554 for _, id := range ids { 555 require.True(t, wantIDs[id]) 556 } 557 } 558 559 func TestBasicSlabStorageSlabIterat(t *testing.T) { 560 r := newRand(t) 561 address := Address{1} 562 index := StorageIndex{0, 0, 0, 0, 0, 0, 0, 0} 563 564 id1 := StorageID{Address: address, Index: index.Next()} 565 id2 := StorageID{Address: address, Index: index.Next()} 566 id3 := StorageID{Address: address, Index: index.Next()} 567 568 want := map[StorageID]Slab{ 569 id1: generateRandomSlab(id1.Address, r), 570 id2: generateRandomSlab(id2.Address, r), 571 id3: generateRandomSlab(id3.Address, r), 572 } 573 574 storage := NewBasicSlabStorage(nil, nil, nil, nil) 575 576 // Store values 577 for id, slab := range want { 578 err := storage.Store(id, slab) 579 require.NoError(t, err) 580 } 581 582 iterator, err := storage.SlabIterator() 583 require.NoError(t, err) 584 585 count := 0 586 for { 587 id, slab := iterator() 588 if id == StorageIDUndefined { 589 break 590 } 591 require.NotNil(t, want[id]) 592 require.Equal(t, want[id], slab) 593 count++ 594 } 595 require.Equal(t, len(want), count) 596 } 597 598 func TestPersistentStorage(t *testing.T) { 599 600 encMode, err := cbor.EncOptions{}.EncMode() 601 require.NoError(t, err) 602 603 decMode, err := cbor.DecOptions{}.DecMode() 604 require.NoError(t, err) 605 606 t.Run("empty storage", func(t *testing.T) { 607 baseStorage := NewInMemBaseStorage() 608 storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil) 609 610 tempStorageID, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) 611 require.NoError(t, err) 612 613 permStorageID, err := NewStorageIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) 614 require.NoError(t, err) 615 616 _, found, err := storage.Retrieve(tempStorageID) 617 require.NoError(t, err) 618 require.False(t, found) 619 620 _, found, err = storage.Retrieve(permStorageID) 621 require.NoError(t, err) 622 require.False(t, found) 623 624 require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses()) 625 require.Equal(t, uint(0), storage.Deltas()) 626 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 627 }) 628 629 t.Run("temp address", func(t *testing.T) { 630 631 r := newRand(t) 632 633 baseStorage := NewInMemBaseStorage() 634 storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil) 635 636 tempStorageID, err := NewStorageIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) 637 require.NoError(t, err) 638 639 permStorageID, err := NewStorageIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) 640 require.NoError(t, err) 641 642 slab1 := generateRandomSlab(tempStorageID.Address, r) 643 slab2 := generateRandomSlab(permStorageID.Address, r) 644 645 // no temp ids should be in the base storage 646 err = storage.Store(tempStorageID, slab1) 647 require.NoError(t, err) 648 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 649 650 err = storage.Store(permStorageID, slab2) 651 require.NoError(t, err) 652 653 require.Equal(t, uint(1), storage.DeltasWithoutTempAddresses()) 654 require.Equal(t, uint(2), storage.Deltas()) 655 require.True(t, storage.DeltasSizeWithoutTempAddresses() > 0) 656 require.Equal(t, uint64(slab2.ByteSize()), storage.DeltasSizeWithoutTempAddresses()) 657 658 err = storage.Commit() 659 require.NoError(t, err) 660 661 require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses()) 662 require.Equal(t, uint(1), storage.Deltas()) 663 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 664 665 // Slab with temp storage id is NOT persisted in base storage. 666 _, found, err := baseStorage.Retrieve(tempStorageID) 667 require.NoError(t, err) 668 require.False(t, found) 669 670 // Slab with temp storage id is cached in storage. 671 _, found, err = storage.Retrieve(tempStorageID) 672 require.NoError(t, err) 673 require.True(t, found) 674 675 // Slab with perm storage id is persisted in base storage. 676 _, found, err = baseStorage.Retrieve(permStorageID) 677 require.NoError(t, err) 678 require.True(t, found) 679 680 // Slab with perm storage id is cached in storage. 681 _, found, err = storage.Retrieve(permStorageID) 682 require.NoError(t, err) 683 require.True(t, found) 684 685 // Remove slab with perm storage id 686 err = storage.Remove(permStorageID) 687 require.NoError(t, err) 688 689 // Remove slab with temp storage id 690 err = storage.Remove(tempStorageID) 691 require.NoError(t, err) 692 693 require.Equal(t, uint(1), storage.DeltasWithoutTempAddresses()) 694 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 695 696 err = storage.Commit() 697 require.NoError(t, err) 698 699 // Slab with perm storage id is removed from base storage. 700 _, found, err = baseStorage.Retrieve(permStorageID) 701 require.NoError(t, err) 702 require.False(t, found) 703 704 // Slab with perm storage id is removed from cache in storage. 705 _, found, err = storage.Retrieve(permStorageID) 706 require.NoError(t, err) 707 require.False(t, found) 708 709 // Slab with temp storage id is removed from cache in storage. 710 _, found, err = storage.Retrieve(tempStorageID) 711 require.NoError(t, err) 712 require.False(t, found) 713 714 require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses()) 715 require.Equal(t, uint(1), storage.Deltas()) 716 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 717 }) 718 719 t.Run("commit", func(t *testing.T) { 720 numberOfAccounts := 100 721 numberOfSlabsPerAccount := 10 722 723 r := newRand(t) 724 baseStorage := newAccessOrderTrackerBaseStorage() 725 storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil) 726 baseStorage2 := newAccessOrderTrackerBaseStorage() 727 storageWithFastCommit := NewPersistentSlabStorage(baseStorage2, encMode, decMode, nil, nil) 728 729 simpleMap := make(map[StorageID][]byte) 730 slabSize := uint64(0) 731 // test random updates apply commit and check the order of committed values 732 for i := 0; i < numberOfAccounts; i++ { 733 for j := 0; j < numberOfSlabsPerAccount; j++ { 734 addr := generateRandomAddress(r) 735 slab := generateRandomSlab(addr, r) 736 slabSize += uint64(slab.ByteSize()) 737 738 storageID, err := storage.GenerateStorageID(addr) 739 require.NoError(t, err) 740 err = storage.Store(storageID, slab) 741 require.NoError(t, err) 742 743 storageID2, err := storageWithFastCommit.GenerateStorageID(addr) 744 require.NoError(t, err) 745 err = storageWithFastCommit.Store(storageID2, slab) 746 require.NoError(t, err) 747 748 // capture data for accuracy testing 749 simpleMap[storageID], err = Encode(slab, encMode) 750 require.NoError(t, err) 751 } 752 } 753 754 require.True(t, storage.DeltasSizeWithoutTempAddresses() > 0) 755 require.Equal(t, slabSize, storage.DeltasSizeWithoutTempAddresses()) 756 require.True(t, storageWithFastCommit.DeltasSizeWithoutTempAddresses() > 0) 757 require.Equal(t, slabSize, storageWithFastCommit.DeltasSizeWithoutTempAddresses()) 758 759 err = storage.Commit() 760 require.NoError(t, err) 761 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 762 763 err = storageWithFastCommit.FastCommit(10) 764 require.NoError(t, err) 765 require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses()) 766 767 require.Equal(t, len(simpleMap), storage.Count()) 768 require.Equal(t, len(simpleMap), storageWithFastCommit.Count()) 769 770 // check update functionality 771 for sid, value := range simpleMap { 772 storedValue, found, err := baseStorage.Retrieve(sid) 773 require.NoError(t, err) 774 require.True(t, found) 775 require.Equal(t, value, storedValue) 776 777 storedValue, found, err = baseStorage2.Retrieve(sid) 778 require.NoError(t, err) 779 require.True(t, found) 780 require.Equal(t, value, storedValue) 781 } 782 783 // compare orders 784 require.Equal(t, baseStorage.SegTouchOrder(), baseStorage2.SegTouchOrder()) 785 786 // remove all slabs from storage 787 for sid := range simpleMap { 788 err = storage.Remove(sid) 789 require.NoError(t, err) 790 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 791 792 err = storageWithFastCommit.Remove(sid) 793 require.NoError(t, err) 794 require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses()) 795 } 796 797 require.Equal(t, uint(len(simpleMap)), storage.DeltasWithoutTempAddresses()) 798 require.Equal(t, uint(len(simpleMap)), storageWithFastCommit.DeltasWithoutTempAddresses()) 799 800 err = storage.Commit() 801 require.NoError(t, err) 802 803 err = storageWithFastCommit.FastCommit(10) 804 require.NoError(t, err) 805 806 require.Equal(t, 0, storage.Count()) 807 require.Equal(t, 0, storageWithFastCommit.Count()) 808 require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses()) 809 require.Equal(t, uint64(0), storageWithFastCommit.DeltasSizeWithoutTempAddresses()) 810 811 // check remove functionality 812 for sid := range simpleMap { 813 storedValue, found, err := storage.Retrieve(sid) 814 require.NoError(t, err) 815 require.False(t, found) 816 require.Nil(t, storedValue) 817 818 storedValue, found, err = storageWithFastCommit.Retrieve(sid) 819 require.NoError(t, err) 820 require.False(t, found) 821 require.Nil(t, storedValue) 822 } 823 824 // compare orders 825 require.Equal(t, baseStorage.SegTouchOrder(), baseStorage2.SegTouchOrder()) 826 }) 827 828 t.Run("commit with error", func(t *testing.T) { 829 830 baseStorage := NewInMemBaseStorage() 831 storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil) 832 833 // Encoding slabWithNonStorable returns error. 834 slabWithNonStorable := &ArrayDataSlab{ 835 header: ArraySlabHeader{size: uint32(1), count: uint32(1)}, 836 elements: []Storable{nonStorable{}}, 837 } 838 // Encoding slabWithSlowStorable takes some time which delays 839 // sending encoding result to results channel. 840 slabWithSlowStorable := &ArrayDataSlab{ 841 header: ArraySlabHeader{size: uint32(3), count: uint32(1)}, 842 elements: []Storable{newSlowStorable(1)}, 843 } 844 845 address := Address{1} 846 847 id, err := storage.GenerateStorageID(address) 848 require.NoError(t, err) 849 850 err = storage.Store(id, slabWithNonStorable) 851 require.NoError(t, err) 852 853 for i := 0; i < 500; i++ { 854 id, err := storage.GenerateStorageID(address) 855 require.NoError(t, err) 856 857 err = storage.Store(id, slabWithSlowStorable) 858 require.NoError(t, err) 859 } 860 861 err = storage.FastCommit(2) 862 require.Equal(t, 1, errorCategorizationCount(err)) 863 864 var externalError *ExternalError 865 require.ErrorAs(t, err, &externalError) 866 require.ErrorIs(t, err, errEncodeNonStorable) 867 require.ErrorIs(t, externalError.Unwrap(), errEncodeNonStorable) 868 }) 869 } 870 871 func TestPersistentStorageSlabIterator(t *testing.T) { 872 t.Run("empty storage", func(t *testing.T) { 873 storage := newTestPersistentStorage(t) 874 875 iterator, err := storage.SlabIterator() 876 require.NoError(t, err) 877 878 count := 0 879 for { 880 id, _ := iterator() 881 if id == StorageIDUndefined { 882 break 883 } 884 count++ 885 } 886 require.Equal(t, 0, count) 887 }) 888 889 t.Run("not-empty storage", func(t *testing.T) { 890 891 address := Address{1, 2, 3, 4, 5, 6, 7, 8} 892 id1 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}} 893 id2 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}} 894 id3 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 3}} 895 id4 := StorageID{Address: address, Index: StorageIndex{0, 0, 0, 0, 0, 0, 0, 4}} 896 897 data := map[StorageID][]byte{ 898 // (metadata slab) headers: [{id:2 size:228 count:9} {id:3 size:270 count:11} ] 899 id1: { 900 // extra data 901 // version 902 0x00, 903 // extra data flag 904 0x81, 905 // array of extra data 906 0x81, 907 // type info 908 0x18, 0x2a, 909 910 // version 911 0x00, 912 // array meta data slab flag 913 0x81, 914 // child header count 915 0x00, 0x02, 916 // child header 1 (storage id, count, size) 917 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 918 0x00, 0x00, 0x00, 0x09, 919 0x00, 0x00, 0x00, 0xe4, 920 // child header 2 921 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 922 0x00, 0x00, 0x00, 0x0b, 923 0x00, 0x00, 0x01, 0x0e, 924 }, 925 926 // (data slab) next: 3, data: [aaaaaaaaaaaaaaaaaaaaaa ... aaaaaaaaaaaaaaaaaaaaaa] 927 id2: { 928 // version 929 0x00, 930 // array data slab flag 931 0x00, 932 // next storage id 933 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 934 // CBOR encoded array head (fixed size 3 byte) 935 0x99, 0x00, 0x09, 936 // CBOR encoded array elements 937 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 938 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 939 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 940 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 941 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 942 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 943 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 944 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 945 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 946 }, 947 948 // (data slab) next: 0, data: [aaaaaaaaaaaaaaaaaaaaaa ... StorageID(...)] 949 id3: { 950 // version 951 0x00, 952 // array data slab flag 953 0x40, 954 // next storage id 955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 956 // CBOR encoded array head (fixed size 3 byte) 957 0x99, 0x00, 0x0b, 958 // CBOR encoded array elements 959 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 960 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 961 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 962 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 963 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 964 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 965 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 966 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 967 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 968 0x76, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 969 0xd8, 0xff, 0x50, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 970 }, 971 972 // (data slab) next: 0, data: [0] 973 id4: { 974 // extra data 975 // version 976 0x00, 977 // extra data flag 978 0x80, 979 // array of extra data 980 0x81, 981 // type info 982 0x18, 0x2b, 983 984 // version 985 0x00, 986 // array data slab flag 987 0x80, 988 // CBOR encoded array head (fixed size 3 byte) 989 0x99, 0x00, 0x01, 990 // CBOR encoded array elements 991 0xd8, 0xa4, 0x00, 992 }, 993 } 994 995 storage := newTestPersistentStorageWithData(t, data) 996 997 _, err := NewArrayWithRootID(storage, id1) 998 require.NoError(t, err) 999 1000 iterator, err := storage.SlabIterator() 1001 require.NoError(t, err) 1002 1003 count := 0 1004 for { 1005 id, slab := iterator() 1006 if id == StorageIDUndefined { 1007 break 1008 } 1009 1010 encodedSlab, err := Encode(slab, storage.cborEncMode) 1011 require.NoError(t, err) 1012 1013 require.Equal(t, encodedSlab, data[id]) 1014 count++ 1015 } 1016 require.Equal(t, len(data), count) 1017 }) 1018 } 1019 1020 func TestPersistentStorageGenerateStorageID(t *testing.T) { 1021 baseStorage := NewInMemBaseStorage() 1022 storage := NewPersistentSlabStorage(baseStorage, nil, nil, nil, nil) 1023 1024 t.Run("temp address", func(t *testing.T) { 1025 address := Address{} 1026 1027 id, err := storage.GenerateStorageID(address) 1028 require.NoError(t, err) 1029 require.Equal(t, address, id.Address) 1030 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 1031 1032 id, err = storage.GenerateStorageID(address) 1033 require.NoError(t, err) 1034 require.Equal(t, address, id.Address) 1035 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index) 1036 }) 1037 t.Run("perm address", func(t *testing.T) { 1038 address := Address{1} 1039 1040 id, err := storage.GenerateStorageID(address) 1041 require.NoError(t, err) 1042 require.Equal(t, address, id.Address) 1043 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 1}, id.Index) 1044 1045 id, err = storage.GenerateStorageID(address) 1046 require.NoError(t, err) 1047 require.Equal(t, address, id.Address) 1048 require.Equal(t, StorageIndex{0, 0, 0, 0, 0, 0, 0, 2}, id.Index) 1049 }) 1050 } 1051 1052 func generateRandomSlab(address Address, r *rand.Rand) Slab { 1053 storable := Uint64Value(r.Uint64()) 1054 1055 return &ArrayDataSlab{ 1056 header: ArraySlabHeader{ 1057 id: NewStorageID(address, StorageIndex{1}), 1058 size: arrayRootDataSlabPrefixSize + storable.ByteSize(), 1059 count: 1, 1060 }, 1061 elements: []Storable{storable}, 1062 } 1063 } 1064 1065 func generateRandomAddress(r *rand.Rand) Address { 1066 address := Address{} 1067 r.Read(address[:]) 1068 return address 1069 } 1070 1071 type accessOrderTrackerBaseStorage struct { 1072 segTouchOrder []StorageID 1073 indexReqOrder []Address 1074 segments map[StorageID][]byte 1075 storageIndex map[Address]StorageIndex 1076 } 1077 1078 func newAccessOrderTrackerBaseStorage() *accessOrderTrackerBaseStorage { 1079 return &accessOrderTrackerBaseStorage{ 1080 segTouchOrder: make([]StorageID, 0), 1081 indexReqOrder: make([]Address, 0), 1082 segments: make(map[StorageID][]byte), 1083 storageIndex: make(map[Address]StorageIndex), 1084 } 1085 } 1086 1087 func (s *accessOrderTrackerBaseStorage) SegTouchOrder() []StorageID { 1088 return s.segTouchOrder 1089 } 1090 1091 func (s *accessOrderTrackerBaseStorage) Retrieve(id StorageID) ([]byte, bool, error) { 1092 s.segTouchOrder = append(s.segTouchOrder, id) 1093 seg, ok := s.segments[id] 1094 return seg, ok, nil 1095 } 1096 1097 func (s *accessOrderTrackerBaseStorage) Store(id StorageID, data []byte) error { 1098 s.segTouchOrder = append(s.segTouchOrder, id) 1099 s.segments[id] = data 1100 return nil 1101 } 1102 1103 func (s *accessOrderTrackerBaseStorage) Remove(id StorageID) error { 1104 s.segTouchOrder = append(s.segTouchOrder, id) 1105 delete(s.segments, id) 1106 return nil 1107 } 1108 1109 func (s *accessOrderTrackerBaseStorage) GenerateStorageID(address Address) (StorageID, error) { 1110 s.indexReqOrder = append(s.indexReqOrder, address) 1111 1112 index := s.storageIndex[address] 1113 nextIndex := index.Next() 1114 1115 s.storageIndex[address] = nextIndex 1116 return NewStorageID(address, nextIndex), nil 1117 } 1118 1119 func (s *accessOrderTrackerBaseStorage) SegmentCounts() int { return len(s.segments) } 1120 1121 func (s *accessOrderTrackerBaseStorage) Size() int { return 0 } 1122 1123 func (s *accessOrderTrackerBaseStorage) BytesRetrieved() int { return 0 } 1124 1125 func (s *accessOrderTrackerBaseStorage) BytesStored() int { return 0 } 1126 1127 func (s *accessOrderTrackerBaseStorage) SegmentsReturned() int { return 0 } 1128 1129 func (s *accessOrderTrackerBaseStorage) SegmentsUpdated() int { return 0 } 1130 1131 func (s *accessOrderTrackerBaseStorage) SegmentsTouched() int { return 0 } 1132 1133 func (s *accessOrderTrackerBaseStorage) ResetReporter() {} 1134 1135 type testLedger struct { 1136 values map[string][]byte 1137 index map[string]StorageIndex 1138 } 1139 1140 var _ Ledger = &testLedger{} 1141 1142 func newTestLedger() *testLedger { 1143 return &testLedger{ 1144 values: make(map[string][]byte), 1145 index: make(map[string]StorageIndex), 1146 } 1147 } 1148 1149 func (l *testLedger) GetValue(owner, key []byte) (value []byte, err error) { 1150 value = l.values[l.key(owner, key)] 1151 return value, nil 1152 } 1153 1154 func (l *testLedger) SetValue(owner, key, value []byte) (err error) { 1155 l.values[l.key(owner, key)] = value 1156 return nil 1157 } 1158 1159 func (l *testLedger) ValueExists(owner, key []byte) (exists bool, err error) { 1160 value := l.values[l.key(owner, key)] 1161 return len(value) > 0, nil 1162 } 1163 1164 func (l *testLedger) AllocateStorageIndex(owner []byte) (StorageIndex, error) { 1165 index := l.index[string(owner)] 1166 next := index.Next() 1167 l.index[string(owner)] = next 1168 return next, nil 1169 } 1170 1171 func (l *testLedger) key(owner, key []byte) string { 1172 return strings.Join([]string{string(owner), string(key)}, "|") 1173 } 1174 1175 type ledgerIterationFunc func() (owner, key, value []byte) 1176 1177 func (l *testLedger) Iterator() ledgerIterationFunc { 1178 keys := make([]string, 0, len(l.values)) 1179 for k := range l.values { 1180 keys = append(keys, k) 1181 } 1182 1183 i := 0 1184 return func() (owner, key, value []byte) { 1185 if i >= len(keys) { 1186 return nil, nil, nil 1187 } 1188 1189 s := strings.Split(keys[i], "|") 1190 owner, key = []byte(s[0]), []byte(s[1]) 1191 value = l.values[keys[i]] 1192 i++ 1193 return owner, key, value 1194 } 1195 } 1196 1197 func (l *testLedger) Count() int { 1198 return len(l.values) 1199 } 1200 1201 var errEncodeNonStorable = errors.New("failed to encode non-storable") 1202 1203 // nonStorable can't be encoded successfully. 1204 type nonStorable struct{} 1205 1206 func (nonStorable) Encode(_ *Encoder) error { 1207 return errEncodeNonStorable 1208 } 1209 1210 func (nonStorable) ByteSize() uint32 { 1211 return 1 1212 } 1213 1214 func (v nonStorable) StoredValue(_ SlabStorage) (Value, error) { 1215 return v, nil 1216 } 1217 1218 func (nonStorable) ChildStorables() []Storable { 1219 return nil 1220 } 1221 1222 func (v nonStorable) Storable(_ SlabStorage, _ Address, _ uint64) (Storable, error) { 1223 return v, nil 1224 } 1225 1226 type slowStorable struct { 1227 Uint8Value 1228 } 1229 1230 func newSlowStorable(i uint8) slowStorable { 1231 return slowStorable{ 1232 Uint8Value: Uint8Value(i), 1233 } 1234 } 1235 1236 // slowStorable.Encode is used to reproduce a 1237 // panic. It needs to be slow enough 1238 // when called by FastCommit() compared to 1239 // to a non-slow Encode function returning an error. 1240 // See Atree issue #240. 1241 func (s slowStorable) Encode(encoder *Encoder) error { 1242 // Use division in a loop to slow down this function 1243 n := 1.0 1244 for i := 0; i < 2000; i++ { 1245 n = (n + float64(i)) / 3.14 1246 } 1247 runtime.KeepAlive(n) 1248 return s.Uint8Value.Encode(encoder) 1249 }