Artifact ac9fdec24ae226eefb51a6944cd5bf93114522b52ff068a15fe7d8ae500e2e58:
- File
internal/index/forum_test.go
— part of check-in
[2fd88bc87a]
at
2026-08-21 19:17:01
on branch quarry-forum
— forum votes: OLTP vote store, forum.vote op, arrows + derived scores
Score is always derived from vote rows (no counter); votes are forge-local 0001 ยง8 state, never synced. Umbrella plan: ticket aa351dec. (user: dmestas, size: 1423) [annotate] [blame] [check-ins using]
package index import ( "testing" "craftdesign.group/quarry/internal/artifact" ) func foldForum(t *testing.T, ix *Index, hash, root, parent, title, date string) { t.Helper() if err := ix.FoldNow([]Parsed{{Hash: hash, Art: &artifact.Artifact{ Type: artifact.Forum, ThreadRoot: root, InReplyTo: parent, ThreadTitle: title, Date: date, User: "dan", Body: []byte("hi"), }}}); err != nil { t.Fatal(err) } } // Votes are keyed on full post hashes while pages link with prefixes; // the resolver bridges the two and also answers which thread a post // belongs to, so a vote row can carry its thread without trusting the // form data. func TestForumPostThreadResolvesPrefix(t *testing.T) { ix := openIndex(t) foldForum(t, ix, "aaaa1111", "", "", "hello", "2026-01-01T10:00:00") foldForum(t, ix, "bbbb2222", "aaaa1111", "aaaa1111", "", "2026-01-02T10:00:00") post, thread, ok, err := ix.ForumPostThread("bbbb") if err != nil || !ok { t.Fatalf("resolve reply: ok=%v err=%v", ok, err) } if post != "bbbb2222" || thread != "aaaa1111" { t.Fatalf("reply resolved to post=%q thread=%q", post, thread) } // An opener roots its own thread. if _, thread, _, _ := ix.ForumPostThread("aaaa"); thread != "aaaa1111" { t.Fatalf("opener thread = %q, want itself", thread) } if _, _, ok, err := ix.ForumPostThread("ffff"); ok || err != nil { t.Fatalf("absent prefix: ok=%v err=%v, want false nil", ok, err) } }