diff options
Diffstat (limited to 'internal/cache/timeline/status_test.go')
| -rw-r--r-- | internal/cache/timeline/status_test.go | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/internal/cache/timeline/status_test.go b/internal/cache/timeline/status_test.go index 6a288d2ea..fc7e43da8 100644 --- a/internal/cache/timeline/status_test.go +++ b/internal/cache/timeline/status_test.go @@ -18,11 +18,16 @@ package timeline import ( + "context" + "fmt" "slices" "testing" apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model" "code.superseriousbusiness.org/gotosocial/internal/gtsmodel" + "code.superseriousbusiness.org/gotosocial/internal/id" + "code.superseriousbusiness.org/gotosocial/internal/log" + "code.superseriousbusiness.org/gotosocial/internal/paging" "codeberg.org/gruf/go-structr" "github.com/stretchr/testify/assert" ) @@ -60,6 +65,46 @@ var testStatusMeta = []*StatusMeta{ }, } +func TestStatusTimelineLoadLimit(t *testing.T) { + var tt StatusTimeline + tt.Init(1000) + + // Prepare new context for the duration of this test. + ctx, cncl := context.WithCancel(context.Background()) + defer cncl() + + // Clone the input test status data. + data := slices.Clone(testStatusMeta) + + // Insert test data into timeline. + _ = tt.cache.Insert(data...) + + // Manually mark timeline as 'preloaded'. + tt.preloader.CheckPreload(tt.preloader.Done) + + // Craft a new page for selection, + // setting placeholder min / max values + // but in particular setting a limit + // HIGHER than currently cached values. + page := new(paging.Page) + page.Min = paging.MinID(id.Lowest) + page.Max = paging.MaxID(id.Highest) + page.Limit = len(data) + 10 + + // Load crafted page from the cache. This + // SHOULD load all cached entries, then + // generate an extra 10 statuses up to limit. + apiStatuses, _, _, err := tt.Load(ctx, + page, + loadGeneratedStatusPage, + loadStatusIDsFrom(data), + nil, // no filtering + func(status *gtsmodel.Status) (*apimodel.Status, error) { return new(apimodel.Status), nil }, + ) + assert.NoError(t, err) + assert.Len(t, apiStatuses, page.Limit) +} + func TestStatusTimelineUnprepare(t *testing.T) { var tt StatusTimeline tt.Init(1000) @@ -301,6 +346,44 @@ func TestStatusTimelineTrim(t *testing.T) { assert.Equal(t, before, tt.cache.Len()) } +// loadStatusIDsFrom imitates loading of statuses of given IDs from the database, instead selecting +// statuses with appropriate IDs from the given slice of status meta, converting them to statuses. +func loadStatusIDsFrom(data []*StatusMeta) func(ids []string) ([]*gtsmodel.Status, error) { + return func(ids []string) ([]*gtsmodel.Status, error) { + var statuses []*gtsmodel.Status + for _, id := range ids { + i := slices.IndexFunc(data, func(s *StatusMeta) bool { + return s.ID == id + }) + if i < 0 || i >= len(data) { + panic(fmt.Sprintf("could not find %s in %v", id, log.VarDump(data))) + } + statuses = append(statuses, >smodel.Status{ + ID: data[i].ID, + AccountID: data[i].AccountID, + BoostOfID: data[i].BoostOfID, + BoostOfAccountID: data[i].BoostOfAccountID, + }) + } + return statuses, nil + } +} + +// loadGeneratedStatusPage imitates loading of a given page of statuses, +// simply generating new statuses until the given page's limit is reached. +func loadGeneratedStatusPage(page *paging.Page) ([]*gtsmodel.Status, error) { + var statuses []*gtsmodel.Status + for range page.Limit { + statuses = append(statuses, >smodel.Status{ + ID: id.NewULID(), + AccountID: id.NewULID(), + BoostOfID: id.NewULID(), + BoostOfAccountID: id.NewULID(), + }) + } + return statuses, nil +} + // containsStatusID returns whether timeline contains a status with ID. func containsStatusID(t *StatusTimeline, id string) bool { return getStatusByID(t, id) != nil |
