| 1 | package sessioncatalog |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "testing" |
| 6 | ) |
| 7 | |
| 8 | func TestListTopicsManualOrderIsAppliedBeforePagination(t *testing.T) { |
| 9 | t.Parallel() |
| 10 | ctx := context.Background() |
| 11 | catalog, err := Open(ctx, Options{InMemory: true, DisableRepair: true}) |
| 12 | if err != nil { |
| 13 | t.Fatal(err) |
| 14 | } |
| 15 | t.Cleanup(func() { _ = catalog.Close(context.Background()) }) |
| 16 | |
| 17 | activity := map[string]int64{"a": 300, "b": 200, "c": 100, "unranked": 400} |
| 18 | for topicID, lastActivity := range activity { |
| 19 | if err := catalog.UpsertSession(ctx, SessionRecord{ |
| 20 | Path: "/sessions/" + topicID + ".jsonl", Directory: "/sessions", |
| 21 | Scope: "global", TopicID: topicID, TopicTitle: topicID, |
| 22 | LastActivityAt: lastActivity, Turns: 1, TurnsState: TurnsValid, Health: HealthOK, |
| 23 | }); err != nil { |
| 24 | t.Fatal(err) |
| 25 | } |
| 26 | } |
| 27 | if err := catalog.SyncMetadata(ctx, nil, []TopicMetadata{ |
| 28 | {Scope: "global", TopicID: "a", Title: "a", SortOrder: 2}, |
| 29 | {Scope: "global", TopicID: "b", Title: "b", SortOrder: 1}, |
| 30 | {Scope: "global", TopicID: "c", Title: "c", SortOrder: 0}, |
| 31 | }); err != nil { |
| 32 | t.Fatal(err) |
| 33 | } |
| 34 | |
| 35 | first, err := catalog.ListTopics(ctx, TopicPageRequest{Scope: "global", Limit: 2, ManualOrder: true}) |
| 36 | if err != nil { |
| 37 | t.Fatal(err) |
| 38 | } |
| 39 | second, err := catalog.ListTopics(ctx, TopicPageRequest{ |
| 40 | Scope: "global", Limit: 2, ManualOrder: true, Cursor: first.NextCursor, |
| 41 | }) |
| 42 | if err != nil { |
| 43 | t.Fatal(err) |
| 44 | } |
| 45 | if len(first.Items) != 2 || len(second.Items) != 2 || first.NextCursor == "" || second.NextCursor != "" { |
| 46 | t.Fatalf("manual pages = first %#v second %#v", first, second) |
| 47 | } |
| 48 | got := []string{first.Items[0].TopicID, first.Items[1].TopicID, second.Items[0].TopicID, second.Items[1].TopicID} |
| 49 | want := []string{"c", "b", "a", "unranked"} |
| 50 | for i := range want { |
| 51 | if got[i] != want[i] { |
| 52 | t.Fatalf("manual keyset order = %v, want %v", got, want) |
| 53 | } |
| 54 | } |
| 55 | if second.Items[1].SortOrder != -1 { |
| 56 | t.Fatalf("unranked sort order = %d, want -1", second.Items[1].SortOrder) |
| 57 | } |
| 58 | if _, err := catalog.ListTopics(ctx, TopicPageRequest{Scope: "global", Limit: 2, Cursor: first.NextCursor}); err == nil { |
| 59 | t.Fatal("manual cursor reused with activity ordering should fail") |
| 60 | } |
| 61 | } |
| 62 |