Skip to content

Commit

Permalink
Add DumpArraySlabs, DumpMapSlabs, and more tests
Browse files Browse the repository at this point in the history
DumpArraySlabs returns a slice of slab details, including id, size,
count, elements, child headers.

DumpMapSlabs returns a slice of slab details, including id, size,
firstKey, elements, child headers.

Array.String returns array data similar to Go's slice string representation.

OrderedMap.String returns map data similar to Go's map string representation.

Add more tests.
  • Loading branch information
fxamacker committed Nov 19, 2021
1 parent ee5b67b commit 472f40f
Show file tree
Hide file tree
Showing 6 changed files with 767 additions and 229 deletions.
56 changes: 24 additions & 32 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,25 +798,17 @@ func (a *ArrayDataSlab) PopIterate(storage SlabStorage, fn ArrayPopIterationFunc
}

func (a *ArrayDataSlab) String() string {
var elements []Storable
if len(a.elements) <= 6 {
elements = a.elements
} else {
elements = append(elements, a.elements[:3]...)
elements = append(elements, a.elements[len(a.elements)-3:]...)
}

var elemsStr []string
for _, e := range elements {
for _, e := range a.elements {
elemsStr = append(elemsStr, fmt.Sprint(e))
}

if len(a.elements) > 6 {
elemsStr = append(elemsStr, "")
copy(elemsStr[4:], elemsStr[3:])
elemsStr[3] = "..."
}
return fmt.Sprintf("[%s]", strings.Join(elemsStr, " "))
return fmt.Sprintf("ArrayDataSlab id:%s size:%d count:%d elements: [%s]",
a.header.id,
a.header.size,
a.header.count,
strings.Join(elemsStr, " "),
)
}

func newArrayMetaDataSlabFromData(
Expand Down Expand Up @@ -1793,7 +1785,13 @@ func (a *ArrayMetaDataSlab) String() string {
for _, h := range a.childrenHeaders {
elemsStr = append(elemsStr, fmt.Sprintf("{id:%s size:%d count:%d}", h.id, h.size, h.count))
}
return fmt.Sprintf("[%s]", strings.Join(elemsStr, " "))

return fmt.Sprintf("ArrayMetaDataSlab id:%s size:%d count:%d children: [%s]",
a.header.id,
a.header.size,
a.header.count,
strings.Join(elemsStr, " "),
)
}

func NewArray(storage SlabStorage, address Address, typeInfo TypeInfo) (*Array, error) {
Expand Down Expand Up @@ -2120,30 +2118,24 @@ func (a *Array) Type() TypeInfo {
}

func (a *Array) String() string {
if a.root.IsData() {
return a.root.String()
iterator, err := a.Iterator()
if err != nil {
return err.Error()
}
meta := a.root.(*ArrayMetaDataSlab)
return a.string(meta)
}

func (a *Array) string(meta *ArrayMetaDataSlab) string {
var elemsStr []string

for _, h := range meta.childrenHeaders {
child, err := getArraySlab(a.Storage, h.id)
for {
v, err := iterator.Next()
if err != nil {
return err.Error()
}
if child.IsData() {
data := child.(*ArrayDataSlab)
elemsStr = append(elemsStr, data.String())
} else {
meta := child.(*ArrayMetaDataSlab)
elemsStr = append(elemsStr, a.string(meta))
if v == nil {
break
}
elemsStr = append(elemsStr, fmt.Sprintf("%s", v))
}
return strings.Join(elemsStr, " ")

return fmt.Sprintf("[%s]", strings.Join(elemsStr, " "))
}

func getArraySlab(storage SlabStorage, id StorageID) (ArraySlab, error) {
Expand Down
46 changes: 21 additions & 25 deletions array_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ package atree

import (
"bytes"
"errors"
"fmt"
"reflect"
"strings"

"github.com/fxamacker/cbor/v2"
)
Expand Down Expand Up @@ -97,6 +99,16 @@ func GetArrayStats(a *Array) (ArrayStats, error) {

// PrintArray prints array slab data to stdout.
func PrintArray(a *Array) {
dumps, err := DumpArraySlabs(a)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(strings.Join(dumps, "\n"))
}

func DumpArraySlabs(a *Array) ([]string, error) {
var dumps []string

nextLevelIDs := []StorageID{a.StorageID()}

Expand All @@ -113,20 +125,12 @@ func PrintArray(a *Array) {

slab, err := getArraySlab(a.Storage, id)
if err != nil {
fmt.Println(err)
return
return nil, err
}

if slab.IsData() {
dataSlab := slab.(*ArrayDataSlab)
fmt.Printf(
"level %d leaf (id:%s size:%d count:%d next:%s): %s\n",
level+1,
dataSlab.header.id,
dataSlab.header.size,
dataSlab.header.count,
dataSlab.next,
dataSlab)
dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, dataSlab))

childStorables := dataSlab.ChildStorables()
for _, e := range childStorables {
Expand All @@ -137,20 +141,12 @@ func PrintArray(a *Array) {

} else {
meta := slab.(*ArrayMetaDataSlab)
fmt.Printf(
"level %d meta (id:%s size:%d count:%d) children: %s\n",
level+1,
meta.header.id,
meta.header.size,
meta.header.count,
meta,
)
dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, meta))

for _, storable := range slab.ChildStorables() {
id, ok := storable.(StorageIDStorable)
if !ok {
fmt.Printf("metadata slab's child storables are not of type StorageIDStorable")
return
return nil, errors.New("metadata slab's child storables are not of type StorageIDStorable")
}
nextLevelIDs = append(nextLevelIDs, StorageID(id))
}
Expand All @@ -163,15 +159,15 @@ func PrintArray(a *Array) {
for _, id := range overflowIDs {
slab, found, err := a.Storage.Retrieve(id)
if err != nil {
fmt.Println(err.Error())
return
return nil, err
}
if !found {
fmt.Printf("slab %s not found\n", id)
return
return nil, NewSlabNotFoundErrorf(id, "slab not found during array slab dump")
}
fmt.Printf("overflow: (id %s) %s\n", id, slab)
dumps = append(dumps, fmt.Sprintf("overflow: %s", slab))
}

return dumps, nil
}

type TypeInfoComparator func(TypeInfo, TypeInfo) bool
Expand Down
83 changes: 78 additions & 5 deletions array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2164,7 +2164,7 @@ func TestArrayString(t *testing.T) {
})

t.Run("large", func(t *testing.T) {
const arraySize = 190
const arraySize = 120

typeInfo := testTypeInfo{42}
storage := newTestPersistentStorage(t)
Expand All @@ -2178,10 +2178,83 @@ func TestArrayString(t *testing.T) {
require.NoError(t, err)
}

wantArrayString := `[0 1 2 ... 51 52 53] [54 55 56 ... 97 98 99] [100 101 102 ... 187 188 189]`
require.Equal(t, wantArrayString, array.String())
want := `[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119]`
require.Equal(t, want, array.String())
})
}

func TestArraySlabDump(t *testing.T) {
SetThreshold(256)
defer SetThreshold(1024)

wantMetaDataSlabString := `[{id:0x102030405060708.2 size:213 count:54} {id:0x102030405060708.3 size:205 count:46} {id:0x102030405060708.4 size:381 count:90}]`
require.Equal(t, wantMetaDataSlabString, array.root.String())
t.Run("small", func(t *testing.T) {
const arraySize = 6

typeInfo := testTypeInfo{42}
storage := newTestPersistentStorage(t)
address := Address{1, 2, 3, 4, 5, 6, 7, 8}

array, err := NewArray(storage, address, typeInfo)
require.NoError(t, err)

for i := uint64(0); i < arraySize; i++ {
err := array.Append(Uint64Value(i))
require.NoError(t, err)
}

want := []string{
"level 1, ArrayDataSlab id:0x102030405060708.1 size:23 count:6 elements: [0 1 2 3 4 5]",
}
dumps, err := DumpArraySlabs(array)
require.NoError(t, err)
require.Equal(t, want, dumps)
})

t.Run("large", func(t *testing.T) {
const arraySize = 120

typeInfo := testTypeInfo{42}
storage := newTestPersistentStorage(t)
address := Address{1, 2, 3, 4, 5, 6, 7, 8}

array, err := NewArray(storage, address, typeInfo)
require.NoError(t, err)

for i := uint64(0); i < arraySize; i++ {
err := array.Append(Uint64Value(i))
require.NoError(t, err)
}

want := []string{
"level 1, ArrayMetaDataSlab id:0x102030405060708.1 size:52 count:120 children: [{id:0x102030405060708.2 size:213 count:54} {id:0x102030405060708.3 size:285 count:66}]",
"level 2, ArrayDataSlab id:0x102030405060708.2 size:213 count:54 elements: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53]",
"level 2, ArrayDataSlab id:0x102030405060708.3 size:285 count:66 elements: [54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119]",
}

dumps, err := DumpArraySlabs(array)
require.NoError(t, err)
require.Equal(t, want, dumps)
})

t.Run("overflow", func(t *testing.T) {

typeInfo := testTypeInfo{42}
storage := newTestPersistentStorage(t)
address := Address{1, 2, 3, 4, 5, 6, 7, 8}

array, err := NewArray(storage, address, typeInfo)
require.NoError(t, err)

err = array.Append(NewStringValue(strings.Repeat("a", int(MaxInlineArrayElementSize))))
require.NoError(t, err)

want := []string{
"level 1, ArrayDataSlab id:0x102030405060708.1 size:24 count:1 elements: [StorageIDStorable({[1 2 3 4 5 6 7 8] [0 0 0 0 0 0 0 2]})]",
"overflow: &{0x102030405060708.2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}",
}

dumps, err := DumpArraySlabs(array)
require.NoError(t, err)
require.Equal(t, want, dumps)
})
}
Loading

0 comments on commit 472f40f

Please sign in to comment.