Implement test utils for space
This commit is contained in:
parent
5532c2c482
commit
9cd73af53c
54
commonspace/spacestorage/inmemoryprovider.go
Normal file
54
commonspace/spacestorage/inmemoryprovider.go
Normal file
@ -0,0 +1,54 @@
|
||||
package spacestorage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/anytypeio/any-sync/app"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func NewInMemorySpaceStorageProvider() SpaceStorageProvider {
|
||||
return &InMemorySpaceStorageProvider{
|
||||
storages: map[string]SpaceStorage{},
|
||||
}
|
||||
}
|
||||
|
||||
type InMemorySpaceStorageProvider struct {
|
||||
storages map[string]SpaceStorage
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorageProvider) Init(a *app.App) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorageProvider) Name() (name string) {
|
||||
return CName
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorageProvider) WaitSpaceStorage(ctx context.Context, id string) (SpaceStorage, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
storage, exists := i.storages[id]
|
||||
if !exists {
|
||||
return nil, ErrSpaceStorageMissing
|
||||
}
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorageProvider) SpaceExists(id string) bool {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
_, exists := i.storages[id]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorageProvider) CreateSpaceStorage(payload SpaceStorageCreatePayload) (SpaceStorage, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
spaceStorage, err := NewInMemorySpaceStorage(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.storages[payload.SpaceHeaderWithId.Id] = spaceStorage
|
||||
return spaceStorage, nil
|
||||
}
|
||||
153
commonspace/spacestorage/inmemorystorage.go
Normal file
153
commonspace/spacestorage/inmemorystorage.go
Normal file
@ -0,0 +1,153 @@
|
||||
package spacestorage
|
||||
|
||||
import (
|
||||
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
|
||||
"github.com/anytypeio/any-sync/commonspace/object/acl/liststorage"
|
||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type InMemorySpaceStorage struct {
|
||||
id string
|
||||
isDeleted bool
|
||||
spaceSettingsId string
|
||||
treeDeleted map[string]string
|
||||
trees map[string]treestorage.TreeStorage
|
||||
aclStorage liststorage.ListStorage
|
||||
spaceHeader *spacesyncproto.RawSpaceHeaderWithId
|
||||
spaceHash string
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func NewInMemorySpaceStorage(payload SpaceStorageCreatePayload) (SpaceStorage, error) {
|
||||
aclStorage, err := liststorage.NewInMemoryAclListStorage(payload.AclWithId.Id, []*aclrecordproto.RawAclRecordWithId{payload.AclWithId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inMemory := &InMemorySpaceStorage{
|
||||
id: payload.SpaceHeaderWithId.Id,
|
||||
spaceSettingsId: payload.SpaceSettingsWithId.Id,
|
||||
treeDeleted: map[string]string{},
|
||||
trees: map[string]treestorage.TreeStorage{},
|
||||
aclStorage: aclStorage,
|
||||
spaceHeader: payload.SpaceHeaderWithId,
|
||||
}
|
||||
_, err = inMemory.CreateTreeStorage(treestorage.TreeStorageCreatePayload{
|
||||
RootRawChange: payload.SpaceSettingsWithId,
|
||||
Changes: []*treechangeproto.RawTreeChangeWithId{payload.SpaceSettingsWithId},
|
||||
Heads: []string{payload.SpaceSettingsWithId.Id},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inMemory, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) Id() string {
|
||||
return i.id
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) SetSpaceDeleted() error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
i.isDeleted = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) IsSpaceDeleted() (bool, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
return i.isDeleted, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) SetTreeDeletedStatus(id, state string) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
i.treeDeleted[id] = state
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) TreeDeletedStatus(id string) (string, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
return i.treeDeleted[id], nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) SpaceSettingsId() string {
|
||||
return i.spaceSettingsId
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) AclStorage() (liststorage.ListStorage, error) {
|
||||
return i.aclStorage, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) SpaceHeader() (*spacesyncproto.RawSpaceHeaderWithId, error) {
|
||||
return i.spaceHeader, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) StoredIds() ([]string, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
var allIds []string
|
||||
for id := range i.trees {
|
||||
allIds = append(allIds, id)
|
||||
}
|
||||
return allIds, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) TreeRoot(id string) (*treechangeproto.RawTreeChangeWithId, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
treeStorage, exists := i.trees[id]
|
||||
if !exists {
|
||||
return nil, treestorage.ErrUnknownTreeId
|
||||
}
|
||||
return treeStorage.Root()
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) TreeStorage(id string) (treestorage.TreeStorage, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
treeStorage, exists := i.trees[id]
|
||||
if !exists {
|
||||
return nil, treestorage.ErrUnknownTreeId
|
||||
}
|
||||
return treeStorage, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) HasTree(id string) (bool, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
_, exists := i.trees[id]
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) CreateTreeStorage(payload treestorage.TreeStorageCreatePayload) (treestorage.TreeStorage, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
storage, err := treestorage.NewInMemoryTreeStorage(payload.RootRawChange, payload.Heads, payload.Changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.trees[payload.RootRawChange.Id] = storage
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) WriteSpaceHash(hash string) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
i.spaceHash = hash
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) ReadSpaceHash() (hash string, err error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
return i.spaceHash, nil
|
||||
}
|
||||
|
||||
func (i *InMemorySpaceStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
317
commonspace/spaceutils_test.go
Normal file
317
commonspace/spaceutils_test.go
Normal file
@ -0,0 +1,317 @@
|
||||
package commonspace
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
accountService "github.com/anytypeio/any-sync/accountservice"
|
||||
"github.com/anytypeio/any-sync/app"
|
||||
"github.com/anytypeio/any-sync/app/ocache"
|
||||
"github.com/anytypeio/any-sync/commonspace/credentialprovider"
|
||||
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/anytypeio/any-sync/commonspace/object/treemanager"
|
||||
"github.com/anytypeio/any-sync/commonspace/peermanager"
|
||||
"github.com/anytypeio/any-sync/commonspace/spacestorage"
|
||||
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
|
||||
"github.com/anytypeio/any-sync/net/peer"
|
||||
"github.com/anytypeio/any-sync/net/pool"
|
||||
"github.com/anytypeio/any-sync/nodeconf"
|
||||
"github.com/anytypeio/any-sync/testutil/accounttest"
|
||||
"github.com/anytypeio/go-chash"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
//
|
||||
// Mock NodeConf implementation
|
||||
//
|
||||
|
||||
type mockConf struct {
|
||||
id string
|
||||
networkId string
|
||||
configuration nodeconf.Configuration
|
||||
}
|
||||
|
||||
func (m *mockConf) Init(a *app.App) (err error) {
|
||||
accountKeys := a.MustComponent(accountService.CName).(accountService.Service).Account()
|
||||
networkId := accountKeys.SignKey.GetPublic().Network()
|
||||
node := nodeconf.Node{
|
||||
PeerId: accountKeys.PeerId,
|
||||
Addresses: []string{"127.0.0.1:4430"},
|
||||
Types: []nodeconf.NodeType{nodeconf.NodeTypeTree},
|
||||
}
|
||||
m.id = networkId
|
||||
m.networkId = networkId
|
||||
m.configuration = nodeconf.Configuration{
|
||||
Id: networkId,
|
||||
NetworkId: networkId,
|
||||
Nodes: []nodeconf.Node{node},
|
||||
CreationTime: time.Now(),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) Name() (name string) {
|
||||
return nodeconf.CName
|
||||
}
|
||||
|
||||
func (m *mockConf) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) Close(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMockConf() *mockConf {
|
||||
return &mockConf{}
|
||||
}
|
||||
|
||||
func (m *mockConf) Id() string {
|
||||
return m.id
|
||||
}
|
||||
|
||||
func (m *mockConf) Configuration() nodeconf.Configuration {
|
||||
return m.configuration
|
||||
}
|
||||
|
||||
func (m *mockConf) NodeIds(spaceId string) []string {
|
||||
var nodeIds []string
|
||||
for _, node := range m.configuration.Nodes {
|
||||
nodeIds = append(nodeIds, node.PeerId)
|
||||
}
|
||||
return nodeIds
|
||||
}
|
||||
|
||||
func (m *mockConf) IsResponsible(spaceId string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *mockConf) FilePeers() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) ConsensusPeers() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) CoordinatorPeers() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) PeerAddresses(peerId string) (addrs []string, ok bool) {
|
||||
if peerId == m.configuration.Nodes[0].PeerId {
|
||||
return m.configuration.Nodes[0].Addresses, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *mockConf) CHash() chash.CHash {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConf) Partition(spaceId string) (part int) {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *mockConf) NodeTypes(nodeId string) []nodeconf.NodeType {
|
||||
if nodeId == m.configuration.Nodes[0].PeerId {
|
||||
return m.configuration.Nodes[0].Types
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// Mock PeerManager implementation
|
||||
//
|
||||
|
||||
type mockPeerManager struct {
|
||||
}
|
||||
|
||||
func (p *mockPeerManager) SendPeer(ctx context.Context, peerId string, msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *mockPeerManager) Broadcast(ctx context.Context, msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *mockPeerManager) GetResponsiblePeers(ctx context.Context) (peers []peer.Peer, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
//
|
||||
// Mock PeerManagerProvider implementation
|
||||
//
|
||||
|
||||
type mockPeerManagerProvider struct {
|
||||
}
|
||||
|
||||
func (m *mockPeerManagerProvider) Init(a *app.App) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockPeerManagerProvider) Name() (name string) {
|
||||
return peermanager.CName
|
||||
}
|
||||
|
||||
func (m *mockPeerManagerProvider) NewPeerManager(ctx context.Context, spaceId string) (sm peermanager.PeerManager, err error) {
|
||||
return &mockPeerManager{}, nil
|
||||
}
|
||||
|
||||
//
|
||||
// Mock Pool implementation
|
||||
//
|
||||
|
||||
type mockPool struct {
|
||||
}
|
||||
|
||||
func (m *mockPool) Init(a *app.App) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockPool) Name() (name string) {
|
||||
return pool.CName
|
||||
}
|
||||
|
||||
func (m *mockPool) Get(ctx context.Context, id string) (peer.Peer, error) {
|
||||
return nil, fmt.Errorf("no such peer")
|
||||
}
|
||||
|
||||
func (m *mockPool) Dial(ctx context.Context, id string) (peer.Peer, error) {
|
||||
return nil, fmt.Errorf("can't dial peer")
|
||||
}
|
||||
|
||||
func (m *mockPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
|
||||
return nil, fmt.Errorf("can't dial peer")
|
||||
}
|
||||
|
||||
func (m *mockPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
|
||||
return nil, fmt.Errorf("can't dial peer")
|
||||
}
|
||||
|
||||
//
|
||||
// Mock Config implementation
|
||||
//
|
||||
|
||||
type mockConfig struct {
|
||||
}
|
||||
|
||||
func (m *mockConfig) Init(a *app.App) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockConfig) Name() (name string) {
|
||||
return "config"
|
||||
}
|
||||
|
||||
func (m *mockConfig) GetSpace() Config {
|
||||
return Config{
|
||||
GCTTL: 60,
|
||||
SyncPeriod: 20,
|
||||
KeepTreeDataInMemory: true,
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Mock TreeManager implementation
|
||||
//
|
||||
|
||||
type mockTreeManager struct {
|
||||
space Space
|
||||
cache ocache.OCache
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) Init(a *app.App) (err error) {
|
||||
t.cache = ocache.New(func(ctx context.Context, id string) (value ocache.Object, err error) {
|
||||
return t.space.BuildTree(ctx, id, BuildTreeOpts{})
|
||||
},
|
||||
ocache.WithGCPeriod(time.Minute),
|
||||
ocache.WithTTL(time.Duration(60)*time.Second))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) Name() (name string) {
|
||||
return treemanager.CName
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) Close(ctx context.Context) (err error) {
|
||||
return t.cache.Close()
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) GetTree(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
val, err := t.cache.Get(ctx, treeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return val.(objecttree.ObjectTree), nil
|
||||
}
|
||||
|
||||
func (t *mockTreeManager) DeleteTree(ctx context.Context, spaceId, treeId string) (err error) {
|
||||
tr, err := t.GetTree(ctx, spaceId, treeId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = tr.Delete()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = t.cache.Remove(ctx, treeId)
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// Space fixture
|
||||
//
|
||||
|
||||
type spaceFixture struct {
|
||||
app *app.App
|
||||
config *mockConfig
|
||||
account accountService.Service
|
||||
configurationService nodeconf.Service
|
||||
storageProvider spacestorage.SpaceStorageProvider
|
||||
peermanagerProvider peermanager.PeerManagerProvider
|
||||
credentialProvider credentialprovider.CredentialProvider
|
||||
treeManager *mockTreeManager
|
||||
pool *mockPool
|
||||
spaceService SpaceService
|
||||
cancelFunc context.CancelFunc
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *spaceFixture {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
fx := &spaceFixture{
|
||||
cancelFunc: cancel,
|
||||
config: &mockConfig{},
|
||||
app: &app.App{},
|
||||
account: &accounttest.AccountTestService{},
|
||||
configurationService: newMockConf(),
|
||||
storageProvider: spacestorage.NewInMemorySpaceStorageProvider(),
|
||||
peermanagerProvider: &mockPeerManagerProvider{},
|
||||
treeManager: &mockTreeManager{},
|
||||
pool: &mockPool{},
|
||||
spaceService: New(),
|
||||
}
|
||||
fx.app.Register(fx.account).
|
||||
Register(fx.config).
|
||||
Register(fx.configurationService).
|
||||
Register(fx.storageProvider).
|
||||
Register(fx.peermanagerProvider).
|
||||
Register(fx.treeManager).
|
||||
Register(fx.pool).
|
||||
Register(fx.spaceService)
|
||||
err := fx.app.Start(ctx)
|
||||
if err != nil {
|
||||
fx.cancelFunc()
|
||||
}
|
||||
require.NoError(t, err)
|
||||
return fx
|
||||
}
|
||||
|
||||
func TestSpace(t *testing.T) {
|
||||
_ = newFixture(t)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user