1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-11 18:20:28 +09:00

Fix deletionstate and settingsobject tests

This commit is contained in:
mcrakhman 2025-02-05 14:27:23 +01:00
parent 4de44b020a
commit 541f96f0cb
No known key found for this signature in database
GPG key ID: DED12CFEF5B8396B
6 changed files with 176 additions and 77 deletions

View file

@ -1,29 +1,32 @@
package deletionstate package deletionstate
import ( import (
"github.com/anyproto/any-sync/commonspace/spacestorage" "context"
"github.com/anyproto/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"sort" "sort"
"testing" "testing"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
"github.com/anyproto/any-sync/commonspace/headsync/headstorage/mock_headstorage"
) )
type fixture struct { type fixture struct {
ctrl *gomock.Controller ctrl *gomock.Controller
delState *objectDeletionState delState *objectDeletionState
spaceStorage *mock_spacestorage.MockSpaceStorage headStorage *mock_headstorage.MockHeadStorage
} }
func newFixture(t *testing.T) *fixture { func newFixture(t *testing.T) *fixture {
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)
spaceStorage := mock_spacestorage.NewMockSpaceStorage(ctrl) headStorage := mock_headstorage.NewMockHeadStorage(ctrl)
delState := New().(*objectDeletionState) delState := New().(*objectDeletionState)
delState.storage = spaceStorage delState.storage = headStorage
return &fixture{ return &fixture{
ctrl: ctrl, ctrl: ctrl,
delState: delState, delState: delState,
spaceStorage: spaceStorage, headStorage: headStorage,
} }
} }
@ -36,28 +39,33 @@ func TestDeletionState_Add(t *testing.T) {
fx := newFixture(t) fx := newFixture(t)
defer fx.stop() defer fx.stop()
id := "newId" id := "newId"
fx.spaceStorage.EXPECT().TreeDeletedStatus(id).Return("", nil) var queued []string
fx.spaceStorage.EXPECT().SetTreeDeletedStatus(id, spacestorage.TreeDeletedStatusQueued).Return(nil) fx.delState.AddObserver(func(ids []string) {
queued = ids
})
fx.headStorage.EXPECT().UpdateEntry(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, update headstorage.HeadsUpdate) error {
require.Equal(t, headstorage.DeletedStatusQueued, *update.DeletedStatus)
return nil
})
fx.delState.Add(map[string]struct{}{id: {}}) fx.delState.Add(map[string]struct{}{id: {}})
require.Contains(t, fx.delState.queued, id) require.Contains(t, fx.delState.queued, id)
require.Equal(t, []string{id}, queued)
}) })
t.Run("add existing queued", func(t *testing.T) { t.Run("add existing queued", func(t *testing.T) {
fx := newFixture(t) fx := newFixture(t)
defer fx.stop() defer fx.stop()
id := "newId" id := "newId"
fx.spaceStorage.EXPECT().TreeDeletedStatus(id).Return(spacestorage.TreeDeletedStatusQueued, nil) fx.delState.queued[id] = struct{}{}
fx.delState.Add(map[string]struct{}{id: {}}) fx.delState.Add(map[string]struct{}{id: {}})
require.Contains(t, fx.delState.queued, id)
}) })
t.Run("add existing deleted", func(t *testing.T) { t.Run("add existing deleted", func(t *testing.T) {
fx := newFixture(t) fx := newFixture(t)
defer fx.stop() defer fx.stop()
id := "newId" id := "newId"
fx.spaceStorage.EXPECT().TreeDeletedStatus(id).Return(spacestorage.TreeDeletedStatusDeleted, nil) fx.delState.deleted[id] = struct{}{}
fx.delState.Add(map[string]struct{}{id: {}}) fx.delState.Add(map[string]struct{}{id: {}})
require.Contains(t, fx.delState.deleted, id)
}) })
} }
@ -84,30 +92,16 @@ func TestDeletionState_FilterJoin(t *testing.T) {
require.Equal(t, []string{"id3"}, filtered) require.Equal(t, []string{"id3"}, filtered)
} }
func TestDeletionState_AddObserver(t *testing.T) {
fx := newFixture(t)
defer fx.stop()
var queued []string
fx.delState.AddObserver(func(ids []string) {
queued = ids
})
id := "newId"
fx.spaceStorage.EXPECT().TreeDeletedStatus(id).Return("", nil)
fx.spaceStorage.EXPECT().SetTreeDeletedStatus(id, spacestorage.TreeDeletedStatusQueued).Return(nil)
fx.delState.Add(map[string]struct{}{id: {}})
require.Contains(t, fx.delState.queued, id)
require.Equal(t, []string{id}, queued)
}
func TestDeletionState_Delete(t *testing.T) { func TestDeletionState_Delete(t *testing.T) {
fx := newFixture(t) fx := newFixture(t)
defer fx.stop() defer fx.stop()
id := "deletedId" id := "deletedId"
fx.delState.queued[id] = struct{}{} fx.delState.queued[id] = struct{}{}
fx.spaceStorage.EXPECT().SetTreeDeletedStatus(id, spacestorage.TreeDeletedStatusDeleted).Return(nil) fx.headStorage.EXPECT().UpdateEntry(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, update headstorage.HeadsUpdate) error {
require.Equal(t, headstorage.DeletedStatusDeleted, *update.DeletedStatus)
return nil
})
err := fx.delState.Delete(id) err := fx.delState.Delete(id)
require.NoError(t, err) require.NoError(t, err)
require.Contains(t, fx.delState.deleted, id) require.Contains(t, fx.delState.deleted, id)

View file

@ -0,0 +1,96 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anyproto/any-sync/commonspace/headsync/statestorage (interfaces: StateStorage)
//
// Generated by this command:
//
// mockgen -destination mock_statestorage/mock_statestorage.go github.com/anyproto/any-sync/commonspace/headsync/statestorage StateStorage
//
// Package mock_statestorage is a generated GoMock package.
package mock_statestorage
import (
context "context"
reflect "reflect"
statestorage "github.com/anyproto/any-sync/commonspace/headsync/statestorage"
gomock "go.uber.org/mock/gomock"
)
// MockStateStorage is a mock of StateStorage interface.
type MockStateStorage struct {
ctrl *gomock.Controller
recorder *MockStateStorageMockRecorder
}
// MockStateStorageMockRecorder is the mock recorder for MockStateStorage.
type MockStateStorageMockRecorder struct {
mock *MockStateStorage
}
// NewMockStateStorage creates a new mock instance.
func NewMockStateStorage(ctrl *gomock.Controller) *MockStateStorage {
mock := &MockStateStorage{ctrl: ctrl}
mock.recorder = &MockStateStorageMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockStateStorage) EXPECT() *MockStateStorageMockRecorder {
return m.recorder
}
// GetState mocks base method.
func (m *MockStateStorage) GetState(arg0 context.Context) (statestorage.State, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetState", arg0)
ret0, _ := ret[0].(statestorage.State)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetState indicates an expected call of GetState.
func (mr *MockStateStorageMockRecorder) GetState(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetState", reflect.TypeOf((*MockStateStorage)(nil).GetState), arg0)
}
// SetHash mocks base method.
func (m *MockStateStorage) SetHash(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetHash", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// SetHash indicates an expected call of SetHash.
func (mr *MockStateStorageMockRecorder) SetHash(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHash", reflect.TypeOf((*MockStateStorage)(nil).SetHash), arg0, arg1)
}
// SetObserver mocks base method.
func (m *MockStateStorage) SetObserver(arg0 statestorage.Observer) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetObserver", arg0)
}
// SetObserver indicates an expected call of SetObserver.
func (mr *MockStateStorageMockRecorder) SetObserver(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetObserver", reflect.TypeOf((*MockStateStorage)(nil).SetObserver), arg0)
}
// SettingsId mocks base method.
func (m *MockStateStorage) SettingsId() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SettingsId")
ret0, _ := ret[0].(string)
return ret0
}
// SettingsId indicates an expected call of SettingsId.
func (mr *MockStateStorageMockRecorder) SettingsId() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SettingsId", reflect.TypeOf((*MockStateStorage)(nil).SettingsId))
}

View file

@ -1,3 +1,4 @@
//go:generate mockgen -destination mock_statestorage/mock_statestorage.go github.com/anyproto/any-sync/commonspace/headsync/statestorage StateStorage
package statestorage package statestorage
import ( import (

View file

@ -2,24 +2,29 @@ package settings
import ( import (
"context" "context"
"sync"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"github.com/anyproto/any-sync/accountservice/mock_accountservice" "github.com/anyproto/any-sync/accountservice/mock_accountservice"
"github.com/anyproto/any-sync/commonspace/deletionmanager/mock_deletionmanager" "github.com/anyproto/any-sync/commonspace/deletionmanager/mock_deletionmanager"
"github.com/anyproto/any-sync/commonspace/headsync/headstorage"
"github.com/anyproto/any-sync/commonspace/headsync/headstorage/mock_headstorage"
"github.com/anyproto/any-sync/commonspace/headsync/statestorage"
"github.com/anyproto/any-sync/commonspace/headsync/statestorage/mock_statestorage"
"github.com/anyproto/any-sync/commonspace/object/accountdata" "github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree" "github.com/anyproto/any-sync/commonspace/object/tree/synctree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree" "github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree"
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/updatelistener" "github.com/anyproto/any-sync/commonspace/object/tree/synctree/updatelistener"
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager" "github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager"
"github.com/anyproto/any-sync/commonspace/settings/settingsstate" "github.com/anyproto/any-sync/commonspace/settings/settingsstate"
"github.com/anyproto/any-sync/commonspace/settings/settingsstate/mock_settingsstate" "github.com/anyproto/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/anyproto/any-sync/commonspace/spacestorage/mock_spacestorage" "github.com/anyproto/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"sync"
"testing"
"time"
) )
type testSyncTreeMock struct { type testSyncTreeMock struct {
@ -54,8 +59,12 @@ type settingsFixture struct {
syncTree *mock_synctree.MockSyncTree syncTree *mock_synctree.MockSyncTree
historyTree *mock_objecttree.MockObjectTree historyTree *mock_objecttree.MockObjectTree
account *mock_accountservice.MockService account *mock_accountservice.MockService
stateStorage *mock_statestorage.MockStateStorage
headStorage *mock_headstorage.MockHeadStorage
} }
var ctx = context.Background()
func newSettingsFixture(t *testing.T) *settingsFixture { func newSettingsFixture(t *testing.T) *settingsFixture {
spaceId := "spaceId" spaceId := "spaceId"
objectId := "objectId" objectId := "objectId"
@ -69,6 +78,8 @@ func newSettingsFixture(t *testing.T) *settingsFixture {
changeFactory := mock_settingsstate.NewMockChangeFactory(ctrl) changeFactory := mock_settingsstate.NewMockChangeFactory(ctrl)
syncTree := mock_synctree.NewMockSyncTree(ctrl) syncTree := mock_synctree.NewMockSyncTree(ctrl)
historyTree := mock_objecttree.NewMockObjectTree(ctrl) historyTree := mock_objecttree.NewMockObjectTree(ctrl)
stateStorage := mock_statestorage.NewMockStateStorage(ctrl)
headStorage := mock_headstorage.NewMockHeadStorage(ctrl)
buildFunc := BuildTreeFunc(func(ctx context.Context, id string, listener updatelistener.UpdateListener) (synctree.SyncTree, error) { buildFunc := BuildTreeFunc(func(ctx context.Context, id string, listener updatelistener.UpdateListener) (synctree.SyncTree, error) {
require.Equal(t, objectId, id) require.Equal(t, objectId, id)
@ -101,11 +112,17 @@ func newSettingsFixture(t *testing.T) *settingsFixture {
syncTree: syncTree, syncTree: syncTree,
account: acc, account: acc,
historyTree: historyTree, historyTree: historyTree,
stateStorage: stateStorage,
headStorage: headStorage,
} }
} }
func (fx *settingsFixture) init(t *testing.T) { func (fx *settingsFixture) init(t *testing.T) {
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId) fx.spaceStorage.EXPECT().StateStorage().AnyTimes().Return(fx.stateStorage)
fx.stateStorage.EXPECT().GetState(gomock.Any()).Return(statestorage.State{
SettingsId: fx.docId,
}, nil)
fx.spaceStorage.EXPECT().HeadStorage().AnyTimes().Return(fx.headStorage)
fx.stateBuilder.EXPECT().Build(fx.historyTree, nil).Return(&settingsstate.State{}, nil) fx.stateBuilder.EXPECT().Build(fx.historyTree, nil).Return(&settingsstate.State{}, nil)
fx.doc.state = &settingsstate.State{} fx.doc.state = &settingsstate.State{}
@ -129,24 +146,18 @@ func TestSettingsObject_Init(t *testing.T) {
} }
func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) { func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return false, nil
}
fx := newSettingsFixture(t) fx := newSettingsFixture(t)
defer fx.stop(t) defer fx.stop(t)
fx.init(t) fx.init(t)
delId := "delId" delId := "delId"
DoSnapshot = func(len int) bool { DoSnapshot = func(len int) bool {
return false return false
} }
fx.syncTree.EXPECT().Id().Return("syncId") fx.syncTree.EXPECT().Id().Return("syncId")
fx.syncTree.EXPECT().Len().Return(10) fx.syncTree.EXPECT().Len().Return(10)
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl) fx.headStorage.EXPECT().GetEntry(gomock.Any(), gomock.Any()).Return(headstorage.HeadsEntry{
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil) IsDerived: false,
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil) }, nil)
res := []byte("settingsData") res := []byte("settingsData")
fx.doc.state = &settingsstate.State{LastIteratedId: "someId"} fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, false).Return(res, nil) fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, false).Return(res, nil)
@ -163,14 +174,11 @@ func TestSettingsObject_DeleteObject_NoSnapshot(t *testing.T) {
fx.stateBuilder.EXPECT().Build(fx.doc, fx.doc.state).Return(fx.doc.state, nil) fx.stateBuilder.EXPECT().Build(fx.doc, fx.doc.state).Return(fx.doc.state, nil)
fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil) fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil)
err = fx.doc.DeleteObject(delId) err = fx.doc.DeleteObject(ctx, delId)
require.NoError(t, err) require.NoError(t, err)
} }
func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) { func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return false, nil
}
fx := newSettingsFixture(t) fx := newSettingsFixture(t)
defer fx.stop(t) defer fx.stop(t)
fx.init(t) fx.init(t)
@ -178,12 +186,11 @@ func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
DoSnapshot = func(len int) bool { DoSnapshot = func(len int) bool {
return true return true
} }
fx.syncTree.EXPECT().Id().Return("syncId") fx.syncTree.EXPECT().Id().Return("syncId")
fx.syncTree.EXPECT().Len().Return(10) fx.syncTree.EXPECT().Len().Return(10)
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl) fx.headStorage.EXPECT().GetEntry(gomock.Any(), gomock.Any()).Return(headstorage.HeadsEntry{
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil) IsDerived: false,
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil) }, nil)
res := []byte("settingsData") res := []byte("settingsData")
fx.doc.state = &settingsstate.State{LastIteratedId: "someId"} fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, true).Return(res, nil) fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, true).Return(res, nil)
@ -196,31 +203,28 @@ func TestSettingsObject_DeleteObject_WithSnapshot(t *testing.T) {
Key: accountData.SignKey, Key: accountData.SignKey,
IsSnapshot: true, IsSnapshot: true,
IsEncrypted: false, IsEncrypted: false,
}).Return(objecttree.AddResult{Mode: objecttree.Rebuild}, nil) }).Return(objecttree.AddResult{}, nil)
fx.stateBuilder.EXPECT().Build(fx.doc, nil).Return(fx.doc.state, nil) fx.stateBuilder.EXPECT().Build(fx.doc, fx.doc.state).Return(fx.doc.state, nil)
fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil) fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil)
err = fx.doc.DeleteObject(delId) err = fx.doc.DeleteObject(ctx, delId)
require.NoError(t, err) require.NoError(t, err)
} }
func TestSettingsObject_DeleteDerivedObject(t *testing.T) { func TestSettingsObject_DeleteDerivedObject(t *testing.T) {
isDerivedRoot = func(root *treechangeproto.RawTreeChangeWithId) (derived bool, err error) {
return true, nil
}
fx := newSettingsFixture(t) fx := newSettingsFixture(t)
defer fx.stop(t) defer fx.stop(t)
fx.init(t) fx.init(t)
delId := "delId" delId := "delId"
DoSnapshot = func(len int) bool { DoSnapshot = func(len int) bool {
return true return false
} }
fx.syncTree.EXPECT().Id().Return("syncId") fx.syncTree.EXPECT().Id().Return("syncId")
treeStorageMock := mock_treestorage.NewMockTreeStorage(fx.ctrl) fx.headStorage.EXPECT().GetEntry(gomock.Any(), gomock.Any()).Return(headstorage.HeadsEntry{
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(treeStorageMock, nil) IsDerived: true,
treeStorageMock.EXPECT().Root().Return(&treechangeproto.RawTreeChangeWithId{}, nil) }, nil)
err := fx.doc.DeleteObject(delId) fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
err := fx.doc.DeleteObject(ctx, delId)
require.Equal(t, ErrCantDeleteDerivedObject, err) require.Equal(t, ErrCantDeleteDerivedObject, err)
} }

View file

@ -1,11 +1,13 @@
package settingsstate package settingsstate
import ( import (
"github.com/anyproto/any-sync/commonspace/spacesyncproto" "testing"
"github.com/anyproto/protobuf/proto" "github.com/anyproto/protobuf/proto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"testing"
"github.com/anyproto/any-sync/commonspace/spacesyncproto"
) )
func TestChangeFactory_CreateObjectDeleteChange(t *testing.T) { func TestChangeFactory_CreateObjectDeleteChange(t *testing.T) {

View file

@ -2,13 +2,15 @@ package settingsstate
import ( import (
"fmt" "fmt"
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"github.com/anyproto/any-sync/commonspace/object/accountdata" "github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree" "github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
"github.com/anyproto/any-sync/commonspace/spacesyncproto" "github.com/anyproto/any-sync/commonspace/spacesyncproto"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"testing"
) )
func TestStateBuilder_ProcessChange(t *testing.T) { func TestStateBuilder_ProcessChange(t *testing.T) {