From b4b18b96faa0946b9d6685202d42d530562739d1 Mon Sep 17 00:00:00 2001 From: Cory Slep Date: Sat, 2 Mar 2019 19:13:02 +0100 Subject: [PATCH] Two more inbox forwarding tests now pass. --- pub/mock_transport_test.go | 117 ++++++++++++++++++++++++++++++++++ pub/pub_test.go | 61 ++++++++++++++++++ pub/side_effect_actor_test.go | 110 +++++++++++++++++++++++++++++++- 3 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 pub/mock_transport_test.go diff --git a/pub/mock_transport_test.go b/pub/mock_transport_test.go new file mode 100644 index 0000000..3105304 --- /dev/null +++ b/pub/mock_transport_test.go @@ -0,0 +1,117 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: transport.go + +// Package pub is a generated GoMock package. +package pub + +import ( + context "context" + gomock "github.com/golang/mock/gomock" + http "net/http" + url "net/url" + reflect "reflect" +) + +// MockTransport is a mock of Transport interface +type MockTransport struct { + ctrl *gomock.Controller + recorder *MockTransportMockRecorder +} + +// MockTransportMockRecorder is the mock recorder for MockTransport +type MockTransportMockRecorder struct { + mock *MockTransport +} + +// NewMockTransport creates a new mock instance +func NewMockTransport(ctrl *gomock.Controller) *MockTransport { + mock := &MockTransport{ctrl: ctrl} + mock.recorder = &MockTransportMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockTransport) EXPECT() *MockTransportMockRecorder { + return m.recorder +} + +// Dereference mocks base method +func (m *MockTransport) Dereference(c context.Context, iri *url.URL) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Dereference", c, iri) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Dereference indicates an expected call of Dereference +func (mr *MockTransportMockRecorder) Dereference(c, iri interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Dereference", reflect.TypeOf((*MockTransport)(nil).Dereference), c, iri) +} + +// Deliver mocks base method +func (m *MockTransport) Deliver(c context.Context, b []byte, to *url.URL) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Deliver", c, b, to) + ret0, _ := ret[0].(error) + return ret0 +} + +// Deliver indicates an expected call of Deliver +func (mr *MockTransportMockRecorder) Deliver(c, b, to interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deliver", reflect.TypeOf((*MockTransport)(nil).Deliver), c, b, to) +} + +// BatchDeliver mocks base method +func (m *MockTransport) BatchDeliver(c context.Context, b []byte, recipients []*url.URL) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BatchDeliver", c, b, recipients) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchDeliver indicates an expected call of BatchDeliver +func (mr *MockTransportMockRecorder) BatchDeliver(c, b, recipients interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchDeliver", reflect.TypeOf((*MockTransport)(nil).BatchDeliver), c, b, recipients) +} + +// MockHttpClient is a mock of HttpClient interface +type MockHttpClient struct { + ctrl *gomock.Controller + recorder *MockHttpClientMockRecorder +} + +// MockHttpClientMockRecorder is the mock recorder for MockHttpClient +type MockHttpClientMockRecorder struct { + mock *MockHttpClient +} + +// NewMockHttpClient creates a new mock instance +func NewMockHttpClient(ctrl *gomock.Controller) *MockHttpClient { + mock := &MockHttpClient{ctrl: ctrl} + mock.recorder = &MockHttpClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockHttpClient) EXPECT() *MockHttpClientMockRecorder { + return m.recorder +} + +// Do mocks base method +func (m *MockHttpClient) Do(req *http.Request) (*http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Do", req) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Do indicates an expected call of Do +func (mr *MockHttpClientMockRecorder) Do(req interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Do", reflect.TypeOf((*MockHttpClient)(nil).Do), req) +} diff --git a/pub/pub_test.go b/pub/pub_test.go index 9227104..3554ba3 100644 --- a/pub/pub_test.go +++ b/pub/pub_test.go @@ -22,6 +22,8 @@ const ( testFederatedActivityIRI2 = "https://other.example.com/activity/2" testFederatedActorIRI = "https://other.example.com/dakota" testFederatedActorIRI2 = "https://other.example.com/addison" + testFederatedActorIRI3 = "https://other.example.com/sam" + testFederatedActorIRI4 = "https://other.example.com/jessie" testNoteId1 = "https://example.com/note/1" testNoteId2 = "https://example.com/note/2" testNewActivityIRI = "https://example.com/new/1" @@ -33,6 +35,8 @@ const ( testAudienceIRI2 = "https://maybe.example.com/audience/2" testPersonIRI = "https://maybe.example.com/person" testServiceIRI = "https://maybe.example.com/service" + testTagIRI = "https://example.com/tag/1" + testTagIRI2 = "https://example.com/tag/2" ) // mustParse parses a URL or panics. @@ -104,6 +108,10 @@ var ( testPerson vocab.ActivityStreamsPerson // testService is a Service. testService vocab.ActivityStreamsService + // testCollectionOfActors is a collection of actors. + testCollectionOfActors vocab.ActivityStreamsCollectionPage + // testOrderedCollectionOfActors is an ordered collection of actors. + testOrderedCollectionOfActors vocab.ActivityStreamsOrderedCollectionPage ) // The test data cannot be created at init time since that is when the hooks of @@ -243,6 +251,22 @@ func setupData() { id.Set(mustParse(testServiceIRI)) testService.SetActivityStreamsId(id) }() + // testCollectionOfActors + func() { + testCollectionOfActors = streams.NewActivityStreamsCollectionPage() + i := streams.NewActivityStreamsItemsProperty() + i.AppendIRI(mustParse(testFederatedActorIRI)) + i.AppendIRI(mustParse(testFederatedActorIRI2)) + testCollectionOfActors.SetActivityStreamsItems(i) + }() + // testOrderedCollectionOfActors + func() { + testOrderedCollectionOfActors = streams.NewActivityStreamsOrderedCollectionPage() + oi := streams.NewActivityStreamsOrderedItemsProperty() + oi.AppendIRI(mustParse(testFederatedActorIRI3)) + oi.AppendIRI(mustParse(testFederatedActorIRI4)) + testOrderedCollectionOfActors.SetActivityStreamsOrderedItems(oi) + }() } // wrappedInCreate returns a Create activity wrapping the given type. @@ -254,6 +278,16 @@ func wrappedInCreate(t vocab.Type) vocab.ActivityStreamsCreate { return create } +// mustSerializeToBytes serializes a type to bytes or panics. +func mustSerializeToBytes(t vocab.Type) []byte { + m := mustSerialize(t) + b, err := json.Marshal(m) + if err != nil { + panic(err) + } + return b +} + // mustSerialize serializes a type or panics. func mustSerialize(t vocab.Type) map[string]interface{} { m, err := serialize(t) @@ -426,3 +460,30 @@ func mustAddAudienceIds(t Activity) Activity { } return t } + +// setTagger is an ActivityStreams type with a 'tag' property +type setTagger interface { + SetActivityStreamsTag(vocab.ActivityStreamsTagProperty) +} + +// mustAddTagIds adds two IRIs to the 'tag' property +func mustAddTagIds(t Activity) Activity { + if st, ok := t.(setTagger); ok { + tag := streams.NewActivityStreamsTagProperty() + tag.AppendIRI(mustParse(testTagIRI)) + tag.AppendIRI(mustParse(testTagIRI2)) + st.SetActivityStreamsTag(tag) + } else { + panic(fmt.Sprintf("activity is not setTagger: %T", t)) + } + return t +} + +// newObjectWithId creates a generic object with a given id. +func newObjectWithId(id string) vocab.ActivityStreamsObject { + obj := streams.NewActivityStreamsObject() + i := streams.NewActivityStreamsIdProperty() + i.Set(mustParse(id)) + obj.SetActivityStreamsId(i) + return obj +} diff --git a/pub/side_effect_actor_test.go b/pub/side_effect_actor_test.go index 5e7acc6..a64e4be 100644 --- a/pub/side_effect_actor_test.go +++ b/pub/side_effect_actor_test.go @@ -543,14 +543,120 @@ func TestInboxForwarding(t *testing.T) { assertEqual(t, err, nil) }) t.Run("DoesNotForwardIfNoChainIsOwned", func(t *testing.T) { - t.Errorf("Not yet implemented.") + // Setup + ctl := gomock.NewController(t) + defer ctl.Finish() + cm, fp, _, db, _, a := setupFn(ctl) + input := mustAddTagIds( + mustAddAudienceIds(testListen)) + mockTPortTag := NewMockTransport(ctl) + mockTPortTag2 := NewMockTransport(ctl) + gomock.InOrder( + db.EXPECT().Lock(ctx, mustParse(testFederatedActivityIRI)), + db.EXPECT().Exists(ctx, mustParse(testFederatedActivityIRI)).Return(false, nil), + db.EXPECT().Create(ctx, input).Return(nil), + db.EXPECT().Unlock(ctx, mustParse(testFederatedActivityIRI)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Owns(ctx, mustParse(testAudienceIRI)).Return(true, nil), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Owns(ctx, mustParse(testAudienceIRI2)).Return(true, nil), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Get(ctx, mustParse(testAudienceIRI)).Return(testOrderedCollectionOfActors, nil), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Get(ctx, mustParse(testAudienceIRI2)).Return(testCollectionOfActors, nil), + fp.EXPECT().MaxInboxForwardingRecursionDepth(ctx).Return(0), + // hasInboxForwardingValues + db.EXPECT().Lock(ctx, mustParse(testTagIRI)), + db.EXPECT().Owns(ctx, mustParse(testTagIRI)).Return(false, nil), + db.EXPECT().Unlock(ctx, mustParse(testTagIRI)), + db.EXPECT().Lock(ctx, mustParse(testTagIRI2)), + db.EXPECT().Owns(ctx, mustParse(testTagIRI2)).Return(false, nil), + db.EXPECT().Unlock(ctx, mustParse(testTagIRI2)), + db.EXPECT().Lock(ctx, mustParse(testNoteId1)), + db.EXPECT().Owns(ctx, mustParse(testNoteId1)).Return(false, nil), + db.EXPECT().Unlock(ctx, mustParse(testNoteId1)), + cm.EXPECT().NewTransport(ctx, mustParse(testMyInboxIRI), goFedUserAgent()).Return(mockTPortTag, nil), + mockTPortTag.EXPECT().Dereference(ctx, mustParse(testTagIRI)).Return(mustSerializeToBytes(newObjectWithId(testTagIRI)), nil), + cm.EXPECT().NewTransport(ctx, mustParse(testMyInboxIRI), goFedUserAgent()).Return(mockTPortTag2, nil), + mockTPortTag2.EXPECT().Dereference(ctx, mustParse(testTagIRI2)).Return(mustSerializeToBytes(newObjectWithId(testTagIRI2)), nil), + // Deferred + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI)), + ) + // Run + err := a.InboxForwarding(ctx, mustParse(testMyInboxIRI), input) + // Verify + assertEqual(t, err, nil) }) t.Run("ForwardsToRecipients", func(t *testing.T) { - t.Errorf("Not yet implemented.") + // Setup + ctl := gomock.NewController(t) + defer ctl.Finish() + cm, fp, _, db, _, a := setupFn(ctl) + input := mustAddTagIds( + mustAddAudienceIds(testListen)) + tPort := NewMockTransport(ctl) + gomock.InOrder( + db.EXPECT().Lock(ctx, mustParse(testFederatedActivityIRI)), + db.EXPECT().Exists(ctx, mustParse(testFederatedActivityIRI)).Return(false, nil), + db.EXPECT().Create(ctx, input).Return(nil), + db.EXPECT().Unlock(ctx, mustParse(testFederatedActivityIRI)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Owns(ctx, mustParse(testAudienceIRI)).Return(true, nil), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Owns(ctx, mustParse(testAudienceIRI2)).Return(true, nil), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI)), + db.EXPECT().Get(ctx, mustParse(testAudienceIRI)).Return(testOrderedCollectionOfActors, nil), + db.EXPECT().Lock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Get(ctx, mustParse(testAudienceIRI2)).Return(testCollectionOfActors, nil), + fp.EXPECT().MaxInboxForwardingRecursionDepth(ctx).Return(0), + // hasInboxForwardingValues + db.EXPECT().Lock(ctx, mustParse(testTagIRI)), + db.EXPECT().Owns(ctx, mustParse(testTagIRI)).Return(true, nil), + db.EXPECT().Unlock(ctx, mustParse(testTagIRI)), + // after hasInboxForwardingValues + fp.EXPECT().FilterForwarding( + ctx, + []*url.URL{ + mustParse(testAudienceIRI), + mustParse(testAudienceIRI2), + }, + input, + ).Return( + []*url.URL{ + mustParse(testAudienceIRI), + }, + nil, + ), + // deliverToRecipients + cm.EXPECT().NewTransport(ctx, mustParse(testMyInboxIRI), goFedUserAgent()).Return(tPort, nil), + tPort.EXPECT().BatchDeliver( + ctx, + mustSerializeToBytes(input), + []*url.URL{ + mustParse(testFederatedActorIRI3), + mustParse(testFederatedActorIRI4), + }, + ), + // Deferred + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI2)), + db.EXPECT().Unlock(ctx, mustParse(testAudienceIRI)), + ) + // Run + err := a.InboxForwarding(ctx, mustParse(testMyInboxIRI), input) + // Verify + assertEqual(t, err, nil) }) t.Run("ForwardsToRecipientsIfChainIsNested", func(t *testing.T) { t.Errorf("Not yet implemented.") }) + t.Run("ForwardsToRecipientsAfterDereferencing", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) t.Run("DoesNotForwardIfChainIsNestedTooDeep", func(t *testing.T) { t.Errorf("Not yet implemented.") })