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
|
||||
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 {
|
||||
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 {
|
||||
@ -141,7 +141,7 @@ func (p *mockPeerManager) GetResponsiblePeers(ctx context.Context) (peers []peer
|
||||
}
|
||||
|
||||
//
|
||||
// Mock PeerManagerProvider implementation
|
||||
// Mock PeerManagerProvider
|
||||
//
|
||||
|
||||
type mockPeerManagerProvider struct {
|
||||
@ -160,7 +160,7 @@ func (m *mockPeerManagerProvider) NewPeerManager(ctx context.Context, spaceId st
|
||||
}
|
||||
|
||||
//
|
||||
// Mock Pool implementation
|
||||
// Mock Pool
|
||||
//
|
||||
|
||||
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 {
|
||||
@ -214,12 +214,13 @@ func (m *mockConfig) GetSpace() Config {
|
||||
}
|
||||
|
||||
//
|
||||
// Mock TreeManager implementation
|
||||
// Mock TreeManager
|
||||
//
|
||||
|
||||
type mockTreeManager struct {
|
||||
space Space
|
||||
cache ocache.OCache
|
||||
deletedIds []string
|
||||
}
|
||||
|
||||
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 {
|
||||
return
|
||||
}
|
||||
t.deletedIds = append(t.deletedIds, treeId)
|
||||
_, err = t.cache.Remove(ctx, treeId)
|
||||
return nil
|
||||
}
|
||||
@ -311,7 +313,3 @@ func newFixture(t *testing.T) *spaceFixture {
|
||||
require.NoError(t, err)
|
||||
return fx
|
||||
}
|
||||
|
||||
func TestSpace(t *testing.T) {
|
||||
_ = newFixture(t)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user