1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 14:07:02 +09:00

Make tests compile

This commit is contained in:
mcrakhman 2024-11-22 17:16:15 +01:00
parent 55f2655dba
commit 0705d1a6b8
No known key found for this signature in database
GPG key ID: DED12CFEF5B8396B
6 changed files with 227 additions and 210 deletions

View file

@ -785,6 +785,19 @@ func (ot *objectTree) ChangesAfterCommonSnapshotLoader(theirPath, theirHeads []s
return iter, nil return iter, nil
} }
// this is a helper function to be used in testing
func (ot *objectTree) changesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
loader, err := ot.ChangesAfterCommonSnapshotLoader(theirPath, theirHeads)
if err != nil {
return nil, err
}
res, err := loader.NextBatch(10 * 1024 * 1024)
if err != nil {
return nil, err
}
return res.Batch, nil
}
func (ot *objectTree) snapshotPathIsActual() bool { func (ot *objectTree) snapshotPathIsActual() bool {
return len(ot.snapshotPath) != 0 && ot.snapshotPath[0] == ot.tree.RootId() return len(ot.snapshotPath) != 0 && ot.snapshotPath[0] == ot.tree.RootId()
} }

View file

@ -119,14 +119,15 @@ func genChanges(creator *MockChangeCreator, params genParams) (res genResult) {
type testTreeContext struct { type testTreeContext struct {
aclList list.AclList aclList list.AclList
storage Storage treeStorage Storage
changeCreator *MockChangeCreator changeCreator *MockChangeCreator
objTree ObjectTree objTree ObjectTree
} }
type testStore struct { type testStore struct {
anystore.DB anystore.DB
path string path string
errAdd bool
} }
func newStore(ctx context.Context, t *testing.T) anystore.DB { func newStore(ctx context.Context, t *testing.T) anystore.DB {
@ -146,6 +147,15 @@ func newNamedStore(ctx context.Context, t *testing.T, name string) anystore.DB {
} }
} }
func allChanges(ctx context.Context, t *testing.T, store Storage) (res []*treechangeproto.RawTreeChangeWithId) {
err := store.GetAfterOrder(ctx, "", func(ctx context.Context, change StorageChange) (shouldContinue bool) {
res = append(res, change.RawTreeChangeWithId())
return true
})
require.NoError(t, err)
return
}
func copyFolder(src string, dst string) error { func copyFolder(src string, dst string) error {
return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error { return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
@ -263,7 +273,7 @@ func prepareContext(
} }
return testTreeContext{ return testTreeContext{
aclList: aclList, aclList: aclList,
storage: treeStorage, treeStorage: treeStorage,
changeCreator: changeCreator, changeCreator: changeCreator,
objTree: objTree, objTree: objTree,
} }
@ -371,32 +381,38 @@ func TestObjectTree(t *testing.T) {
DataType: mockDataType, DataType: mockDataType,
}) })
require.NoError(t, err) require.NoError(t, err)
var rawAdded []*treechangeproto.RawTreeChangeWithId
for _, ch := range res.Added {
rawAdded = append(rawAdded, ch.RawTreeChangeWithId())
}
oldHeads := bTree.Heads() oldHeads := bTree.Heads()
res, err = bTree.AddRawChanges(ctx, RawChangesPayload{ res, err = bTree.AddRawChanges(ctx, RawChangesPayload{
NewHeads: aTree.Heads(), NewHeads: aTree.Heads(),
RawChanges: res.Added, RawChanges: rawAdded,
}) })
require.Equal(t, oldHeads, bTree.Heads()) require.Equal(t, oldHeads, bTree.Heads())
bStore = aTree.Storage().(*treestorage.InMemoryTreeStorage).Copy() rawAdded = allChanges(ctx, t, bStore)
root, _ = bStore.Root() require.NoError(t, err)
heads, _ := bStore.Heads()
newTree, err := ValidateFilterRawTree(treestorage.TreeStorageCreatePayload{ newTree, err := ValidateFilterRawTree(treestorage.TreeStorageCreatePayload{
RootRawChange: root, RootRawChange: root,
Changes: bStore.AllChanges(), Changes: rawAdded,
Heads: heads, Heads: bTree.Heads(),
}, InMemoryStorageCreator{}, bAccount.Acl) }, InMemoryStorageCreator{}, bAccount.Acl)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(newTree.Storage().(*treestorage.InMemoryTreeStorage).AllChanges())) chCount := 0
err = aTree.IterateRoot(func(change *Change, decrypted []byte) (any, error) { err = newTree.IterateRoot(func(change *Change, decrypted []byte) (any, error) {
chCount++
return nil, nil return nil, nil
}, func(change *Change) bool { }, func(change *Change) bool {
return true return true
}) })
require.Equal(t, 2, chCount)
require.NoError(t, err) require.NoError(t, err)
}) })
t.Run("filter changes when no aclHeadId", func(t *testing.T) { t.Run("filter changes when no aclHeadId", func(t *testing.T) {
exec := list.NewAclExecutor("spaceId") exec := list.NewAclExecutor("spaceId")
store := newStore(ctx, t)
type cmdErr struct { type cmdErr struct {
cmd string cmd string
err error err error
@ -421,7 +437,7 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aAccount.Acl) }, aAccount.Acl)
require.NoError(t, err) require.NoError(t, err)
aStore, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) aStore, _ := createStorage(ctx, root, store)
aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl) aTree, err := BuildKeyFilterableObjectTree(aStore, aAccount.Acl)
require.NoError(t, err) require.NoError(t, err)
_, err = aTree.AddContent(ctx, SignableChangeContent{ _, err = aTree.AddContent(ctx, SignableChangeContent{
@ -432,7 +448,9 @@ func TestObjectTree(t *testing.T) {
DataType: mockDataType, DataType: mockDataType,
}) })
require.NoError(t, err) require.NoError(t, err)
bStore := aTree.Storage().(*treestorage.InMemoryTreeStorage).Copy() storeB := copyStore(ctx, t, store.(testStore), "b")
bStore, err := createStorage(ctx, root, storeB)
require.NoError(t, err)
// copying old version of storage // copying old version of storage
prevAclRecs, err := bAccount.Acl.RecordsAfter(ctx, "") prevAclRecs, err := bAccount.Acl.RecordsAfter(ctx, "")
require.NoError(t, err) require.NoError(t, err)
@ -482,8 +500,9 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
store, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) store := newStore(ctx, t)
oTree, err := BuildObjectTree(store, aclList) storage, _ := createStorage(ctx, root, store)
oTree, err := BuildObjectTree(storage, aclList)
require.NoError(t, err) require.NoError(t, err)
t.Run("add content validate failed", func(t *testing.T) { t.Run("add content validate failed", func(t *testing.T) {
@ -515,7 +534,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, oTree.Heads(), 1) require.Len(t, oTree.Heads(), 1)
require.Equal(t, res.Added[0].Id, oTree.Heads()[0]) require.Equal(t, res.Added[0].Id, oTree.Heads()[0])
ch, err := oTree.(*objectTree).changeBuilder.Unmarshall(res.Added[0], true) ch, err := oTree.(*objectTree).changeBuilder.Unmarshall(res.Added[0].RawTreeChangeWithId(), true)
require.NoError(t, err) require.NoError(t, err)
require.GreaterOrEqual(t, start.Unix(), ch.Timestamp) require.GreaterOrEqual(t, start.Unix(), ch.Timestamp)
require.LessOrEqual(t, end.Unix(), ch.Timestamp) require.LessOrEqual(t, end.Unix(), ch.Timestamp)
@ -534,7 +553,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, oTree.Heads(), 1) require.Len(t, oTree.Heads(), 1)
require.Equal(t, res.Added[0].Id, oTree.Heads()[0]) require.Equal(t, res.Added[0].Id, oTree.Heads()[0])
ch, err := oTree.(*objectTree).changeBuilder.Unmarshall(res.Added[0], true) ch, err := oTree.(*objectTree).changeBuilder.Unmarshall(res.Added[0].RawTreeChangeWithId(), true)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ch.Timestamp, someTs) require.Equal(t, ch.Timestamp, someTs)
require.Equal(t, res.Added[0].Id, oTree.(*objectTree).tree.lastIteratedHeadId) require.Equal(t, res.Added[0].Id, oTree.(*objectTree).tree.lastIteratedHeadId)
@ -551,14 +570,15 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
store, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) store := newStore(ctx, t)
oTree, err := BuildObjectTree(store, aclList) storage, _ := createStorage(ctx, root, store)
oTree, err := BuildObjectTree(storage, aclList)
require.NoError(t, err) require.NoError(t, err)
emptyDataTreeDeps = nonVerifiableTreeDeps emptyDataTreeDeps = nonVerifiableTreeDeps
err = ValidateRawTree(treestorage.TreeStorageCreatePayload{ err = ValidateRawTree(treestorage.TreeStorageCreatePayload{
RootRawChange: oTree.Header(), RootRawChange: oTree.Header(),
Heads: []string{root.Id}, Heads: []string{root.Id},
Changes: oTree.Storage().(*treestorage.InMemoryTreeStorage).AllChanges(), Changes: allChanges(ctx, t, oTree.Storage()),
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
}) })
@ -571,14 +591,15 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
store, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) store := newStore(ctx, t)
oTree, err := BuildObjectTree(store, aclList) storage, _ := createStorage(ctx, root, store)
oTree, err := BuildObjectTree(storage, aclList)
require.NoError(t, err) require.NoError(t, err)
emptyDataTreeDeps = nonVerifiableTreeDeps emptyDataTreeDeps = nonVerifiableTreeDeps
err = ValidateRawTree(treestorage.TreeStorageCreatePayload{ err = ValidateRawTree(treestorage.TreeStorageCreatePayload{
RootRawChange: oTree.Header(), RootRawChange: oTree.Header(),
Heads: []string{root.Id}, Heads: []string{root.Id},
Changes: oTree.Storage().(*treestorage.InMemoryTreeStorage).AllChanges(), Changes: allChanges(ctx, t, oTree.Storage()),
}, aclList) }, aclList)
require.Equal(t, ErrDerived, err) require.Equal(t, ErrDerived, err)
}) })
@ -604,8 +625,9 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
store, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root}) store := newStore(ctx, t)
oTree, err := BuildObjectTree(store, aclList) storage, _ := createStorage(ctx, root, store)
oTree, err := BuildObjectTree(storage, aclList)
require.NoError(t, err) require.NoError(t, err)
_, err = oTree.AddContent(ctx, SignableChangeContent{ _, err = oTree.AddContent(ctx, SignableChangeContent{
Data: []byte("some"), Data: []byte("some"),
@ -616,15 +638,15 @@ func TestObjectTree(t *testing.T) {
DataType: mockDataType, DataType: mockDataType,
}) })
require.NoError(t, err) require.NoError(t, err)
allChanges := oTree.Storage().(*treestorage.InMemoryTreeStorage).AllChanges() chs := allChanges(ctx, t, storage)
emptyDataTreeDeps = nonVerifiableTreeDeps emptyDataTreeDeps = nonVerifiableTreeDeps
err = ValidateRawTree(treestorage.TreeStorageCreatePayload{ err = ValidateRawTree(treestorage.TreeStorageCreatePayload{
RootRawChange: oTree.Header(), RootRawChange: oTree.Header(),
Heads: []string{oTree.Heads()[0]}, Heads: []string{oTree.Heads()[0]},
Changes: allChanges, Changes: chs,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
rawChs, err := oTree.ChangesAfterCommonSnapshot(nil, nil) rawChs := allChanges(ctx, t, oTree.Storage())
require.NoError(t, err) require.NoError(t, err)
sortFunc := func(a, b *treechangeproto.RawTreeChangeWithId) int { sortFunc := func(a, b *treechangeproto.RawTreeChangeWithId) int {
if a.Id < b.Id { if a.Id < b.Id {
@ -633,9 +655,9 @@ func TestObjectTree(t *testing.T) {
return -1 return -1
} }
} }
slices.SortFunc(allChanges, sortFunc) slices.SortFunc(chs, sortFunc)
slices.SortFunc(rawChs, sortFunc) slices.SortFunc(rawChs, sortFunc)
require.Equal(t, allChanges, rawChs) require.Equal(t, chs, rawChs)
}) })
t.Run("derived more than 1 change, snapshot, correct", func(t *testing.T) { t.Run("derived more than 1 change, snapshot, correct", func(t *testing.T) {
@ -646,9 +668,10 @@ func TestObjectTree(t *testing.T) {
IsEncrypted: true, IsEncrypted: true,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
store, _ := treestorage.NewInMemoryTreeStorage(root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root})
emptyDataTreeDeps = nonVerifiableTreeDeps emptyDataTreeDeps = nonVerifiableTreeDeps
oTree, err := BuildObjectTree(store, aclList) store := newStore(ctx, t)
storage, _ := createStorage(ctx, root, store)
oTree, err := BuildObjectTree(storage, aclList)
require.NoError(t, err) require.NoError(t, err)
_, err = oTree.AddContent(ctx, SignableChangeContent{ _, err = oTree.AddContent(ctx, SignableChangeContent{
Data: []byte("some"), Data: []byte("some"),
@ -659,14 +682,14 @@ func TestObjectTree(t *testing.T) {
DataType: mockDataType, DataType: mockDataType,
}) })
require.NoError(t, err) require.NoError(t, err)
allChanges := oTree.Storage().(*treestorage.InMemoryTreeStorage).AllChanges() chs := allChanges(ctx, t, storage)
err = ValidateRawTree(treestorage.TreeStorageCreatePayload{ err = ValidateRawTree(treestorage.TreeStorageCreatePayload{
RootRawChange: oTree.Header(), RootRawChange: oTree.Header(),
Heads: []string{oTree.Heads()[0]}, Heads: []string{oTree.Heads()[0]},
Changes: allChanges, Changes: chs,
}, aclList) }, aclList)
require.NoError(t, err) require.NoError(t, err)
rawChs, err := oTree.ChangesAfterCommonSnapshot(nil, nil) rawChs := allChanges(ctx, t, oTree.Storage())
require.NoError(t, err) require.NoError(t, err)
sortFunc := func(a, b *treechangeproto.RawTreeChangeWithId) int { sortFunc := func(a, b *treechangeproto.RawTreeChangeWithId) int {
if a.Id < b.Id { if a.Id < b.Id {
@ -675,9 +698,9 @@ func TestObjectTree(t *testing.T) {
return -1 return -1
} }
} }
slices.SortFunc(allChanges, sortFunc) slices.SortFunc(chs, sortFunc)
slices.SortFunc(rawChs, sortFunc) slices.SortFunc(rawChs, sortFunc)
require.Equal(t, allChanges, rawChs) require.Equal(t, chs, rawChs)
}) })
t.Run("validate from start, multiple snapshots, correct", func(t *testing.T) { t.Run("validate from start, multiple snapshots, correct", func(t *testing.T) {
@ -701,10 +724,10 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("add simple", func(t *testing.T) { t.Run("add simple", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
treeStorage := ctx.treeStorage treeStorage := treeCtx.treeStorage
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree objTree := treeCtx.objTree
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -739,11 +762,11 @@ func TestObjectTree(t *testing.T) {
assert.Equal(t, []string{"0", "1", "2"}, iterChangesId) assert.Equal(t, []string{"0", "1", "2"}, iterChangesId)
// check storage // check storage
heads, _ := treeStorage.Heads() heads, _ := treeStorage.Heads(ctx)
assert.Equal(t, []string{"2"}, heads) assert.Equal(t, []string{"2"}, heads)
for _, ch := range rawChanges { for _, ch := range rawChanges {
raw, err := treeStorage.GetRawChange(context.Background(), ch.Id) raw, err := treeStorage.Get(context.Background(), ch.Id)
assert.NoError(t, err, "storage should have all the changes") assert.NoError(t, err, "storage should have all the changes")
assert.Equal(t, ch, raw, "the changes in the storage should be the same") assert.Equal(t, ch, raw, "the changes in the storage should be the same")
} }
@ -825,10 +848,10 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("add new snapshot simple", func(t *testing.T) { t.Run("add new snapshot simple", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
treeStorage := ctx.treeStorage treeStorage := treeCtx.treeStorage
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree objTree := treeCtx.objTree
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -865,11 +888,11 @@ func TestObjectTree(t *testing.T) {
assert.Equal(t, "3", objTree.Root().Id) assert.Equal(t, "3", objTree.Root().Id)
// check storage // check storage
heads, _ := treeStorage.Heads() heads, _ := treeStorage.Heads(ctx)
assert.Equal(t, []string{"4"}, heads) assert.Equal(t, []string{"4"}, heads)
for _, ch := range rawChanges { for _, ch := range rawChanges {
raw, err := treeStorage.GetRawChange(context.Background(), ch.Id) raw, err := treeStorage.Get(context.Background(), ch.Id)
assert.NoError(t, err, "storage should have all the changes") assert.NoError(t, err, "storage should have all the changes")
assert.Equal(t, ch, raw, "the changes in the storage should be the same") assert.Equal(t, ch, raw, "the changes in the storage should be the same")
} }
@ -899,10 +922,10 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("add new snapshot simple with newChangeFlusher", func(t *testing.T) { t.Run("add new snapshot simple with newChangeFlusher", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
treeStorage := ctx.treeStorage treeStorage := treeCtx.treeStorage
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree.(*objectTree) objTree := treeCtx.objTree.(*objectTree)
objTree.flusher = &newChangeFlusher{} objTree.flusher = &newChangeFlusher{}
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
@ -946,13 +969,13 @@ func TestObjectTree(t *testing.T) {
assert.Equal(t, []string{"4"}, objTree.Heads()) assert.Equal(t, []string{"4"}, objTree.Heads())
// check storage // check storage
heads, _ := treeStorage.Heads() heads, _ := treeStorage.Heads(ctx)
assert.Equal(t, []string{"4"}, heads) assert.Equal(t, []string{"4"}, heads)
// after Flush // after Flush
assert.Equal(t, "3", objTree.Root().Id) assert.Equal(t, "3", objTree.Root().Id)
for _, ch := range rawChanges { for _, ch := range rawChanges {
raw, err := treeStorage.GetRawChange(context.Background(), ch.Id) raw, err := treeStorage.Get(context.Background(), ch.Id)
assert.NoError(t, err, "storage should have all the changes") assert.NoError(t, err, "storage should have all the changes")
assert.Equal(t, ch, raw, "the changes in the storage should be the same") assert.Equal(t, ch, raw, "the changes in the storage should be the same")
treeCh, err := objTree.GetChange(ch.Id) treeCh, err := objTree.GetChange(ch.Id)
@ -966,10 +989,10 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("update failed, nothing saved", func(t *testing.T) { t.Run("update failed, nothing saved", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
treeStorage := ctx.treeStorage treeStorage := treeCtx.treeStorage
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree.(*objectTree) objTree := treeCtx.objTree.(*objectTree)
objTree.flusher = &newChangeFlusher{} objTree.flusher = &newChangeFlusher{}
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
@ -992,12 +1015,12 @@ func TestObjectTree(t *testing.T) {
require.Equal(t, []string{"0"}, objTree.Heads()) require.Equal(t, []string{"0"}, objTree.Heads())
// check storage // check storage
heads, _ := treeStorage.Heads() heads, _ := treeStorage.Heads(ctx)
require.Equal(t, []string{"0"}, heads) require.Equal(t, []string{"0"}, heads)
require.Equal(t, "0", objTree.Root().Id) require.Equal(t, "0", objTree.Root().Id)
for _, ch := range rawChanges { for _, ch := range rawChanges {
_, err := treeStorage.GetRawChange(context.Background(), ch.Id) _, err := treeStorage.Get(context.Background(), ch.Id)
require.Error(t, err) require.Error(t, err)
} }
}) })
@ -1026,77 +1049,12 @@ func TestObjectTree(t *testing.T) {
assert.Equal(t, true, objTree.(*objectTree).snapshotPathIsActual()) assert.Equal(t, true, objTree.(*objectTree).snapshotPathIsActual())
}) })
t.Run("test empty data tree", func(t *testing.T) {
// TODO: think about how to rewrite this test without additional changes
//t.Run("empty tree load", func(t *testing.T) {
// ctx := prepareEmptyDataTreeContext(t, aclList, func(changeCreator *MockChangeCreator) RawChangesPayload {
// rawChanges := []*treechangeproto.RawTreeChangeWithId{
// changeCreator.CreateRawWithData("1", aclList.Head().Id, "0", false, []byte("1"), "0"),
// changeCreator.CreateRawWithData("2", aclList.Head().Id, "0", false, []byte("2"), "1"),
// changeCreator.CreateRawWithData("3", aclList.Head().Id, "0", false, []byte("3"), "2"),
// changeCreator.CreateRawWithData("4", aclList.Head().Id, "0", false, []byte("4"), "2"),
// changeCreator.CreateRawWithData("5", aclList.Head().Id, "0", false, []byte("5"), "1"),
// changeCreator.CreateRawWithData("6", aclList.Head().Id, "0", false, []byte("6"), "3", "4", "5"),
// }
// return RawChangesPayload{NewHeads: []string{"6"}, RawChanges: rawChanges}
// })
// ctx.objTree.IterateRoot(nil, func(change *Change) bool {
// if change.Id == "0" {
// return true
// }
// require.Nil(t, change.Data)
// return true
// })
// rawChanges, err := ctx.objTree.ChangesAfterCommonSnapshot([]string{"0"}, []string{"6"})
// require.NoError(t, err)
// for _, ch := range rawChanges {
// unmarshallRaw := &treechangeproto.RawTreeChange{}
// proto.Unmarshal(ch.RawChange, unmarshallRaw)
// treeCh := &treechangeproto.TreeChange{}
// proto.Unmarshal(unmarshallRaw.Payload, treeCh)
// require.Equal(t, ch.Id, string(treeCh.ChangesData))
// }
//})
})
t.Run("test tree restore", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList)
rawChanges := []*treechangeproto.RawTreeChangeWithId{
ctx.changeCreator.CreateRawWithData("1", aclList.Head().Id, "0", false, []byte("1"), "0"),
ctx.changeCreator.CreateRawWithData("2", aclList.Head().Id, "0", false, []byte("2"), "1"),
ctx.changeCreator.CreateRawWithData("3", aclList.Head().Id, "0", false, []byte("3"), "2"),
ctx.changeCreator.CreateRawWithData("4", aclList.Head().Id, "0", false, []byte("4"), "2"),
ctx.changeCreator.CreateRawWithData("5", aclList.Head().Id, "0", false, []byte("5"), "1"),
ctx.changeCreator.CreateRawWithData("6", aclList.Head().Id, "0", true, []byte("6"), "3", "4", "5"),
ctx.changeCreator.CreateRawWithData("7", aclList.Head().Id, "6", false, []byte("7"), "6"),
ctx.changeCreator.CreateRawWithData("8", aclList.Head().Id, "6", false, []byte("8"), "6"),
}
_, err := ctx.objTree.AddRawChanges(context.Background(), RawChangesPayload{
NewHeads: []string{"7", "8"},
RawChanges: rawChanges,
})
require.NoError(t, err)
st := ctx.treeStorage.(*treestorage.InMemoryTreeStorage)
st.Remove("6")
newCh := ctx.changeCreator.CreateRawWithData("9", aclList.Head().Id, "0", false, []byte("9"), "3", "4", "5")
_, err = ctx.objTree.AddRawChanges(context.Background(), RawChangesPayload{
NewHeads: []string{"9"},
RawChanges: []*treechangeproto.RawTreeChangeWithId{newCh},
})
require.NoError(t, err)
require.Equal(t, []string{"9"}, ctx.objTree.Heads())
heads, err := ctx.objTree.Storage().Heads()
require.NoError(t, err)
require.Equal(t, []string{"9"}, heads)
})
t.Run("rollback when add to storage returns error", func(t *testing.T) { t.Run("rollback when add to storage returns error", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree objTree := treeCtx.objTree
store := ctx.treeStorage.(*treestorage.InMemoryTreeStorage) store := treeCtx.treeStorage.(testStorage)
addErr := fmt.Errorf("error saving") store.errAdd = fmt.Errorf("error saving")
store.SetReturnErrorOnAdd(addErr)
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", true, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", true, "0"),
@ -1106,7 +1064,7 @@ func TestObjectTree(t *testing.T) {
RawChanges: rawChanges, RawChanges: rawChanges,
} }
_, err := objTree.AddRawChanges(context.Background(), payload) _, err := objTree.AddRawChanges(context.Background(), payload)
require.Error(t, err, addErr) require.Error(t, err, store.errAdd)
require.Equal(t, "0", objTree.Root().Id) require.Equal(t, "0", objTree.Root().Id)
}) })
@ -1144,49 +1102,10 @@ func TestObjectTree(t *testing.T) {
require.Equal(t, "6", objTree.Root().Id) require.Equal(t, "6", objTree.Root().Id)
}) })
t.Run("stored changes will not break the pipeline if heads were not updated", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList)
changeCreator := ctx.changeCreator
objTree := ctx.objTree
store := ctx.treeStorage.(*treestorage.InMemoryTreeStorage)
rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", true, "0"),
}
payload := RawChangesPayload{
NewHeads: []string{rawChanges[len(rawChanges)-1].Id},
RawChanges: rawChanges,
}
_, err := objTree.AddRawChanges(context.Background(), payload)
require.NoError(t, err, "adding changes should be without error")
require.Equal(t, "1", objTree.Root().Id)
// creating changes to save in the storage
// to imitate the condition where all changes are in the storage
// but the head was not updated
storageChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("2", aclList.Head().Id, "1", false, "1"),
changeCreator.CreateRaw("3", aclList.Head().Id, "1", true, "2"),
changeCreator.CreateRaw("4", aclList.Head().Id, "1", false, "2"),
changeCreator.CreateRaw("5", aclList.Head().Id, "1", false, "1"),
changeCreator.CreateRaw("6", aclList.Head().Id, "1", true, "3", "4", "5"),
}
store.AddRawChangesSetHeads(storageChanges, []string{"1"})
// updating with subset of those changes to see that everything will still work
payload = RawChangesPayload{
NewHeads: []string{"6"},
RawChanges: storageChanges,
}
_, err = objTree.AddRawChanges(context.Background(), payload)
require.NoError(t, err, "adding changes should be without error")
require.Equal(t, "6", objTree.Root().Id)
})
t.Run("changes from tree after common snapshot complex", func(t *testing.T) { t.Run("changes from tree after common snapshot complex", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) ctx := prepareTreeContext(t, aclList)
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree.(*objectTree)
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -1207,7 +1126,7 @@ func TestObjectTree(t *testing.T) {
require.Equal(t, "0", objTree.Root().Id) require.Equal(t, "0", objTree.Root().Id)
t.Run("all changes from tree", func(t *testing.T) { t.Run("all changes from tree", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1224,7 +1143,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("changes from tree after 1", func(t *testing.T) { t.Run("changes from tree after 1", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"1"}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{"1"})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1249,7 +1168,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("changes from tree after 5", func(t *testing.T) { t.Run("changes from tree after 5", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"5"}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{"5"})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1271,7 +1190,7 @@ func TestObjectTree(t *testing.T) {
t.Run("changes after common snapshot db complex", func(t *testing.T) { t.Run("changes after common snapshot db complex", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) ctx := prepareTreeContext(t, aclList)
changeCreator := ctx.changeCreator changeCreator := ctx.changeCreator
objTree := ctx.objTree objTree := ctx.objTree.(*objectTree)
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -1293,7 +1212,7 @@ func TestObjectTree(t *testing.T) {
require.Equal(t, "6", objTree.Root().Id) require.Equal(t, "6", objTree.Root().Id)
t.Run("all changes from db", func(t *testing.T) { t.Run("all changes from db", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1310,7 +1229,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("changes from tree db 1", func(t *testing.T) { t.Run("changes from tree db 1", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"1"}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{"1"})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1329,7 +1248,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("changes from tree db 5", func(t *testing.T) { t.Run("changes from tree db 5", func(t *testing.T) {
changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"5"}) changes, err := objTree.changesAfterCommonSnapshot([]string{"3", "0"}, []string{"5"})
require.NoError(t, err, "changes after common snapshot should be without error") require.NoError(t, err, "changes after common snapshot should be without error")
changeIds := make(map[string]struct{}) changeIds := make(map[string]struct{})
@ -1349,10 +1268,10 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("add new changes related to previous snapshot", func(t *testing.T) { t.Run("add new changes related to previous snapshot", func(t *testing.T) {
ctx := prepareTreeContext(t, aclList) treeCtx := prepareTreeContext(t, aclList)
treeStorage := ctx.treeStorage treeStorage := treeCtx.treeStorage
changeCreator := ctx.changeCreator changeCreator := treeCtx.changeCreator
objTree := ctx.objTree objTree := treeCtx.objTree
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -1401,18 +1320,18 @@ func TestObjectTree(t *testing.T) {
assert.Equal(t, "0", objTree.Root().Id) assert.Equal(t, "0", objTree.Root().Id)
// check storage // check storage
heads, _ := treeStorage.Heads() heads, _ := treeStorage.Heads(ctx)
assert.Equal(t, []string{"6"}, heads) assert.Equal(t, []string{"6"}, heads)
for _, ch := range rawChanges { for _, ch := range rawChanges {
raw, err := treeStorage.GetRawChange(context.Background(), ch.Id) raw, err := treeStorage.Get(context.Background(), ch.Id)
assert.NoError(t, err, "storage should have all the changes") assert.NoError(t, err, "storage should have all the changes")
assert.Equal(t, ch, raw, "the changes in the storage should be the same") assert.Equal(t, ch, raw, "the changes in the storage should be the same")
} }
}) })
t.Run("test history tree not include", func(t *testing.T) { t.Run("test history tree not include", func(t *testing.T) {
changeCreator, deps := prepareHistoryTreeDeps(aclList) changeCreator, deps := prepareHistoryTreeDeps(t, aclList)
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -1422,7 +1341,14 @@ func TestObjectTree(t *testing.T) {
changeCreator.CreateRaw("5", aclList.Head().Id, "0", false, "1"), changeCreator.CreateRaw("5", aclList.Head().Id, "0", false, "1"),
changeCreator.CreateRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"), changeCreator.CreateRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),
} }
deps.storage.AddRawChangesSetHeads(rawChanges, []string{"6"}) objTree, err := BuildObjectTree(deps.storage, deps.aclList)
require.NoError(t, err)
payload := RawChangesPayload{
NewHeads: []string{rawChanges[len(rawChanges)-1].Id},
RawChanges: rawChanges,
}
_, err = objTree.AddRawChanges(ctx, payload)
require.NoError(t, err)
hTree, err := buildHistoryTree(deps, HistoryTreeParams{ hTree, err := buildHistoryTree(deps, HistoryTreeParams{
Heads: []string{"6"}, Heads: []string{"6"},
IncludeBeforeId: false, IncludeBeforeId: false,
@ -1443,7 +1369,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("test history tree build full", func(t *testing.T) { t.Run("test history tree build full", func(t *testing.T) {
changeCreator, deps := prepareHistoryTreeDeps(aclList) changeCreator, deps := prepareHistoryTreeDeps(t, aclList)
// sequence of snapshots: 5->1->0 // sequence of snapshots: 5->1->0
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
@ -1454,7 +1380,14 @@ func TestObjectTree(t *testing.T) {
changeCreator.CreateRaw("5", aclList.Head().Id, "1", true, "3", "4"), changeCreator.CreateRaw("5", aclList.Head().Id, "1", true, "3", "4"),
changeCreator.CreateRaw("6", aclList.Head().Id, "5", false, "5"), changeCreator.CreateRaw("6", aclList.Head().Id, "5", false, "5"),
} }
deps.storage.AddRawChangesSetHeads(rawChanges, []string{"6"}) objTree, err := BuildObjectTree(deps.storage, deps.aclList)
require.NoError(t, err)
payload := RawChangesPayload{
NewHeads: []string{rawChanges[len(rawChanges)-1].Id},
RawChanges: rawChanges,
}
_, err = objTree.AddRawChanges(ctx, payload)
require.NoError(t, err)
hTree, err := buildHistoryTree(deps, HistoryTreeParams{}) hTree, err := buildHistoryTree(deps, HistoryTreeParams{})
require.NoError(t, err) require.NoError(t, err)
// check tree heads // check tree heads
@ -1472,7 +1405,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("test history tree include", func(t *testing.T) { t.Run("test history tree include", func(t *testing.T) {
changeCreator, deps := prepareHistoryTreeDeps(aclList) changeCreator, deps := prepareHistoryTreeDeps(t, aclList)
rawChanges := []*treechangeproto.RawTreeChangeWithId{ rawChanges := []*treechangeproto.RawTreeChangeWithId{
changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"), changeCreator.CreateRaw("1", aclList.Head().Id, "0", false, "0"),
@ -1482,9 +1415,17 @@ func TestObjectTree(t *testing.T) {
changeCreator.CreateRaw("5", aclList.Head().Id, "0", false, "1"), changeCreator.CreateRaw("5", aclList.Head().Id, "0", false, "1"),
changeCreator.CreateRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"), changeCreator.CreateRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),
} }
deps.storage.AddRawChangesSetHeads(rawChanges, []string{"6"}) objTree, err := BuildObjectTree(deps.storage, deps.aclList)
require.NoError(t, err)
payload := RawChangesPayload{
NewHeads: []string{rawChanges[len(rawChanges)-1].Id},
RawChanges: rawChanges,
}
_, err = objTree.AddRawChanges(ctx, payload)
require.NoError(t, err)
hTree, err := buildHistoryTree(deps, HistoryTreeParams{ hTree, err := buildHistoryTree(deps, HistoryTreeParams{
Heads: []string{"6"}, IncludeBeforeId: true, Heads: []string{"6"},
IncludeBeforeId: true,
}) })
require.NoError(t, err) require.NoError(t, err)
// check tree heads // check tree heads
@ -1502,7 +1443,7 @@ func TestObjectTree(t *testing.T) {
}) })
t.Run("test history tree root", func(t *testing.T) { t.Run("test history tree root", func(t *testing.T) {
_, deps := prepareHistoryTreeDeps(aclList) _, deps := prepareHistoryTreeDeps(t, aclList)
hTree, err := buildHistoryTree(deps, HistoryTreeParams{ hTree, err := buildHistoryTree(deps, HistoryTreeParams{
Heads: []string{"0"}, Heads: []string{"0"},
IncludeBeforeId: true, IncludeBeforeId: true,
@ -1582,7 +1523,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()}) iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()})
require.NoError(t, err) require.NoError(t, err)
otherTreeStorage := changeCreator.CreateNewTreeStorage("0", aclList.Head().Id, false) otherTreeStorage := changeCreator.CreateNewTreeStorage(t, "0", aclList.Head().Id, false)
otherTree, err := BuildTestableTree(otherTreeStorage, aclList) otherTree, err := BuildTestableTree(otherTreeStorage, aclList)
require.NoError(t, err) require.NoError(t, err)
for { for {
@ -1625,7 +1566,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()}) iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()})
require.NoError(t, err) require.NoError(t, err)
otherTreeStorage := changeCreator.CreateNewTreeStorage("0", aclList.Head().Id, false) otherTreeStorage := changeCreator.CreateNewTreeStorage(t, "0", aclList.Head().Id, false)
otherTree, err := BuildTestableTree(otherTreeStorage, aclList) otherTree, err := BuildTestableTree(otherTreeStorage, aclList)
require.NoError(t, err) require.NoError(t, err)
for { for {
@ -1670,7 +1611,7 @@ func TestObjectTree(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()}) iter, err := objTree.ChangesAfterCommonSnapshotLoader([]string{objTree.Id()}, []string{objTree.Id()})
require.NoError(t, err) require.NoError(t, err)
otherTreeStorage := changeCreator.CreateNewTreeStorage("0", aclList.Head().Id, false) otherTreeStorage := changeCreator.CreateNewTreeStorage(t, "0", aclList.Head().Id, false)
otherTree, err := BuildTestableTree(otherTreeStorage, aclList) otherTree, err := BuildTestableTree(otherTreeStorage, aclList)
require.NoError(t, err) require.NoError(t, err)
for { for {
@ -1708,7 +1649,7 @@ func TestObjectTree(t *testing.T) {
}, },
hasData: false, hasData: false,
}) })
otherTreeStorage := changeCreator.CreateNewTreeStorage("0", aclList.Head().Id, false) otherTreeStorage := changeCreator.CreateNewTreeStorage(t, "0", aclList.Head().Id, false)
otherTree, err := BuildTestableTree(otherTreeStorage, aclList) otherTree, err := BuildTestableTree(otherTreeStorage, aclList)
_, err = objTree.AddRawChanges(context.Background(), RawChangesPayload{ _, err = objTree.AddRawChanges(context.Background(), RawChangesPayload{
NewHeads: result.heads, NewHeads: result.heads,

View file

@ -1,6 +1,8 @@
package objecttree package objecttree
import ( import (
"context"
"github.com/anyproto/any-sync/commonspace/object/acl/list" "github.com/anyproto/any-sync/commonspace/object/acl/list"
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto" "github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anyproto/any-sync/util/crypto" "github.com/anyproto/any-sync/util/crypto"
@ -94,7 +96,7 @@ func nonVerifiableTreeDeps(
} }
func BuildEmptyDataObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildEmptyDataObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
rootChange, err := storage.Root() rootChange, err := storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -103,7 +105,7 @@ func BuildEmptyDataObjectTree(storage Storage, aclList list.AclList) (ObjectTree
} }
func BuildTestableTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildTestableTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
root, _ := storage.Root() root, _ := storage.Root(context.Background())
changeBuilder := &nonVerifiableChangeBuilder{ changeBuilder := &nonVerifiableChangeBuilder{
ChangeBuilder: NewChangeBuilder(newMockKeyStorage(), root.RawTreeChangeWithId()), ChangeBuilder: NewChangeBuilder(newMockKeyStorage(), root.RawTreeChangeWithId()),
} }
@ -120,7 +122,7 @@ func BuildTestableTree(storage Storage, aclList list.AclList) (ObjectTree, error
} }
func BuildEmptyDataTestableTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildEmptyDataTestableTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
root, _ := storage.Root() root, _ := storage.Root(context.Background())
changeBuilder := &nonVerifiableChangeBuilder{ changeBuilder := &nonVerifiableChangeBuilder{
ChangeBuilder: NewEmptyDataChangeBuilder(newMockKeyStorage(), root.RawTreeChangeWithId()), ChangeBuilder: NewEmptyDataChangeBuilder(newMockKeyStorage(), root.RawTreeChangeWithId()),
} }
@ -137,7 +139,7 @@ func BuildEmptyDataTestableTree(storage Storage, aclList list.AclList) (ObjectTr
} }
func BuildKeyFilterableObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildKeyFilterableObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
rootChange, err := storage.Root() rootChange, err := storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -147,7 +149,7 @@ func BuildKeyFilterableObjectTree(storage Storage, aclList list.AclList) (Object
} }
func BuildEmptyDataKeyFilterableObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildEmptyDataKeyFilterableObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
rootChange, err := storage.Root() rootChange, err := storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -157,7 +159,7 @@ func BuildEmptyDataKeyFilterableObjectTree(storage Storage, aclList list.AclList
} }
func BuildObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) { func BuildObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error) {
rootChange, err := storage.Root() rootChange, err := storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -166,7 +168,7 @@ func BuildObjectTree(storage Storage, aclList list.AclList) (ObjectTree, error)
} }
func BuildNonVerifiableHistoryTree(params HistoryTreeParams) (HistoryTree, error) { func BuildNonVerifiableHistoryTree(params HistoryTreeParams) (HistoryTree, error) {
rootChange, err := params.Storage.Root() rootChange, err := params.Storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -175,7 +177,7 @@ func BuildNonVerifiableHistoryTree(params HistoryTreeParams) (HistoryTree, error
} }
func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) { func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) {
rootChange, err := params.Storage.Root() rootChange, err := params.Storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -232,10 +234,12 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
return nil, err return nil, err
} }
objTree.rawRoot, err = objTree.treeStorage.Root() // TODO: think about contexts
root, err := objTree.storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }
objTree.rawRoot = root.RawTreeChangeWithId()
// verifying root // verifying root
header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, true) header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, true)
@ -269,7 +273,7 @@ func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht History
return nil, err return nil, err
} }
objTree.id = objTree.storage.Id() objTree.id = objTree.storage.Id()
root, err := objTree.storage.Root() root, err := objTree.storage.Root(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -76,6 +76,18 @@ type MockChangeCreator struct {
store anystore.DB store anystore.DB
} }
type testStorage struct {
Storage
errAdd error
}
func (t testStorage) AddAll(ctx context.Context, changes []StorageChange, heads []string, commonSnapshot string) error {
if t.errAdd != nil {
return t.errAdd
}
return t.Storage.AddAll(ctx, changes, heads, commonSnapshot)
}
func NewMockChangeCreator(store anystore.DB) *MockChangeCreator { func NewMockChangeCreator(store anystore.DB) *MockChangeCreator {
return &MockChangeCreator{ return &MockChangeCreator{
store: store, store: store,
@ -149,5 +161,7 @@ func (c *MockChangeCreator) CreateNewTreeStorage(t *testing.T, treeId, aclHeadId
root := c.CreateRoot(treeId, aclHeadId) root := c.CreateRoot(treeId, aclHeadId)
storage, err := createStorage(context.Background(), root, c.store) storage, err := createStorage(context.Background(), root, c.store)
require.NoError(t, err) require.NoError(t, err)
return storage return testStorage{
Storage: storage,
}
} }

13
go.mod
View file

@ -8,8 +8,8 @@ require (
github.com/anyproto/go-chash v0.1.0 github.com/anyproto/go-chash v0.1.0
github.com/anyproto/go-slip10 v1.0.0 github.com/anyproto/go-slip10 v1.0.0
github.com/anyproto/go-slip21 v1.0.0 github.com/anyproto/go-slip21 v1.0.0
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5
github.com/anyproto/lexid v0.0.2 github.com/anyproto/lexid v0.0.2
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5
github.com/btcsuite/btcd v0.22.1 github.com/btcsuite/btcd v0.22.1
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cespare/xxhash v1.1.0 github.com/cespare/xxhash v1.1.0
@ -39,6 +39,7 @@ require (
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
golang.org/x/net v0.31.0 golang.org/x/net v0.31.0
golang.org/x/time v0.8.0 golang.org/x/time v0.8.0
golang.org/x/tools v0.26.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
storj.io/drpc v0.0.34 storj.io/drpc v0.0.34
) )
@ -53,6 +54,7 @@ require (
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/disintegration/imaging v1.6.2 // indirect github.com/disintegration/imaging v1.6.2 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/flopp/go-findfont v0.1.0 // indirect github.com/flopp/go-findfont v0.1.0 // indirect
github.com/fogleman/gg v1.3.0 // indirect github.com/fogleman/gg v1.3.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
@ -85,14 +87,17 @@ require (
github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect github.com/multiformats/go-varint v0.0.7 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/onsi/ginkgo/v2 v2.20.2 // indirect github.com/onsi/ginkgo/v2 v2.20.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/common v0.60.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tetratelabs/wazero v1.8.1 // indirect github.com/tetratelabs/wazero v1.8.1 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/zeebo/errs v1.3.0 // indirect github.com/zeebo/errs v1.3.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect
@ -104,7 +109,11 @@ require (
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/text v0.20.0 // indirect
golang.org/x/tools v0.26.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect google.golang.org/protobuf v1.35.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect
modernc.org/libc v1.55.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.33.1 // indirect
zombiezen.com/go/sqlite v1.4.0 // indirect
) )

36
go.sum
View file

@ -6,6 +6,7 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/anyproto/any-store v0.1.2 h1:/WKsPOQxK1jOHS7efTIosnyJTvy0O3gYg/DSnt41DT0=
github.com/anyproto/any-store v0.1.2/go.mod h1:SDlN2AzysAfs8CDd28rrs6boUUtf5H/ydCvwmj+EbsE= github.com/anyproto/any-store v0.1.2/go.mod h1:SDlN2AzysAfs8CDd28rrs6boUUtf5H/ydCvwmj+EbsE=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
github.com/anyproto/go-chash v0.1.0/go.mod h1:0UjNQi3PDazP0fINpFYu6VKhuna+W/V+1vpXHAfNgLY= github.com/anyproto/go-chash v0.1.0/go.mod h1:0UjNQi3PDazP0fINpFYu6VKhuna+W/V+1vpXHAfNgLY=
@ -13,6 +14,7 @@ github.com/anyproto/go-slip10 v1.0.0 h1:uAEtSuudR3jJBOfkOXf3bErxVoxbuKwdoJN55M1i
github.com/anyproto/go-slip10 v1.0.0/go.mod h1:BCmIlM1KB8wX6K4/8pOvxPl9oVKfEvZ5vsmO5rkK6vg= github.com/anyproto/go-slip10 v1.0.0/go.mod h1:BCmIlM1KB8wX6K4/8pOvxPl9oVKfEvZ5vsmO5rkK6vg=
github.com/anyproto/go-slip21 v1.0.0 h1:CI7lUqTIwmPOEGVAj4jyNLoICvueh++0U2HoAi3m2ZY= github.com/anyproto/go-slip21 v1.0.0 h1:CI7lUqTIwmPOEGVAj4jyNLoICvueh++0U2HoAi3m2ZY=
github.com/anyproto/go-slip21 v1.0.0/go.mod h1:gbIJt7HAdr5DuT4f2pFTKCBSUWYsm/fysHBNqgsuxT0= github.com/anyproto/go-slip21 v1.0.0/go.mod h1:gbIJt7HAdr5DuT4f2pFTKCBSUWYsm/fysHBNqgsuxT0=
github.com/anyproto/lexid v0.0.2 h1:sYMbqBEOwAK+0JlX360oPPCqV4b2N7NtVhvT4gZD+5w=
github.com/anyproto/lexid v0.0.2/go.mod h1:2RfpYiZkgoNmSDklXdwCCwGlso1FIp9Te8ZtoF3/Ehg= github.com/anyproto/lexid v0.0.2/go.mod h1:2RfpYiZkgoNmSDklXdwCCwGlso1FIp9Te8ZtoF3/Ehg=
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5 h1:aY7tBzQ+z8Hr/v8vOL4/EaKwPZx+J/ClZ1WuD6sqPvE= github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5 h1:aY7tBzQ+z8Hr/v8vOL4/EaKwPZx+J/ClZ1WuD6sqPvE=
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5/go.mod h1:5+PHE01DgsDPkralb8MYmGg2sPQahsqEJ9ue7ciDHKg= github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5/go.mod h1:5+PHE01DgsDPkralb8MYmGg2sPQahsqEJ9ue7ciDHKg=
@ -60,6 +62,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnN
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU= github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU=
github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw= github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw=
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
@ -220,6 +224,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -280,6 +286,8 @@ github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYX
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg= github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw= github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@ -308,6 +316,8 @@ github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
@ -434,5 +444,31 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
storj.io/drpc v0.0.34 h1:q9zlQKfJ5A7x8NQNFk8x7eKUF78FMhmAbZLnFK+og7I= storj.io/drpc v0.0.34 h1:q9zlQKfJ5A7x8NQNFk8x7eKUF78FMhmAbZLnFK+og7I=
storj.io/drpc v0.0.34/go.mod h1:Y9LZaa8esL1PW2IDMqJE7CFSNq7d5bQ3RI7mGPtmKMg= storj.io/drpc v0.0.34/go.mod h1:Y9LZaa8esL1PW2IDMqJE7CFSNq7d5bQ3RI7mGPtmKMg=
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
zombiezen.com/go/sqlite v1.4.0/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=