Add tests
This commit is contained in:
parent
9cd73af53c
commit
c348ee2a49
184
commonspace/deletion_test.go
Normal file
184
commonspace/deletion_test.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package commonspace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/object/accountdata"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/settings"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
|
||||||
|
"github.com/anytypeio/any-sync/commonspace/spacestorage"
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addIncorrectSnapshot(settingsObject settings.SettingsObject, acc *accountdata.AccountKeys, partialIds []string, newId string) (err error) {
|
||||||
|
factory := settingsstate.NewChangeFactory()
|
||||||
|
bytes, err := factory.CreateObjectDeleteChange(newId, &settingsstate.State{DeletedIds: partialIds}, true)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch, err := settingsObject.PrepareChange(objecttree.SignableChangeContent{
|
||||||
|
Data: bytes,
|
||||||
|
Key: acc.SignKey,
|
||||||
|
IsSnapshot: true,
|
||||||
|
IsEncrypted: false,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res, err := settingsObject.AddRawChanges(context.Background(), objecttree.RawChangesPayload{
|
||||||
|
NewHeads: []string{ch.Id},
|
||||||
|
RawChanges: []*treechangeproto.RawTreeChangeWithId{ch},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if res.Mode != objecttree.Rebuild {
|
||||||
|
return fmt.Errorf("incorrect mode: %d", res.Mode)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpaceDeleteIds(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
acc := fx.account.Account()
|
||||||
|
rk := crypto.NewAES()
|
||||||
|
ctx := context.Background()
|
||||||
|
totalObjs := 3000
|
||||||
|
|
||||||
|
// creating space
|
||||||
|
sp, err := fx.spaceService.CreateSpace(ctx, SpaceCreatePayload{
|
||||||
|
SigningKey: acc.SignKey,
|
||||||
|
SpaceType: "type",
|
||||||
|
ReadKey: rk.Bytes(),
|
||||||
|
ReplicationKey: 10,
|
||||||
|
MasterKey: acc.PeerKey,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, sp)
|
||||||
|
|
||||||
|
// initializing space
|
||||||
|
spc, err := fx.spaceService.NewSpace(ctx, sp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, spc)
|
||||||
|
err = spc.Init(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
// adding space to tree manager
|
||||||
|
fx.treeManager.space = spc
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
for i := 0; i < totalObjs; i++ {
|
||||||
|
// creating a tree
|
||||||
|
bytes := make([]byte, 32)
|
||||||
|
rand.Read(bytes)
|
||||||
|
doc, err := spc.CreateTree(ctx, objecttree.ObjectTreeCreatePayload{
|
||||||
|
PrivKey: acc.SignKey,
|
||||||
|
ChangeType: "some",
|
||||||
|
SpaceId: spc.Id(),
|
||||||
|
IsEncrypted: false,
|
||||||
|
Seed: bytes,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
tr, err := spc.PutTree(ctx, doc, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
ids = append(ids, tr.Id())
|
||||||
|
tr.Close()
|
||||||
|
}
|
||||||
|
// deleting trees
|
||||||
|
for _, id := range ids {
|
||||||
|
err = spc.DeleteTree(ctx, id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
spc.Close()
|
||||||
|
require.Equal(t, len(ids), len(fx.treeManager.deletedIds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpaceDeleteIdsIncorrectSnapshot(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
acc := fx.account.Account()
|
||||||
|
rk := crypto.NewAES()
|
||||||
|
ctx := context.Background()
|
||||||
|
totalObjs := 3000
|
||||||
|
partialObjs := 300
|
||||||
|
|
||||||
|
// creating space
|
||||||
|
sp, err := fx.spaceService.CreateSpace(ctx, SpaceCreatePayload{
|
||||||
|
SigningKey: acc.SignKey,
|
||||||
|
SpaceType: "type",
|
||||||
|
ReadKey: rk.Bytes(),
|
||||||
|
ReplicationKey: 10,
|
||||||
|
MasterKey: acc.PeerKey,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, sp)
|
||||||
|
|
||||||
|
// initializing space
|
||||||
|
spc, err := fx.spaceService.NewSpace(ctx, sp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, spc)
|
||||||
|
err = spc.Init(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
// adding space to tree manager
|
||||||
|
fx.treeManager.space = spc
|
||||||
|
|
||||||
|
settingsObject := spc.(*space).settingsObject
|
||||||
|
var ids []string
|
||||||
|
for i := 0; i < totalObjs; i++ {
|
||||||
|
// creating a tree
|
||||||
|
bytes := make([]byte, 32)
|
||||||
|
rand.Read(bytes)
|
||||||
|
doc, err := spc.CreateTree(ctx, objecttree.ObjectTreeCreatePayload{
|
||||||
|
PrivKey: acc.SignKey,
|
||||||
|
ChangeType: "some",
|
||||||
|
SpaceId: spc.Id(),
|
||||||
|
IsEncrypted: false,
|
||||||
|
Seed: bytes,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
tr, err := spc.PutTree(ctx, doc, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
ids = append(ids, tr.Id())
|
||||||
|
tr.Close()
|
||||||
|
}
|
||||||
|
// copying storage, so we will have all the trees locally
|
||||||
|
inmemory := spc.Storage().(*commonStorage).SpaceStorage.(*spacestorage.InMemorySpaceStorage)
|
||||||
|
storageCopy := inmemory.CopyStorage()
|
||||||
|
treesCopy := inmemory.AllTrees()
|
||||||
|
|
||||||
|
// deleting trees
|
||||||
|
for _, id := range ids {
|
||||||
|
err = spc.DeleteTree(ctx, id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
// adding snapshot that breaks the state
|
||||||
|
err = addIncorrectSnapshot(settingsObject, acc, ids[:partialObjs], ids[partialObjs])
|
||||||
|
require.NoError(t, err)
|
||||||
|
// copying the contents of the settings tree
|
||||||
|
treesCopy[settingsObject.Id()] = settingsObject.Storage()
|
||||||
|
storageCopy.SetTrees(treesCopy)
|
||||||
|
spc.Close()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
// now we replace the storage, so the trees are back, but the settings object says that they are deleted
|
||||||
|
fx.storageProvider.(*spacestorage.InMemorySpaceStorageProvider).SetStorage(storageCopy)
|
||||||
|
|
||||||
|
spc, err = fx.spaceService.NewSpace(ctx, sp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, spc)
|
||||||
|
err = spc.Init(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fx.treeManager.space = spc
|
||||||
|
fx.treeManager.deletedIds = nil
|
||||||
|
|
||||||
|
// waiting until everything is deleted
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
require.Equal(t, len(ids), len(fx.treeManager.deletedIds))
|
||||||
|
}
|
||||||
@ -52,3 +52,9 @@ func (i *InMemorySpaceStorageProvider) CreateSpaceStorage(payload SpaceStorageCr
|
|||||||
i.storages[payload.SpaceHeaderWithId.Id] = spaceStorage
|
i.storages[payload.SpaceHeaderWithId.Id] = spaceStorage
|
||||||
return spaceStorage, nil
|
return spaceStorage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *InMemorySpaceStorageProvider) SetStorage(storage SpaceStorage) {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
i.storages[storage.Id()] = storage
|
||||||
|
}
|
||||||
|
|||||||
@ -151,3 +151,43 @@ func (i *InMemorySpaceStorage) ReadSpaceHash() (hash string, err error) {
|
|||||||
func (i *InMemorySpaceStorage) Close() error {
|
func (i *InMemorySpaceStorage) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *InMemorySpaceStorage) AllTrees() map[string]treestorage.TreeStorage {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
cp := map[string]treestorage.TreeStorage{}
|
||||||
|
for id, store := range i.trees {
|
||||||
|
cp[id] = store
|
||||||
|
}
|
||||||
|
return cp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InMemorySpaceStorage) SetTrees(trees map[string]treestorage.TreeStorage) {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
i.trees = trees
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InMemorySpaceStorage) CopyStorage() *InMemorySpaceStorage {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
copyTreeDeleted := map[string]string{}
|
||||||
|
for id, status := range i.treeDeleted {
|
||||||
|
copyTreeDeleted[id] = status
|
||||||
|
}
|
||||||
|
copyTrees := map[string]treestorage.TreeStorage{}
|
||||||
|
for id, store := range i.trees {
|
||||||
|
copyTrees[id] = store
|
||||||
|
}
|
||||||
|
return &InMemorySpaceStorage{
|
||||||
|
id: i.id,
|
||||||
|
isDeleted: i.isDeleted,
|
||||||
|
spaceSettingsId: i.spaceSettingsId,
|
||||||
|
treeDeleted: copyTreeDeleted,
|
||||||
|
trees: copyTrees,
|
||||||
|
aclStorage: i.aclStorage,
|
||||||
|
spaceHeader: i.spaceHeader,
|
||||||
|
spaceHash: i.spaceHash,
|
||||||
|
Mutex: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -122,7 +122,7 @@ func (m *mockConf) NodeTypes(nodeId string) []nodeconf.NodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mock PeerManager implementation
|
// Mock PeerManager
|
||||||
//
|
//
|
||||||
|
|
||||||
type mockPeerManager struct {
|
type mockPeerManager struct {
|
||||||
@ -141,7 +141,7 @@ func (p *mockPeerManager) GetResponsiblePeers(ctx context.Context) (peers []peer
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mock PeerManagerProvider implementation
|
// Mock PeerManagerProvider
|
||||||
//
|
//
|
||||||
|
|
||||||
type mockPeerManagerProvider struct {
|
type mockPeerManagerProvider struct {
|
||||||
@ -160,7 +160,7 @@ func (m *mockPeerManagerProvider) NewPeerManager(ctx context.Context, spaceId st
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mock Pool implementation
|
// Mock Pool
|
||||||
//
|
//
|
||||||
|
|
||||||
type mockPool struct {
|
type mockPool struct {
|
||||||
@ -191,7 +191,7 @@ func (m *mockPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mock Config implementation
|
// Mock Config
|
||||||
//
|
//
|
||||||
|
|
||||||
type mockConfig struct {
|
type mockConfig struct {
|
||||||
@ -214,12 +214,13 @@ func (m *mockConfig) GetSpace() Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mock TreeManager implementation
|
// Mock TreeManager
|
||||||
//
|
//
|
||||||
|
|
||||||
type mockTreeManager struct {
|
type mockTreeManager struct {
|
||||||
space Space
|
space Space
|
||||||
cache ocache.OCache
|
cache ocache.OCache
|
||||||
|
deletedIds []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mockTreeManager) Init(a *app.App) (err error) {
|
func (t *mockTreeManager) Init(a *app.App) (err error) {
|
||||||
@ -260,6 +261,7 @@ func (t *mockTreeManager) DeleteTree(ctx context.Context, spaceId, treeId string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
t.deletedIds = append(t.deletedIds, treeId)
|
||||||
_, err = t.cache.Remove(ctx, treeId)
|
_, err = t.cache.Remove(ctx, treeId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -311,7 +313,3 @@ func newFixture(t *testing.T) *spaceFixture {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return fx
|
return fx
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSpace(t *testing.T) {
|
|
||||||
_ = newFixture(t)
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user