diff --git a/internal/processing/workers/fromclientapi_test.go b/internal/processing/workers/fromclientapi_test.go index 3aa0fbdad..af1e02907 100644 --- a/internal/processing/workers/fromclientapi_test.go +++ b/internal/processing/workers/fromclientapi_test.go @@ -31,7 +31,9 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/internal/messages" + "github.com/superseriousbusiness/gotosocial/internal/state" "github.com/superseriousbusiness/gotosocial/internal/stream" + "github.com/superseriousbusiness/gotosocial/internal/typeutils" "github.com/superseriousbusiness/gotosocial/internal/util" "github.com/superseriousbusiness/gotosocial/testrig" ) @@ -42,6 +44,7 @@ type FromClientAPITestSuite struct { func (suite *FromClientAPITestSuite) newStatus( ctx context.Context, + state *state.State, account *gtsmodel.Account, visibility gtsmodel.Visibility, replyToStatus *gtsmodel.Status, @@ -86,7 +89,7 @@ func (suite *FromClientAPITestSuite) newStatus( TargetAccountID: replyToStatus.AccountID, } - if err := suite.db.PutMention(ctx, mention); err != nil { + if err := state.DB.PutMention(ctx, mention); err != nil { suite.FailNow(err.Error()) } newStatus.Mentions = []*gtsmodel.Mention{mention} @@ -103,7 +106,7 @@ func (suite *FromClientAPITestSuite) newStatus( // Put the status in the db, to mimic what would // have already happened earlier up the flow. - if err := suite.db.PutStatus(ctx, newStatus); err != nil { + if err := state.DB.PutStatus(ctx, newStatus); err != nil { suite.FailNow(err.Error()) } @@ -122,7 +125,15 @@ func (suite *FromClientAPITestSuite) checkStreamed( ctx, cncl := context.WithTimeout(ctx, time.Second*5) defer cncl() - msg, ok := str.Recv(ctx) + var ( + msg stream.Message + ok bool + ) + + testrig.WaitFor(func() bool { + msg, ok = str.Recv(ctx) + return (expectMessage && ok) || (!expectMessage && !ok) + }) if expectMessage && !ok { suite.FailNow("expected a message but message was not received") @@ -143,10 +154,11 @@ func (suite *FromClientAPITestSuite) checkStreamed( func (suite *FromClientAPITestSuite) statusJSON( ctx context.Context, + typeConverter *typeutils.Converter, status *gtsmodel.Status, requestingAccount *gtsmodel.Account, ) string { - apiStatus, err := suite.typeconverter.StatusToAPIStatus( + apiStatus, err := typeConverter.StatusToAPIStatus( ctx, status, requestingAccount, @@ -164,19 +176,27 @@ func (suite *FromClientAPITestSuite) statusJSON( } func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] testList = suite.testLists["local_account_1_list_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) - homeStream = streams[stream.TimelineHome] - listStream = streams[stream.TimelineList+":"+testList.ID] - notifStream = streams[stream.TimelineNotifications] + streams = suite.openStreams(ctx, + testStructs.Processor, + receivingAccount, + []string{testList.ID}, + ) + homeStream = streams[stream.TimelineHome] + listStream = streams[stream.TimelineList+":"+testList.ID] + notifStream = streams[stream.TimelineNotifications] // Admin account posts a new top-level status. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, nil, @@ -190,12 +210,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { *follow = *suite.testFollows["local_account_1_admin_account"] follow.Notify = util.Ptr(true) - if err := suite.db.UpdateFollow(ctx, follow); err != nil { + if err := testStructs.State.DB.UpdateFollow(ctx, follow); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -209,6 +229,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -233,7 +254,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { var notif *gtsmodel.Notification if !testrig.WaitFor(func() bool { var err error - notif, err = suite.db.GetNotification( + notif, err = testStructs.State.DB.GetNotification( ctx, gtsmodel.NotificationStatus, receivingAccount.ID, @@ -245,7 +266,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { suite.FailNow("timed out waiting for new status notification") } - apiNotif, err := suite.typeconverter.NotificationToAPINotification(ctx, notif) + apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif) if err != nil { suite.FailNow(err.Error()) } @@ -265,12 +286,15 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() { } func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] testList = suite.testLists["local_account_1_list_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] @@ -281,6 +305,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() { // post should also show in the list stream. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, suite.testStatuses["local_account_2_status_1"], @@ -289,7 +314,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() { ) // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -303,6 +328,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() { statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -325,6 +351,9 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() { } func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] @@ -335,6 +364,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() { // for this, but zork mutes this thread. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, suite.testStatuses["local_account_1_status_1"], @@ -348,12 +378,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() { ) // Store the thread mute before processing new status. - if err := suite.db.PutThreadMute(ctx, threadMute); err != nil { + if err := testStructs.State.DB.PutThreadMute(ctx, threadMute); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -366,7 +396,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() { } // Ensure no notification received. - notif, err := suite.db.GetNotification( + notif, err := testStructs.State.DB.GetNotification( ctx, gtsmodel.NotificationMention, receivingAccount.ID, @@ -379,6 +409,9 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() { } func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] @@ -389,6 +422,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() { // for this, but zork mutes this thread. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, nil, @@ -402,12 +436,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() { ) // Store the thread mute before processing new status. - if err := suite.db.PutThreadMute(ctx, threadMute); err != nil { + if err := testStructs.State.DB.PutThreadMute(ctx, threadMute); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ActivityAnnounce, @@ -420,7 +454,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() { } // Ensure no notification received. - notif, err := suite.db.GetNotification( + notif, err := testStructs.State.DB.GetNotification( ctx, gtsmodel.NotificationReblog, receivingAccount.ID, @@ -433,6 +467,9 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() { } func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyListOnlyOK() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + // We're modifying the test list so take a copy. testList := new(gtsmodel.List) *testList = *suite.testLists["local_account_1_list_1"] @@ -441,13 +478,14 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] // Admin account posts a reply to turtle. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, suite.testStatuses["local_account_2_status_1"], @@ -460,12 +498,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis // and admin are in the same list, this means the reply // should be shown in the list. testList.RepliesPolicy = gtsmodel.RepliesPolicyList - if err := suite.db.UpdateList(ctx, testList, "replies_policy"); err != nil { + if err := testStructs.State.DB.UpdateList(ctx, testList, "replies_policy"); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -479,6 +517,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -501,6 +540,9 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis } func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyListOnlyNo() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + // We're modifying the test list so take a copy. testList := new(gtsmodel.List) *testList = *suite.testLists["local_account_1_list_1"] @@ -509,13 +551,14 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] // Admin account posts a reply to turtle. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, suite.testStatuses["local_account_2_status_1"], @@ -528,17 +571,17 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis // about to remove turtle from the same list as admin, // so the new post should not be streamed to the list. testList.RepliesPolicy = gtsmodel.RepliesPolicyList - if err := suite.db.UpdateList(ctx, testList, "replies_policy"); err != nil { + if err := testStructs.State.DB.UpdateList(ctx, testList, "replies_policy"); err != nil { suite.FailNow(err.Error()) } // Remove turtle from the list. - if err := suite.db.DeleteListEntry(ctx, suite.testListEntries["local_account_1_list_1_entry_1"].ID); err != nil { + if err := testStructs.State.DB.DeleteListEntry(ctx, suite.testListEntries["local_account_1_list_1_entry_1"].ID); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -552,6 +595,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -574,6 +618,9 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis } func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPolicyNone() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + // We're modifying the test list so take a copy. testList := new(gtsmodel.List) *testList = *suite.testLists["local_account_1_list_1"] @@ -582,13 +629,14 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPoli ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] // Admin account posts a reply to turtle. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, suite.testStatuses["local_account_2_status_1"], @@ -601,12 +649,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPoli // show any replies, the post should not // be streamed to the list. testList.RepliesPolicy = gtsmodel.RepliesPolicyNone - if err := suite.db.UpdateList(ctx, testList, "replies_policy"); err != nil { + if err := testStructs.State.DB.UpdateList(ctx, testList, "replies_policy"); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -620,6 +668,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPoli statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -642,18 +691,22 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPoli } func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoost() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] testList = suite.testLists["local_account_1_list_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] // Admin account boosts a post by turtle. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, nil, @@ -662,7 +715,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoost() { ) // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ActivityAnnounce, @@ -676,6 +729,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoost() { statusJSON := suite.statusJSON( ctx, + testStructs.TypeConverter, status, receivingAccount, ) @@ -698,18 +752,22 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoost() { } func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostNoReblogs() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() postingAccount = suite.testAccounts["admin_account"] receivingAccount = suite.testAccounts["local_account_1"] testList = suite.testLists["local_account_1_list_1"] - streams = suite.openStreams(ctx, receivingAccount, []string{testList.ID}) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, []string{testList.ID}) homeStream = streams[stream.TimelineHome] listStream = streams[stream.TimelineList+":"+testList.ID] // Admin account boosts a post by turtle. status = suite.newStatus( ctx, + testStructs.State, postingAccount, gtsmodel.VisibilityPublic, nil, @@ -722,12 +780,12 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostNoReblogs() { follow := new(gtsmodel.Follow) *follow = *suite.testFollows["local_account_1_admin_account"] follow.ShowReblogs = util.Ptr(false) - if err := suite.db.UpdateFollow(ctx, follow, "show_reblogs"); err != nil { + if err := testStructs.State.DB.UpdateFollow(ctx, follow, "show_reblogs"); err != nil { suite.FailNow(err.Error()) } // Process the new status. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ActivityAnnounce, @@ -757,24 +815,27 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostNoReblogs() { } func (suite *FromClientAPITestSuite) TestProcessStatusDelete() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + var ( ctx = context.Background() deletingAccount = suite.testAccounts["local_account_1"] receivingAccount = suite.testAccounts["local_account_2"] deletedStatus = suite.testStatuses["local_account_1_status_1"] boostOfDeletedStatus = suite.testStatuses["admin_account_status_4"] - streams = suite.openStreams(ctx, receivingAccount, nil) + streams = suite.openStreams(ctx, testStructs.Processor, receivingAccount, nil) homeStream = streams[stream.TimelineHome] ) // Delete the status from the db first, to mimic what // would have already happened earlier up the flow - if err := suite.db.DeleteStatusByID(ctx, deletedStatus.ID); err != nil { + if err := testStructs.State.DB.DeleteStatusByID(ctx, deletedStatus.ID); err != nil { suite.FailNow(err.Error()) } // Process the status delete. - if err := suite.processor.Workers().ProcessFromClientAPI( + if err := testStructs.Processor.Workers().ProcessFromClientAPI( ctx, &messages.FromClientAPI{ APObjectType: ap.ObjectNote, @@ -806,7 +867,7 @@ func (suite *FromClientAPITestSuite) TestProcessStatusDelete() { // Boost should no longer be in the database. if !testrig.WaitFor(func() bool { - _, err := suite.db.GetStatusByID(ctx, boostOfDeletedStatus.ID) + _, err := testStructs.State.DB.GetStatusByID(ctx, boostOfDeletedStatus.ID) return errors.Is(err, db.ErrNoEntries) }) { suite.FailNow("timed out waiting for status delete") diff --git a/internal/processing/workers/fromfediapi_test.go b/internal/processing/workers/fromfediapi_test.go index b8acca94d..8429fe17c 100644 --- a/internal/processing/workers/fromfediapi_test.go +++ b/internal/processing/workers/fromfediapi_test.go @@ -42,6 +42,9 @@ type FromFediAPITestSuite struct { // remote_account_1 boosts the first status of local_account_1 func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + boostedStatus := suite.testStatuses["local_account_1_status_1"] boostingAccount := suite.testAccounts["remote_account_1"] announceStatus := >smodel.Status{} @@ -54,7 +57,7 @@ func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() { announceStatus.Account = boostingAccount announceStatus.Visibility = boostedStatus.Visibility - err := suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ + err := testStructs.Processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ APObjectType: ap.ActivityAnnounce, APActivityType: ap.ActivityCreate, GTSModel: announceStatus, @@ -66,7 +69,7 @@ func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() { // side effects should be triggered // 1. status should have an ID, and be in the database suite.NotEmpty(announceStatus.ID) - _, err = suite.db.GetStatusByID(context.Background(), announceStatus.ID) + _, err = testStructs.State.DB.GetStatusByID(context.Background(), announceStatus.ID) suite.NoError(err) // 2. a notification should exist for the announce @@ -77,7 +80,7 @@ func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() { }, } notif := >smodel.Notification{} - err = suite.db.GetWhere(context.Background(), where, notif) + err = testStructs.State.DB.GetWhere(context.Background(), where, notif) suite.NoError(err) suite.Equal(gtsmodel.NotificationReblog, notif.NotificationType) suite.Equal(boostedStatus.AccountID, notif.TargetAccountID) @@ -87,6 +90,9 @@ func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() { } func (suite *FromFediAPITestSuite) TestProcessReplyMention() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + repliedAccount := suite.testAccounts["local_account_1"] repliedStatus := suite.testStatuses["local_account_1_status_1"] replyingAccount := suite.testAccounts["remote_account_1"] @@ -97,7 +103,7 @@ func (suite *FromFediAPITestSuite) TestProcessReplyMention() { replyingAccount.FetchedAt = time.Now() replyingAccount.SuspendedAt = time.Time{} replyingAccount.SuspensionOrigin = "" - err := suite.state.DB.UpdateAccount(context.Background(), + err := testStructs.State.DB.UpdateAccount(context.Background(), replyingAccount, "fetched_at", "suspended_at", @@ -111,11 +117,11 @@ func (suite *FromFediAPITestSuite) TestProcessReplyMention() { ap.AppendInReplyTo(replyingStatusable, testrig.URLMustParse(repliedStatus.URI)) // Open a websocket stream to later test the streamed status reply. - wssStream, errWithCode := suite.processor.Stream().Open(context.Background(), repliedAccount, stream.TimelineHome) + wssStream, errWithCode := testStructs.Processor.Stream().Open(context.Background(), repliedAccount, stream.TimelineHome) suite.NoError(errWithCode) // Send the replied status off to the fedi worker to be further processed. - err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ APObjectType: ap.ObjectNote, APActivityType: ap.ActivityCreate, APObject: replyingStatusable, @@ -126,12 +132,12 @@ func (suite *FromFediAPITestSuite) TestProcessReplyMention() { // side effects should be triggered // 1. status should be in the database - replyingStatus, err := suite.state.DB.GetStatusByURI(context.Background(), replyingURI) + replyingStatus, err := testStructs.State.DB.GetStatusByURI(context.Background(), replyingURI) suite.NoError(err) // 2. a notification should exist for the mention var notif gtsmodel.Notification - err = suite.db.GetWhere(context.Background(), []db.Where{ + err = testStructs.State.DB.GetWhere(context.Background(), []db.Where{ {Key: "status_id", Value: replyingStatus.ID}, }, ¬if) suite.NoError(err) @@ -156,11 +162,14 @@ func (suite *FromFediAPITestSuite) TestProcessReplyMention() { } func (suite *FromFediAPITestSuite) TestProcessFave() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + favedAccount := suite.testAccounts["local_account_1"] favedStatus := suite.testStatuses["local_account_1_status_1"] favingAccount := suite.testAccounts["remote_account_1"] - wssStream, errWithCode := suite.processor.Stream().Open(context.Background(), favedAccount, stream.TimelineNotifications) + wssStream, errWithCode := testStructs.Processor.Stream().Open(context.Background(), favedAccount, stream.TimelineNotifications) suite.NoError(errWithCode) fave := >smodel.StatusFave{ @@ -176,10 +185,10 @@ func (suite *FromFediAPITestSuite) TestProcessFave() { URI: favingAccount.URI + "/faves/aaaaaaaaaaaa", } - err := suite.db.Put(context.Background(), fave) + err := testStructs.State.DB.Put(context.Background(), fave) suite.NoError(err) - err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ APObjectType: ap.ActivityLike, APActivityType: ap.ActivityCreate, GTSModel: fave, @@ -202,7 +211,7 @@ func (suite *FromFediAPITestSuite) TestProcessFave() { } notif := >smodel.Notification{} - err = suite.db.GetWhere(context.Background(), where, notif) + err = testStructs.State.DB.GetWhere(context.Background(), where, notif) suite.NoError(err) suite.Equal(gtsmodel.NotificationFave, notif.NotificationType) suite.Equal(fave.TargetAccountID, notif.TargetAccountID) @@ -225,12 +234,15 @@ func (suite *FromFediAPITestSuite) TestProcessFave() { // This tests for an issue we were seeing where Misskey sends out faves to inboxes of people that don't own // the fave, but just follow the actor who received the fave. func (suite *FromFediAPITestSuite) TestProcessFaveWithDifferentReceivingAccount() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + receivingAccount := suite.testAccounts["local_account_2"] favedAccount := suite.testAccounts["local_account_1"] favedStatus := suite.testStatuses["local_account_1_status_1"] favingAccount := suite.testAccounts["remote_account_1"] - wssStream, errWithCode := suite.processor.Stream().Open(context.Background(), receivingAccount, stream.TimelineHome) + wssStream, errWithCode := testStructs.Processor.Stream().Open(context.Background(), receivingAccount, stream.TimelineHome) suite.NoError(errWithCode) fave := >smodel.StatusFave{ @@ -246,10 +258,10 @@ func (suite *FromFediAPITestSuite) TestProcessFaveWithDifferentReceivingAccount( URI: favingAccount.URI + "/faves/aaaaaaaaaaaa", } - err := suite.db.Put(context.Background(), fave) + err := testStructs.State.DB.Put(context.Background(), fave) suite.NoError(err) - err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{ APObjectType: ap.ActivityLike, APActivityType: ap.ActivityCreate, GTSModel: fave, @@ -272,7 +284,7 @@ func (suite *FromFediAPITestSuite) TestProcessFaveWithDifferentReceivingAccount( } notif := >smodel.Notification{} - err = suite.db.GetWhere(context.Background(), where, notif) + err = testStructs.State.DB.GetWhere(context.Background(), where, notif) suite.NoError(err) suite.Equal(gtsmodel.NotificationFave, notif.NotificationType) suite.Equal(fave.TargetAccountID, notif.TargetAccountID) @@ -287,6 +299,9 @@ func (suite *FromFediAPITestSuite) TestProcessFaveWithDifferentReceivingAccount( } func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + ctx := context.Background() deletedAccount := suite.testAccounts["remote_account_1"] @@ -304,7 +319,7 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { URI: fmt.Sprintf("%s/follows/01FGRY72ASHBSET64353DPHK9T", deletedAccount.URI), Notify: util.Ptr(false), } - err := suite.db.Put(ctx, zorkFollowSatan) + err := testStructs.State.DB.Put(ctx, zorkFollowSatan) suite.NoError(err) satanFollowZork := >smodel.Follow{ @@ -317,11 +332,11 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { URI: fmt.Sprintf("%s/follows/01FGRYAVAWWPP926J175QGM0WV", receivingAccount.URI), Notify: util.Ptr(false), } - err = suite.db.Put(ctx, satanFollowZork) + err = testStructs.State.DB.Put(ctx, satanFollowZork) suite.NoError(err) // now they are mufos! - err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ APObjectType: ap.ObjectProfile, APActivityType: ap.ActivityDelete, GTSModel: deletedAccount, @@ -333,20 +348,20 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { // local account 2 blocked foss_satan, that block should be gone now testBlock := suite.testBlocks["local_account_2_block_remote_account_1"] dbBlock := >smodel.Block{} - err = suite.db.GetByID(ctx, testBlock.ID, dbBlock) + err = testStructs.State.DB.GetByID(ctx, testBlock.ID, dbBlock) suite.ErrorIs(err, db.ErrNoEntries) // the mufos should be gone now too - satanFollowsZork, err := suite.db.IsFollowing(ctx, deletedAccount.ID, receivingAccount.ID) + satanFollowsZork, err := testStructs.State.DB.IsFollowing(ctx, deletedAccount.ID, receivingAccount.ID) suite.NoError(err) suite.False(satanFollowsZork) - zorkFollowsSatan, err := suite.db.IsFollowing(ctx, receivingAccount.ID, deletedAccount.ID) + zorkFollowsSatan, err := testStructs.State.DB.IsFollowing(ctx, receivingAccount.ID, deletedAccount.ID) suite.NoError(err) suite.False(zorkFollowsSatan) // no statuses from foss satan should be left in the database if !testrig.WaitFor(func() bool { - s, err := suite.db.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, false, "", "", false, false) + s, err := testStructs.State.DB.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, false, "", "", false, false) return s == nil && err == db.ErrNoEntries }) { suite.FailNow("timeout waiting for statuses to be deleted") @@ -356,7 +371,7 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { // account data should be zeroed. if !testrig.WaitFor(func() bool { - dbAccount, err = suite.db.GetAccountByID(ctx, deletedAccount.ID) + dbAccount, err = testStructs.State.DB.GetAccountByID(ctx, deletedAccount.ID) return err == nil && dbAccount.DisplayName == "" }) { suite.FailNow("timeout waiting for statuses to be deleted") @@ -375,6 +390,9 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() { } func (suite *FromFediAPITestSuite) TestProcessFollowRequestLocked() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + ctx := context.Background() originAccount := suite.testAccounts["remote_account_1"] @@ -382,7 +400,7 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestLocked() { // target is a locked account targetAccount := suite.testAccounts["local_account_2"] - wssStream, errWithCode := suite.processor.Stream().Open(context.Background(), targetAccount, stream.TimelineHome) + wssStream, errWithCode := testStructs.Processor.Stream().Open(context.Background(), targetAccount, stream.TimelineHome) suite.NoError(errWithCode) // put the follow request in the database as though it had passed through the federating db already @@ -399,10 +417,10 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestLocked() { Notify: util.Ptr(false), } - err := suite.db.Put(ctx, satanFollowRequestTurtle) + err := testStructs.State.DB.Put(ctx, satanFollowRequestTurtle) suite.NoError(err) - err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ APObjectType: ap.ActivityFollow, APActivityType: ap.ActivityCreate, GTSModel: satanFollowRequestTurtle, @@ -425,10 +443,13 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestLocked() { suite.Equal(originAccount.ID, notif.Account.ID) // no messages should have been sent out, since we didn't need to federate an accept - suite.Empty(&suite.httpClient.SentMessages) + suite.Empty(testStructs.HTTPClient.SentMessages) } func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + ctx := context.Background() originAccount := suite.testAccounts["remote_account_1"] @@ -436,7 +457,7 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() { // target is an unlocked account targetAccount := suite.testAccounts["local_account_1"] - wssStream, errWithCode := suite.processor.Stream().Open(context.Background(), targetAccount, stream.TimelineHome) + wssStream, errWithCode := testStructs.Processor.Stream().Open(context.Background(), targetAccount, stream.TimelineHome) suite.NoError(errWithCode) // put the follow request in the database as though it had passed through the federating db already @@ -453,10 +474,10 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() { Notify: util.Ptr(false), } - err := suite.db.Put(ctx, satanFollowRequestTurtle) + err := testStructs.State.DB.Put(ctx, satanFollowRequestTurtle) suite.NoError(err) - err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ + err = testStructs.Processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ APObjectType: ap.ActivityFollow, APActivityType: ap.ActivityCreate, GTSModel: satanFollowRequestTurtle, @@ -482,7 +503,7 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() { // an accept message should be sent to satan's inbox var sent []byte if !testrig.WaitFor(func() bool { - delivery, ok := suite.state.Workers.Delivery.Queue.Pop() + delivery, ok := testStructs.State.Workers.Delivery.Queue.Pop() if !ok { return false } @@ -527,12 +548,15 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() { // TestCreateStatusFromIRI checks if a forwarded status can be dereferenced by the processor. func (suite *FromFediAPITestSuite) TestCreateStatusFromIRI() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + ctx := context.Background() receivingAccount := suite.testAccounts["local_account_1"] statusCreator := suite.testAccounts["remote_account_2"] - err := suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ + err := testStructs.Processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ APObjectType: ap.ObjectNote, APActivityType: ap.ActivityCreate, GTSModel: nil, // gtsmodel is nil because this is a forwarded status -- we want to dereference it using the iri @@ -543,12 +567,15 @@ func (suite *FromFediAPITestSuite) TestCreateStatusFromIRI() { suite.NoError(err) // status should now be in the database, attributed to remote_account_2 - s, err := suite.db.GetStatusByURI(context.Background(), "http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1") + s, err := testStructs.State.DB.GetStatusByURI(context.Background(), "http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1") suite.NoError(err) suite.Equal(statusCreator.URI, s.AccountURI) } func (suite *FromFediAPITestSuite) TestMoveAccount() { + testStructs := suite.SetupTestStructs() + defer suite.TearDownTestStructs(testStructs) + // We're gonna migrate foss_satan to our local admin account. ctx := context.Background() receivingAcct := suite.testAccounts["local_account_1"] @@ -562,12 +589,12 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() { // Set alsoKnownAs on the admin account. targetAcct.AlsoKnownAsURIs = []string{requestingAcct.URI} - if err := suite.state.DB.UpdateAccount(ctx, targetAcct, "also_known_as_uris"); err != nil { + if err := testStructs.State.DB.UpdateAccount(ctx, targetAcct, "also_known_as_uris"); err != nil { suite.FailNow(err.Error()) } // Remove existing follow from zork to admin account. - if err := suite.state.DB.DeleteFollowByID( + if err := testStructs.State.DB.DeleteFollowByID( ctx, suite.testFollows["local_account_1_admin_account"].ID, ); err != nil { @@ -575,7 +602,7 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() { } // Have Zork follow foss_satan instead. - if err := suite.state.DB.PutFollow(ctx, >smodel.Follow{ + if err := testStructs.State.DB.PutFollow(ctx, >smodel.Follow{ ID: "01HRA0XZYFZC5MNWTKEBR58SSE", URI: "http://localhost:8080/users/the_mighty_zork/follows/01HRA0XZYFZC5MNWTKEBR58SSE", AccountID: receivingAcct.ID, @@ -585,7 +612,7 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() { } // Process the Move. - err := suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ + err := testStructs.Processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{ APObjectType: ap.ObjectProfile, APActivityType: ap.ActivityMove, GTSModel: >smodel.Move{ @@ -601,14 +628,14 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() { suite.NoError(err) // Zork should now be following admin account. - follows, err := suite.state.DB.IsFollowing(ctx, receivingAcct.ID, targetAcct.ID) + follows, err := testStructs.State.DB.IsFollowing(ctx, receivingAcct.ID, targetAcct.ID) if err != nil { suite.FailNow(err.Error()) } suite.True(follows) // Move should be in the DB. - move, err := suite.state.DB.GetMoveByURI(ctx, "https://fossbros-anonymous.io/users/foss_satan/moves/01HRA064871MR8HGVSAFJ333GM") + move, err := testStructs.State.DB.GetMoveByURI(ctx, "https://fossbros-anonymous.io/users/foss_satan/moves/01HRA064871MR8HGVSAFJ333GM") if err != nil { suite.FailNow(err.Error()) } diff --git a/internal/processing/workers/workers_test.go b/internal/processing/workers/workers_test.go index af1428e64..a8562ea4f 100644 --- a/internal/processing/workers/workers_test.go +++ b/internal/processing/workers/workers_test.go @@ -22,18 +22,12 @@ import ( "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/gotosocial/internal/cleaner" - "github.com/superseriousbusiness/gotosocial/internal/db" - "github.com/superseriousbusiness/gotosocial/internal/email" - "github.com/superseriousbusiness/gotosocial/internal/federation" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" - "github.com/superseriousbusiness/gotosocial/internal/media" "github.com/superseriousbusiness/gotosocial/internal/oauth" "github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/state" - "github.com/superseriousbusiness/gotosocial/internal/storage" "github.com/superseriousbusiness/gotosocial/internal/stream" - "github.com/superseriousbusiness/gotosocial/internal/transport" "github.com/superseriousbusiness/gotosocial/internal/typeutils" "github.com/superseriousbusiness/gotosocial/testrig" ) @@ -41,16 +35,6 @@ import ( type WorkersTestSuite struct { // standard suite interfaces suite.Suite - db db.DB - storage *storage.Driver - state state.State - mediaManager *media.Manager - typeconverter *typeutils.Converter - httpClient *testrig.MockHTTPClient - transportController transport.Controller - federator *federation.Federator - oauthServer oauth.Server - emailSender email.Sender // standard suite models testTokens map[string]*gtsmodel.Token @@ -68,8 +52,13 @@ type WorkersTestSuite struct { testActivities map[string]testrig.ActivityWithSignature testLists map[string]*gtsmodel.List testListEntries map[string]*gtsmodel.ListEntry +} - processor *processing.Processor +type TestStructs struct { + State *state.State + Processor *processing.Processor + HTTPClient *testrig.MockHTTPClient + TypeConverter *typeutils.Converter } func (suite *WorkersTestSuite) SetupSuite() { @@ -96,48 +85,12 @@ func (suite *WorkersTestSuite) SetupSuite() { } func (suite *WorkersTestSuite) SetupTest() { - suite.state.Caches.Init() - testrig.InitTestConfig() testrig.InitTestLog() - - suite.db = testrig.NewTestDB(&suite.state) - suite.state.DB = suite.db suite.testActivities = testrig.NewTestActivities(suite.testAccounts) - suite.storage = testrig.NewInMemoryStorage() - suite.state.Storage = suite.storage - suite.typeconverter = typeutils.NewConverter(&suite.state) - - testrig.StartTimelines( - &suite.state, - visibility.NewFilter(&suite.state), - suite.typeconverter, - ) - - suite.httpClient = testrig.NewMockHTTPClient(nil, "../../../testrig/media") - suite.httpClient.TestRemotePeople = testrig.NewTestFediPeople() - suite.httpClient.TestRemoteStatuses = testrig.NewTestFediStatuses() - - suite.transportController = testrig.NewTestTransportController(&suite.state, suite.httpClient) - suite.mediaManager = testrig.NewTestMediaManager(&suite.state) - suite.federator = testrig.NewTestFederator(&suite.state, suite.transportController, suite.mediaManager) - suite.oauthServer = testrig.NewTestOauthServer(suite.db) - suite.emailSender = testrig.NewEmailSender("../../../web/template/", nil) - - suite.processor = processing.NewProcessor(cleaner.New(&suite.state), suite.typeconverter, suite.federator, suite.oauthServer, suite.mediaManager, &suite.state, suite.emailSender) - testrig.StartWorkers(&suite.state, suite.processor.Workers()) - - testrig.StandardDBSetup(suite.db, suite.testAccounts) - testrig.StandardStorageSetup(suite.storage, "../../../testrig/media") } -func (suite *WorkersTestSuite) TearDownTest() { - testrig.StandardDBTeardown(suite.db) - testrig.StandardStorageTeardown(suite.storage) - testrig.StopWorkers(&suite.state) -} - -func (suite *WorkersTestSuite) openStreams(ctx context.Context, account *gtsmodel.Account, listIDs []string) map[string]*stream.Stream { +func (suite *WorkersTestSuite) openStreams(ctx context.Context, processor *processing.Processor, account *gtsmodel.Account, listIDs []string) map[string]*stream.Stream { streams := make(map[string]*stream.Stream) for _, streamType := range []string{ @@ -145,7 +98,7 @@ func (suite *WorkersTestSuite) openStreams(ctx context.Context, account *gtsmode stream.TimelinePublic, stream.TimelineNotifications, } { - stream, err := suite.processor.Stream().Open(ctx, account, streamType) + stream, err := processor.Stream().Open(ctx, account, streamType) if err != nil { suite.FailNow(err.Error()) } @@ -156,7 +109,7 @@ func (suite *WorkersTestSuite) openStreams(ctx context.Context, account *gtsmode for _, listID := range listIDs { streamType := stream.TimelineList + ":" + listID - stream, err := suite.processor.Stream().Open(ctx, account, streamType) + stream, err := processor.Stream().Open(ctx, account, streamType) if err != nil { suite.FailNow(err.Error()) } @@ -166,3 +119,51 @@ func (suite *WorkersTestSuite) openStreams(ctx context.Context, account *gtsmode return streams } + +func (suite *WorkersTestSuite) SetupTestStructs() *TestStructs { + state := state.State{} + + state.Caches.Init() + + db := testrig.NewTestDB(&state) + state.DB = db + + storage := testrig.NewInMemoryStorage() + state.Storage = storage + typeconverter := typeutils.NewConverter(&state) + + testrig.StartTimelines( + &state, + visibility.NewFilter(&state), + typeconverter, + ) + + httpClient := testrig.NewMockHTTPClient(nil, "../../../testrig/media") + httpClient.TestRemotePeople = testrig.NewTestFediPeople() + httpClient.TestRemoteStatuses = testrig.NewTestFediStatuses() + + transportController := testrig.NewTestTransportController(&state, httpClient) + mediaManager := testrig.NewTestMediaManager(&state) + federator := testrig.NewTestFederator(&state, transportController, mediaManager) + oauthServer := testrig.NewTestOauthServer(db) + emailSender := testrig.NewEmailSender("../../../web/template/", nil) + + processor := processing.NewProcessor(cleaner.New(&state), typeconverter, federator, oauthServer, mediaManager, &state, emailSender) + testrig.StartWorkers(&state, processor.Workers()) + + testrig.StandardDBSetup(db, suite.testAccounts) + testrig.StandardStorageSetup(storage, "../../../testrig/media") + + return &TestStructs{ + State: &state, + Processor: processor, + HTTPClient: httpClient, + TypeConverter: typeconverter, + } +} + +func (suite *WorkersTestSuite) TearDownTestStructs(testStructs *TestStructs) { + testrig.StandardDBTeardown(testStructs.State.DB) + testrig.StandardStorageTeardown(testStructs.State.Storage) + testrig.StopWorkers(testStructs.State) +}