diff --git a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go index ca4789f1..792dbee7 100644 --- a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go +++ b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/anyproto/any-sync/commonspace/object/tree/synctree (interfaces: SyncTree,ReceiveQueue,HeadNotifiable,SyncClient,RequestFactory) +// Source: github.com/anyproto/any-sync/commonspace/object/tree/synctree (interfaces: SyncTree,ReceiveQueue,HeadNotifiable,SyncClient,RequestFactory,TreeSyncProtocol) // Package mock_synctree is a generated GoMock package. package mock_synctree @@ -822,3 +822,70 @@ func (mr *MockRequestFactoryMockRecorder) CreateNewTreeRequest() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNewTreeRequest", reflect.TypeOf((*MockRequestFactory)(nil).CreateNewTreeRequest)) } + +// MockTreeSyncProtocol is a mock of TreeSyncProtocol interface. +type MockTreeSyncProtocol struct { + ctrl *gomock.Controller + recorder *MockTreeSyncProtocolMockRecorder +} + +// MockTreeSyncProtocolMockRecorder is the mock recorder for MockTreeSyncProtocol. +type MockTreeSyncProtocolMockRecorder struct { + mock *MockTreeSyncProtocol +} + +// NewMockTreeSyncProtocol creates a new mock instance. +func NewMockTreeSyncProtocol(ctrl *gomock.Controller) *MockTreeSyncProtocol { + mock := &MockTreeSyncProtocol{ctrl: ctrl} + mock.recorder = &MockTreeSyncProtocolMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockTreeSyncProtocol) EXPECT() *MockTreeSyncProtocolMockRecorder { + return m.recorder +} + +// FullSyncRequest mocks base method. +func (m *MockTreeSyncProtocol) FullSyncRequest(arg0 context.Context, arg1 string, arg2 *treechangeproto.TreeFullSyncRequest) (*treechangeproto.TreeSyncMessage, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FullSyncRequest", arg0, arg1, arg2) + ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FullSyncRequest indicates an expected call of FullSyncRequest. +func (mr *MockTreeSyncProtocolMockRecorder) FullSyncRequest(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullSyncRequest", reflect.TypeOf((*MockTreeSyncProtocol)(nil).FullSyncRequest), arg0, arg1, arg2) +} + +// FullSyncResponse mocks base method. +func (m *MockTreeSyncProtocol) FullSyncResponse(arg0 context.Context, arg1 string, arg2 *treechangeproto.TreeFullSyncResponse) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FullSyncResponse", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// FullSyncResponse indicates an expected call of FullSyncResponse. +func (mr *MockTreeSyncProtocolMockRecorder) FullSyncResponse(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullSyncResponse", reflect.TypeOf((*MockTreeSyncProtocol)(nil).FullSyncResponse), arg0, arg1, arg2) +} + +// HeadUpdate mocks base method. +func (m *MockTreeSyncProtocol) HeadUpdate(arg0 context.Context, arg1 string, arg2 *treechangeproto.TreeHeadUpdate) (*treechangeproto.TreeSyncMessage, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeadUpdate", arg0, arg1, arg2) + ret0, _ := ret[0].(*treechangeproto.TreeSyncMessage) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeadUpdate indicates an expected call of HeadUpdate. +func (mr *MockTreeSyncProtocolMockRecorder) HeadUpdate(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeadUpdate", reflect.TypeOf((*MockTreeSyncProtocol)(nil).HeadUpdate), arg0, arg1, arg2) +} diff --git a/commonspace/object/tree/synctree/synctree.go b/commonspace/object/tree/synctree/synctree.go index f8558992..cd6ff7a2 100644 --- a/commonspace/object/tree/synctree/synctree.go +++ b/commonspace/object/tree/synctree/synctree.go @@ -1,4 +1,4 @@ -//go:generate mockgen -destination mock_synctree/mock_synctree.go github.com/anyproto/any-sync/commonspace/object/tree/synctree SyncTree,ReceiveQueue,HeadNotifiable,SyncClient,RequestFactory +//go:generate mockgen -destination mock_synctree/mock_synctree.go github.com/anyproto/any-sync/commonspace/object/tree/synctree SyncTree,ReceiveQueue,HeadNotifiable,SyncClient,RequestFactory,TreeSyncProtocol package synctree import ( diff --git a/commonspace/object/tree/synctree/synctreehandler_test.go b/commonspace/object/tree/synctree/synctreehandler_test.go index f029b092..f03f5ff1 100644 --- a/commonspace/object/tree/synctree/synctreehandler_test.go +++ b/commonspace/object/tree/synctree/synctreehandler_test.go @@ -2,19 +2,15 @@ package synctree import ( "context" - "fmt" - "github.com/anyproto/any-sync/commonspace/objectsync/mock_objectsync" + "github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree" + "github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto" + "github.com/stretchr/testify/require" "sync" "testing" - "github.com/anyproto/any-sync/app/logger" - "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/treechangeproto" "github.com/anyproto/any-sync/commonspace/syncstatus" "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" ) type testObjTreeMock struct { @@ -54,9 +50,13 @@ func (t *testObjTreeMock) TryRLock() bool { type syncHandlerFixture struct { ctrl *gomock.Controller - syncClientMock *mock_objectsync.MockSyncClient + syncClientMock *mock_synctree.MockSyncClient objectTreeMock *testObjTreeMock receiveQueueMock ReceiveQueue + syncProtocolMock *mock_synctree.MockTreeSyncProtocol + spaceId string + senderId string + treeId string syncHandler *syncTreeHandler } @@ -64,19 +64,29 @@ type syncHandlerFixture struct { func newSyncHandlerFixture(t *testing.T) *syncHandlerFixture { ctrl := gomock.NewController(t) objectTreeMock := newTestObjMock(mock_objecttree.NewMockObjectTree(ctrl)) + syncClientMock := mock_synctree.NewMockSyncClient(ctrl) + syncProtocolMock := mock_synctree.NewMockTreeSyncProtocol(ctrl) + spaceId := "spaceId" receiveQueue := newReceiveQueue(5) syncHandler := &syncTreeHandler{ - objTree: objectTreeMock, - //syncClient: syncClientMock, - queue: receiveQueue, - syncStatus: syncstatus.NewNoOpSyncStatus(), + objTree: objectTreeMock, + syncClient: syncClientMock, + syncProtocol: syncProtocolMock, + spaceId: spaceId, + queue: receiveQueue, + syncStatus: syncstatus.NewNoOpSyncStatus(), } return &syncHandlerFixture{ ctrl: ctrl, objectTreeMock: objectTreeMock, receiveQueueMock: receiveQueue, + syncProtocolMock: syncProtocolMock, + syncClientMock: syncClientMock, syncHandler: syncHandler, + spaceId: spaceId, + senderId: "senderId", + treeId: "treeId", } } @@ -84,341 +94,128 @@ func (fx *syncHandlerFixture) stop() { fx.ctrl.Finish() } -func TestSyncHandler_HandleHeadUpdate(t *testing.T) { +func TestSyncTreeHandler_HandleMessage(t *testing.T) { ctx := context.Background() - log = logger.CtxLogger{Logger: zap.NewNop()} - fullRequest := &treechangeproto.TreeSyncMessage{ - Content: &treechangeproto.TreeSyncContentValue{ - Value: &treechangeproto.TreeSyncContentValue_FullSyncRequest{ - FullSyncRequest: &treechangeproto.TreeFullSyncRequest{}, - }, - }, - } - t.Run("head update non empty all heads added", func(t *testing.T) { + t.Run("handle head update message", func(t *testing.T) { fx := newSyncHandlerFixture(t) defer fx.stop() treeId := "treeId" - senderId := "senderId" chWithId := &treechangeproto.RawTreeChangeWithId{} - headUpdate := &treechangeproto.TreeHeadUpdate{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } + headUpdate := &treechangeproto.TreeHeadUpdate{} treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h2"}).Times(2) - fx.objectTreeMock.EXPECT().HasChanges(gomock.Eq([]string{"h1"})).Return(false) - fx.objectTreeMock.EXPECT(). - AddRawChanges(gomock.Any(), gomock.Eq(objecttree.RawChangesPayload{ - NewHeads: []string{"h1"}, - RawChanges: []*treechangeproto.RawTreeChangeWithId{chWithId}, - })). - Return(objecttree.AddResult{}, nil) - fx.objectTreeMock.EXPECT().HasChanges(gomock.Eq([]string{"h1"})).Return(true) + syncReq := &treechangeproto.TreeSyncMessage{} + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) + fx.syncProtocolMock.EXPECT().HeadUpdate(ctx, fx.senderId, gomock.Any()).Return(syncReq, nil) + fx.syncClientMock.EXPECT().QueueRequest(fx.senderId, fx.treeId, syncReq).Return(nil) - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) + err := fx.syncHandler.HandleMessage(ctx, fx.senderId, objectMsg) require.NoError(t, err) }) - t.Run("head update non empty heads not added", func(t *testing.T) { + t.Run("handle head update message, empty sync request", func(t *testing.T) { fx := newSyncHandlerFixture(t) defer fx.stop() treeId := "treeId" - senderId := "senderId" chWithId := &treechangeproto.RawTreeChangeWithId{} - headUpdate := &treechangeproto.TreeHeadUpdate{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } + headUpdate := &treechangeproto.TreeHeadUpdate{} treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h2"}).AnyTimes() - fx.objectTreeMock.EXPECT().HasChanges(gomock.Eq([]string{"h1"})).Return(false) - fx.objectTreeMock.EXPECT(). - AddRawChanges(gomock.Any(), gomock.Eq(objecttree.RawChangesPayload{ - NewHeads: []string{"h1"}, - RawChanges: []*treechangeproto.RawTreeChangeWithId{chWithId}, - })). - Return(objecttree.AddResult{}, nil) - fx.objectTreeMock.EXPECT().HasChanges(gomock.Eq([]string{"h1"})).Return(false) - fx.syncClientMock.EXPECT(). - CreateFullSyncRequest(gomock.Eq(fx.objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})). - Return(fullRequest, nil) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Eq(fullRequest), gomock.Eq("")) + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) + fx.syncProtocolMock.EXPECT().HeadUpdate(ctx, fx.senderId, gomock.Any()).Return(nil, nil) - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) + err := fx.syncHandler.HandleMessage(ctx, fx.senderId, objectMsg) require.NoError(t, err) }) - t.Run("head update non empty equal heads", func(t *testing.T) { + t.Run("handle full sync request returns error", func(t *testing.T) { fx := newSyncHandlerFixture(t) defer fx.stop() treeId := "treeId" - senderId := "senderId" chWithId := &treechangeproto.RawTreeChangeWithId{} - headUpdate := &treechangeproto.TreeHeadUpdate{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) + fullRequest := &treechangeproto.TreeFullSyncRequest{} + treeMsg := treechangeproto.WrapFullRequest(fullRequest, chWithId) objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h1"}).AnyTimes() + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) + err := fx.syncHandler.HandleMessage(ctx, fx.senderId, objectMsg) + require.Equal(t, err, ErrMessageIsRequest) }) - t.Run("head update empty", func(t *testing.T) { + t.Run("handle full sync response", func(t *testing.T) { fx := newSyncHandlerFixture(t) defer fx.stop() treeId := "treeId" - senderId := "senderId" chWithId := &treechangeproto.RawTreeChangeWithId{} - headUpdate := &treechangeproto.TreeHeadUpdate{ - Heads: []string{"h1"}, - Changes: nil, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h2"}).AnyTimes() - fx.syncClientMock.EXPECT(). - CreateFullSyncRequest(gomock.Eq(fx.objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})). - Return(fullRequest, nil) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Eq(fullRequest), gomock.Eq("")) - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) - - t.Run("head update empty equal heads", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - headUpdate := &treechangeproto.TreeHeadUpdate{ - Heads: []string{"h1"}, - Changes: nil, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h1"}).AnyTimes() - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) -} - -func TestSyncHandler_HandleFullSyncRequest(t *testing.T) { - ctx := context.Background() - log = logger.CtxLogger{Logger: zap.NewNop()} - fullResponse := &treechangeproto.TreeSyncMessage{ - Content: &treechangeproto.TreeSyncContentValue{ - Value: &treechangeproto.TreeSyncContentValue_FullSyncResponse{ - FullSyncResponse: &treechangeproto.TreeFullSyncResponse{}, - }, - }, - } - - t.Run("full sync request with change", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncRequest := &treechangeproto.TreeFullSyncRequest{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Header().Return(nil) - fx.objectTreeMock.EXPECT().Heads().Return([]string{"h2"}).AnyTimes() - fx.objectTreeMock.EXPECT().HasChanges(gomock.Eq([]string{"h1"})).Return(false) - fx.objectTreeMock.EXPECT(). - AddRawChanges(gomock.Any(), gomock.Eq(objecttree.RawChangesPayload{ - NewHeads: []string{"h1"}, - RawChanges: []*treechangeproto.RawTreeChangeWithId{chWithId}, - })). - Return(objecttree.AddResult{}, nil) - fx.syncClientMock.EXPECT(). - CreateFullSyncResponse(gomock.Eq(fx.objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})). - Return(fullResponse, nil) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Eq(fullResponse), gomock.Eq("")) - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) - - t.Run("full sync request with change same heads", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncRequest := &treechangeproto.TreeFullSyncRequest{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - - fx.objectTreeMock.EXPECT(). - Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Header().Return(nil) - fx.objectTreeMock.EXPECT(). - Heads(). - Return([]string{"h1"}).AnyTimes() - fx.syncClientMock.EXPECT(). - CreateFullSyncResponse(gomock.Eq(fx.objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})). - Return(fullResponse, nil) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Eq(fullResponse), gomock.Eq("")) - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) - - t.Run("full sync request without change but with reply id", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - replyId := "replyId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncRequest := &treechangeproto.TreeFullSyncRequest{ - Heads: []string{"h1"}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - objectMsg.RequestId = replyId - - fx.objectTreeMock.EXPECT(). - Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Header().Return(nil) - fx.syncClientMock.EXPECT(). - CreateFullSyncResponse(gomock.Eq(fx.objectTreeMock), gomock.Eq([]string{"h1"}), gomock.Eq([]string{"h1"})). - Return(fullResponse, nil) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Eq(fullResponse), gomock.Eq(replyId)) - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) - - t.Run("full sync request with add raw changes error", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncRequest := &treechangeproto.TreeFullSyncRequest{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapFullRequest(fullSyncRequest, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - - fx.objectTreeMock.EXPECT(). - Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT().Header().Return(nil) - fx.objectTreeMock.EXPECT(). - Heads(). - Return([]string{"h2"}) - fx.objectTreeMock.EXPECT(). - HasChanges(gomock.Eq([]string{"h1"})). - Return(false) - fx.objectTreeMock.EXPECT(). - AddRawChanges(gomock.Any(), gomock.Eq(objecttree.RawChangesPayload{ - NewHeads: []string{"h1"}, - RawChanges: []*treechangeproto.RawTreeChangeWithId{chWithId}, - })). - Return(objecttree.AddResult{}, fmt.Errorf("")) - fx.syncClientMock.EXPECT().SendWithReply(gomock.Any(), gomock.Eq(senderId), gomock.Eq(treeId), gomock.Any(), gomock.Eq("")) - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.Error(t, err) - }) -} - -func TestSyncHandler_HandleFullSyncResponse(t *testing.T) { - ctx := context.Background() - log = logger.CtxLogger{Logger: zap.NewNop()} - - t.Run("full sync response with change", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - replyId := "replyId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncResponse := &treechangeproto.TreeFullSyncResponse{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } + fullSyncResponse := &treechangeproto.TreeFullSyncResponse{} treeMsg := treechangeproto.WrapFullResponse(fullSyncResponse, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, replyId) + objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT(). - Heads(). - Return([]string{"h2"}).AnyTimes() - fx.objectTreeMock.EXPECT(). - HasChanges(gomock.Eq([]string{"h1"})). - Return(false) - fx.objectTreeMock.EXPECT(). - AddRawChanges(gomock.Any(), gomock.Eq(objecttree.RawChangesPayload{ - NewHeads: []string{"h1"}, - RawChanges: []*treechangeproto.RawTreeChangeWithId{chWithId}, - })). - Return(objecttree.AddResult{}, nil) + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) + fx.syncProtocolMock.EXPECT().FullSyncResponse(ctx, fx.senderId, gomock.Any()).Return(nil) - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) - require.NoError(t, err) - }) - - t.Run("full sync response with same heads", func(t *testing.T) { - fx := newSyncHandlerFixture(t) - defer fx.stop() - treeId := "treeId" - senderId := "senderId" - replyId := "replyId" - chWithId := &treechangeproto.RawTreeChangeWithId{} - fullSyncResponse := &treechangeproto.TreeFullSyncResponse{ - Heads: []string{"h1"}, - Changes: []*treechangeproto.RawTreeChangeWithId{chWithId}, - SnapshotPath: []string{"h1"}, - } - treeMsg := treechangeproto.WrapFullResponse(fullSyncResponse, chWithId) - objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, replyId) - - fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(treeId) - fx.objectTreeMock.EXPECT(). - Heads(). - Return([]string{"h1"}).AnyTimes() - - err := fx.syncHandler.HandleMessage(ctx, senderId, objectMsg) + err := fx.syncHandler.HandleMessage(ctx, fx.senderId, objectMsg) require.NoError(t, err) }) } + +func TestSyncTreeHandler_HandleRequest(t *testing.T) { + ctx := context.Background() + + t.Run("handle request", func(t *testing.T) { + fx := newSyncHandlerFixture(t) + defer fx.stop() + treeId := "treeId" + chWithId := &treechangeproto.RawTreeChangeWithId{} + fullRequest := &treechangeproto.TreeFullSyncRequest{} + treeMsg := treechangeproto.WrapFullRequest(fullRequest, chWithId) + objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") + + syncResp := &treechangeproto.TreeSyncMessage{} + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) + fx.syncProtocolMock.EXPECT().FullSyncRequest(ctx, fx.senderId, gomock.Any()).Return(syncResp, nil) + + res, err := fx.syncHandler.HandleRequest(ctx, fx.senderId, objectMsg) + require.NoError(t, err) + require.NotNil(t, res) + }) + + t.Run("handle request", func(t *testing.T) { + fx := newSyncHandlerFixture(t) + defer fx.stop() + treeId := "treeId" + chWithId := &treechangeproto.RawTreeChangeWithId{} + fullRequest := &treechangeproto.TreeFullSyncRequest{} + treeMsg := treechangeproto.WrapFullRequest(fullRequest, chWithId) + objectMsg, _ := MarshallTreeMessage(treeMsg, "spaceId", treeId, "") + + syncResp := &treechangeproto.TreeSyncMessage{} + fx.objectTreeMock.EXPECT().Id().AnyTimes().Return(fx.treeId) + fx.syncProtocolMock.EXPECT().FullSyncRequest(ctx, fx.senderId, gomock.Any()).Return(syncResp, nil) + + res, err := fx.syncHandler.HandleRequest(ctx, fx.senderId, objectMsg) + require.NoError(t, err) + require.NotNil(t, res) + }) + + t.Run("handle other message", func(t *testing.T) { + fx := newSyncHandlerFixture(t) + defer fx.stop() + treeId := "treeId" + chWithId := &treechangeproto.RawTreeChangeWithId{} + fullResponse := &treechangeproto.TreeFullSyncResponse{} + responseMsg := treechangeproto.WrapFullResponse(fullResponse, chWithId) + headUpdate := &treechangeproto.TreeHeadUpdate{} + headUpdateMsg := treechangeproto.WrapHeadUpdate(headUpdate, chWithId) + for _, msg := range []*treechangeproto.TreeSyncMessage{responseMsg, headUpdateMsg} { + objectMsg, _ := MarshallTreeMessage(msg, "spaceId", treeId, "") + + _, err := fx.syncHandler.HandleRequest(ctx, fx.senderId, objectMsg) + require.Equal(t, err, ErrMessageIsNotRequest) + } + }) +}