diff options
author | 2023-06-04 18:55:30 +0200 | |
---|---|---|
committer | 2023-06-04 18:55:30 +0200 | |
commit | 97bc2e713a6e5b2c25869b93f5232560d7110170 (patch) | |
tree | 62d76de2c489331413cd2d53a99e0daeb762efaa /internal/timeline/get_test.go | |
parent | [docs] Add Repology stats (#1859) (diff) | |
download | gotosocial-97bc2e713a6e5b2c25869b93f5232560d7110170.tar.xz |
[chore] tidy + test timelines a bit better (#1865)
* [chore] tidy + test timelines a bit better
* thanks linter
Diffstat (limited to 'internal/timeline/get_test.go')
-rw-r--r-- | internal/timeline/get_test.go | 617 |
1 files changed, 464 insertions, 153 deletions
diff --git a/internal/timeline/get_test.go b/internal/timeline/get_test.go index f99e58611..7b31ec977 100644 --- a/internal/timeline/get_test.go +++ b/internal/timeline/get_test.go @@ -19,85 +19,19 @@ package timeline_test import ( "context" - "sort" + "sync" "testing" - "time" "github.com/stretchr/testify/suite" - "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/gtscontext" "github.com/superseriousbusiness/gotosocial/internal/id" - tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline" "github.com/superseriousbusiness/gotosocial/internal/timeline" - "github.com/superseriousbusiness/gotosocial/internal/visibility" - "github.com/superseriousbusiness/gotosocial/testrig" ) type GetTestSuite struct { TimelineStandardTestSuite } -func (suite *GetTestSuite) SetupSuite() { - suite.testAccounts = testrig.NewTestAccounts() - suite.testStatuses = testrig.NewTestStatuses() -} - -func (suite *GetTestSuite) SetupTest() { - suite.state.Caches.Init() - - testrig.InitTestConfig() - testrig.InitTestLog() - - suite.db = testrig.NewTestDB(&suite.state) - suite.tc = testrig.NewTestTypeConverter(suite.db) - suite.filter = visibility.NewFilter(&suite.state) - - testrig.StandardDBSetup(suite.db, nil) - - // Take local_account_1 as the timeline owner, it - // doesn't really matter too much for these tests. - tl := timeline.NewTimeline( - context.Background(), - suite.testAccounts["local_account_1"].ID, - tlprocessor.HomeTimelineGrab(&suite.state), - tlprocessor.HomeTimelineFilter(&suite.state, suite.filter), - tlprocessor.HomeTimelineStatusPrepare(&suite.state, suite.tc), - tlprocessor.SkipInsert(), - ) - - // Put testrig statuses in a determinate order - // since we can't trust a map to keep order. - statuses := []*gtsmodel.Status{} - for _, s := range suite.testStatuses { - statuses = append(statuses, s) - } - - sort.Slice(statuses, func(i, j int) bool { - return statuses[i].ID > statuses[j].ID - }) - - // Statuses are now highest -> lowest. - suite.highestStatusID = statuses[0].ID - suite.lowestStatusID = statuses[len(statuses)-1].ID - if suite.highestStatusID < suite.lowestStatusID { - suite.FailNow("", "statuses weren't ordered properly by sort") - } - - // Put all test statuses into the timeline; we don't - // need to be fussy about who sees what for these tests. - for _, s := range statuses { - _, err := tl.IndexAndPrepareOne(context.Background(), s.GetID(), s.BoostOfID, s.AccountID, s.BoostOfAccountID) - if err != nil { - suite.FailNow(err.Error()) - } - } - - suite.timeline = tl -} - -func (suite *GetTestSuite) TearDownTest() { - testrig.StandardDBTeardown(suite.db) -} - func (suite *GetTestSuite) checkStatuses(statuses []timeline.Preparable, maxID string, minID string, expectedLength int) { if l := len(statuses); l != expectedLength { suite.FailNow("", "expected %d statuses in slice, got %d", expectedLength, l) @@ -127,79 +61,168 @@ func (suite *GetTestSuite) checkStatuses(statuses []timeline.Preparable, maxID s } } +func (suite *GetTestSuite) emptyAccountFollows(ctx context.Context, accountID string) { + // Get all of account's follows. + follows, err := suite.state.DB.GetAccountFollows( + gtscontext.SetBarebones(ctx), + accountID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Remove each follow. + for _, follow := range follows { + if err := suite.state.DB.DeleteFollowByID(ctx, follow.ID); err != nil { + suite.FailNow(err.Error()) + } + } + + // Ensure no follows left. + follows, err = suite.state.DB.GetAccountFollows( + gtscontext.SetBarebones(ctx), + accountID, + ) + if err != nil { + suite.FailNow(err.Error()) + } + if len(follows) != 0 { + suite.FailNow("follows should be empty") + } +} + +func (suite *GetTestSuite) emptyAccountStatuses(ctx context.Context, accountID string) { + // Get all of account's statuses. + statuses, err := suite.state.DB.GetAccountStatuses( + ctx, + accountID, + 9999, + false, + false, + id.Highest, + id.Lowest, + false, + false, + ) + if err != nil { + suite.FailNow(err.Error()) + } + + // Remove each status. + for _, status := range statuses { + if err := suite.state.DB.DeleteStatusByID(ctx, status.ID); err != nil { + suite.FailNow(err.Error()) + } + } +} + func (suite *GetTestSuite) TestGetNewTimelinePageDown() { - // Take a fresh timeline for this test. - // This tests whether indexing works - // properly against uninitialized timelines. - tl := timeline.NewTimeline( - context.Background(), - suite.testAccounts["local_account_1"].ID, - tlprocessor.HomeTimelineGrab(&suite.state), - tlprocessor.HomeTimelineFilter(&suite.state, suite.filter), - tlprocessor.HomeTimelineStatusPrepare(&suite.state, suite.tc), - tlprocessor.SkipInsert(), + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 5 + local = false ) // Get 5 from the top. - statuses, err := tl.Get(context.Background(), 5, "", "", "", true) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } suite.checkStatuses(statuses, id.Highest, id.Lowest, 5) // Get 5 from next maxID. - nextMaxID := statuses[len(statuses)-1].GetID() - statuses, err = tl.Get(context.Background(), 5, nextMaxID, "", "", false) + maxID = statuses[len(statuses)-1].GetID() + statuses, err = suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } - suite.checkStatuses(statuses, nextMaxID, id.Lowest, 5) + suite.checkStatuses(statuses, maxID, id.Lowest, 5) } func (suite *GetTestSuite) TestGetNewTimelinePageUp() { - // Take a fresh timeline for this test. - // This tests whether indexing works - // properly against uninitialized timelines. - tl := timeline.NewTimeline( - context.Background(), - suite.testAccounts["local_account_1"].ID, - tlprocessor.HomeTimelineGrab(&suite.state), - tlprocessor.HomeTimelineFilter(&suite.state, suite.filter), - tlprocessor.HomeTimelineStatusPrepare(&suite.state, suite.tc), - tlprocessor.SkipInsert(), + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = id.Lowest + limit = 5 + local = false ) // Get 5 from the back. - statuses, err := tl.Get(context.Background(), 5, "", "", id.Lowest, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } - suite.checkStatuses(statuses, id.Highest, id.Lowest, 5) + suite.checkStatuses(statuses, id.Highest, minID, 5) - // Page upwards. - nextMinID := statuses[len(statuses)-1].GetID() - statuses, err = tl.Get(context.Background(), 5, "", "", nextMinID, false) + // Page up from next minID. + minID = statuses[0].GetID() + statuses, err = suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } - suite.checkStatuses(statuses, id.Highest, nextMinID, 5) + suite.checkStatuses(statuses, id.Highest, minID, 5) } func (suite *GetTestSuite) TestGetNewTimelineMoreThanPossible() { - // Take a fresh timeline for this test. - // This tests whether indexing works - // properly against uninitialized timelines. - tl := timeline.NewTimeline( - context.Background(), - suite.testAccounts["local_account_1"].ID, - tlprocessor.HomeTimelineGrab(&suite.state), - tlprocessor.HomeTimelineFilter(&suite.state, suite.filter), - tlprocessor.HomeTimelineStatusPrepare(&suite.state, suite.tc), - tlprocessor.SkipInsert(), + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 100 + local = false ) // Get 100 from the top. - statuses, err := tl.Get(context.Background(), 100, id.Highest, "", "", false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -207,29 +230,120 @@ func (suite *GetTestSuite) TestGetNewTimelineMoreThanPossible() { } func (suite *GetTestSuite) TestGetNewTimelineMoreThanPossiblePageUp() { - // Take a fresh timeline for this test. - // This tests whether indexing works - // properly against uninitialized timelines. - tl := timeline.NewTimeline( - context.Background(), - suite.testAccounts["local_account_1"].ID, - tlprocessor.HomeTimelineGrab(&suite.state), - tlprocessor.HomeTimelineFilter(&suite.state, suite.filter), - tlprocessor.HomeTimelineStatusPrepare(&suite.state, suite.tc), - tlprocessor.SkipInsert(), + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = id.Lowest + limit = 100 + local = false ) // Get 100 from the back. - statuses, err := tl.Get(context.Background(), 100, "", "", id.Lowest, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } suite.checkStatuses(statuses, id.Highest, id.Lowest, 16) } +func (suite *GetTestSuite) TestGetNewTimelineNoFollowing() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 10 + local = false + ) + + suite.emptyAccountFollows(ctx, testAccount.ID) + + // Try to get 10 from the top of the timeline. + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) + if err != nil { + suite.FailNow(err.Error()) + } + suite.checkStatuses(statuses, id.Highest, id.Lowest, 5) + + for _, s := range statuses { + if s.GetAccountID() != testAccount.ID { + suite.FailNow("timeline with no follows should only contain posts by timeline owner account") + } + } +} + +func (suite *GetTestSuite) TestGetNewTimelineNoFollowingNoStatuses() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 5 + local = false + ) + + suite.emptyAccountFollows(ctx, testAccount.ID) + suite.emptyAccountStatuses(ctx, testAccount.ID) + + // Try to get 5 from the top of the timeline. + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) + if err != nil { + suite.FailNow(err.Error()) + } + suite.checkStatuses(statuses, id.Highest, id.Lowest, 0) +} + func (suite *GetTestSuite) TestGetNoParams() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 10 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Get 10 statuses from the top (no params). - statuses, err := suite.timeline.Get(context.Background(), 10, "", "", "", false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -241,10 +355,28 @@ func (suite *GetTestSuite) TestGetNoParams() { } func (suite *GetTestSuite) TestGetMaxID() { - // Ask for 10 with a max ID somewhere in the middle of the stack. - maxID := "01F8MHBQCBTDKN6X5VHGMMN4MA" + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + sinceID = "" + minID = "" + limit = 10 + local = false + ) - statuses, err := suite.timeline.Get(context.Background(), 10, maxID, "", "", false) + suite.fillTimeline(testAccount.ID) + + // Ask for 10 with a max ID somewhere in the middle of the stack. + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -254,9 +386,28 @@ func (suite *GetTestSuite) TestGetMaxID() { } func (suite *GetTestSuite) TestGetSinceID() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + minID = "" + limit = 10 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 10 with a since ID somewhere in the middle of the stack. - sinceID := "01F8MHBQCBTDKN6X5VHGMMN4MA" - statuses, err := suite.timeline.Get(context.Background(), 10, "", sinceID, "", false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -269,9 +420,28 @@ func (suite *GetTestSuite) TestGetSinceID() { } func (suite *GetTestSuite) TestGetSinceIDOneOnly() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + minID = "" + limit = 1 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 1 with a since ID somewhere in the middle of the stack. - sinceID := "01F8MHBQCBTDKN6X5VHGMMN4MA" - statuses, err := suite.timeline.Get(context.Background(), 1, "", sinceID, "", false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -284,9 +454,28 @@ func (suite *GetTestSuite) TestGetSinceIDOneOnly() { } func (suite *GetTestSuite) TestGetMinID() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + limit = 5 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 5 with a min ID somewhere in the middle of the stack. - minID := "01F8MHBQCBTDKN6X5VHGMMN4MA" - statuses, err := suite.timeline.Get(context.Background(), 5, "", "", minID, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -299,9 +488,28 @@ func (suite *GetTestSuite) TestGetMinID() { } func (suite *GetTestSuite) TestGetMinIDOneOnly() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + limit = 1 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 1 with a min ID somewhere in the middle of the stack. - minID := "01F8MHBQCBTDKN6X5VHGMMN4MA" - statuses, err := suite.timeline.Get(context.Background(), 1, "", "", minID, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -314,9 +522,28 @@ func (suite *GetTestSuite) TestGetMinIDOneOnly() { } func (suite *GetTestSuite) TestGetMinIDFromLowestInTestrig() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = suite.lowestStatusID + limit = 1 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 1 with minID equal to the lowest status in the testrig. - minID := suite.lowestStatusID - statuses, err := suite.timeline.Get(context.Background(), 1, "", "", minID, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -329,9 +556,28 @@ func (suite *GetTestSuite) TestGetMinIDFromLowestInTestrig() { } func (suite *GetTestSuite) TestGetMinIDFromLowestPossible() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = id.Lowest + limit = 1 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 1 with the lowest possible min ID. - minID := id.Lowest - statuses, err := suite.timeline.Get(context.Background(), 1, "", "", minID, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -344,11 +590,28 @@ func (suite *GetTestSuite) TestGetMinIDFromLowestPossible() { } func (suite *GetTestSuite) TestGetBetweenID() { - // Ask for 10 between these two IDs - maxID := "01F8MHCP5P2NWYQ416SBA0XSEV" - minID := "01F8MHBQCBTDKN6X5VHGMMN4MA" + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = "01F8MHCP5P2NWYQ416SBA0XSEV" + sinceID = "" + minID = "01F8MHBQCBTDKN6X5VHGMMN4MA" + limit = 10 + local = false + ) - statuses, err := suite.timeline.Get(context.Background(), 10, maxID, "", minID, false) + suite.fillTimeline(testAccount.ID) + + // Ask for 10 between these two IDs + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -358,12 +621,29 @@ func (suite *GetTestSuite) TestGetBetweenID() { } func (suite *GetTestSuite) TestGetBetweenIDImpossible() { + var ( + ctx = context.Background() + testAccount = suite.testAccounts["local_account_1"] + maxID = id.Lowest + sinceID = "" + minID = id.Highest + limit = 10 + local = false + ) + + suite.fillTimeline(testAccount.ID) + // Ask for 10 between these two IDs which present // an impossible query. - maxID := id.Lowest - minID := id.Highest - - statuses, err := suite.timeline.Get(context.Background(), 10, maxID, "", minID, false) + statuses, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ) if err != nil { suite.FailNow(err.Error()) } @@ -372,18 +652,49 @@ func (suite *GetTestSuite) TestGetBetweenIDImpossible() { suite.checkStatuses(statuses, maxID, minID, 0) } -func (suite *GetTestSuite) TestLastGot() { - // LastGot should be zero - suite.Zero(suite.timeline.LastGot()) +func (suite *GetTestSuite) TestGetTimelinesAsync() { + var ( + ctx = context.Background() + accountToNuke = suite.testAccounts["local_account_1"] + maxID = "" + sinceID = "" + minID = "" + limit = 5 + local = false + multiplier = 5 + ) - // Get some from the top - _, err := suite.timeline.Get(context.Background(), 10, "", "", "", false) - if err != nil { - suite.FailNow(err.Error()) + // Nuke one account's statuses and follows, + // as though the account had just been created. + suite.emptyAccountFollows(ctx, accountToNuke.ID) + suite.emptyAccountStatuses(ctx, accountToNuke.ID) + + // Get 5 statuses from each timeline in + // our testrig at the same time, five times. + wg := new(sync.WaitGroup) + wg.Add(len(suite.testAccounts) * multiplier) + + for i := 0; i < multiplier; i++ { + go func() { + for _, testAccount := range suite.testAccounts { + if _, err := suite.state.Timelines.Home.GetTimeline( + ctx, + testAccount.ID, + maxID, + sinceID, + minID, + limit, + local, + ); err != nil { + suite.FailNow(err.Error()) + } + + wg.Done() + } + }() } - // LastGot should be updated - suite.WithinDuration(time.Now(), suite.timeline.LastGot(), 1*time.Second) + wg.Wait() // Wait until all get calls have returned. } func TestGetTestSuite(t *testing.T) { |