Artifact ceb42101b5af64b671c73b9c866a6ce7afebf67778e8a66117fcd6c3ce2499f1:
- File
internal/oltp/vote_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: 3358) [annotate] [blame] [check-ins using]
package oltp import "testing" func TestForumVoteRoundTrip(t *testing.T) { db := testDB(t) // Vote, and the score reflects it. if err := db.SetForumVote("r", "alice", "post1", "thread1", 1); err != nil { t.Fatal(err) } if err := db.SetForumVote("r", "bob", "post1", "thread1", -1); err != nil { t.Fatal(err) } if err := db.SetForumVote("r", "carol", "post1", "thread1", 1); err != nil { t.Fatal(err) } scores, err := db.ForumPostScores("r", []string{"post1", "absent"}) if err != nil { t.Fatal(err) } if scores["post1"] != 1 { t.Fatalf("post1 score = %d, want 1", scores["post1"]) } if _, ok := scores["absent"]; ok { t.Fatal("unvoted post must be absent from the map, not zero-valued in it") } // Changing a vote replaces it — the (repo, account, post) key is the // idempotency: two upvotes from one account are one upvote. if err := db.SetForumVote("r", "alice", "post1", "thread1", -1); err != nil { t.Fatal(err) } scores, _ = db.ForumPostScores("r", []string{"post1"}) if scores["post1"] != -1 { t.Fatalf("after alice flips: score = %d, want -1", scores["post1"]) } // Retracting (dir 0) deletes the row. if err := db.SetForumVote("r", "bob", "post1", "thread1", 0); err != nil { t.Fatal(err) } scores, _ = db.ForumPostScores("r", []string{"post1"}) if scores["post1"] != 0 { t.Fatalf("after bob retracts: score = %d, want 0", scores["post1"]) } // Anything other than -1, 0, 1 is refused. if err := db.SetForumVote("r", "mallory", "post1", "thread1", 5); err == nil { t.Fatal("dir 5 accepted") } } func TestForumThreadScoresAggregate(t *testing.T) { db := testDB(t) must := func(err error) { t.Helper() if err != nil { t.Fatal(err) } } must(db.SetForumVote("r", "alice", "p1", "t1", 1)) must(db.SetForumVote("r", "bob", "p2", "t1", 1)) must(db.SetForumVote("r", "carol", "p3", "t2", -1)) // Another repo's votes must not bleed in. must(db.SetForumVote("other", "dave", "p1", "t1", -1)) scores, err := db.ForumThreadScores("r", []string{"t1", "t2", "t3"}) if err != nil { t.Fatal(err) } if scores["t1"] != 2 || scores["t2"] != -1 { t.Fatalf("thread scores = %v, want t1:2 t2:-1", scores) } if _, ok := scores["t3"]; ok { t.Fatal("unvoted thread present in map") } } func TestForumAccountVotes(t *testing.T) { db := testDB(t) if err := db.SetForumVote("r", "alice", "p1", "t1", 1); err != nil { t.Fatal(err) } if err := db.SetForumVote("r", "alice", "p2", "t1", -1); err != nil { t.Fatal(err) } mine, err := db.ForumAccountVotes("r", "alice", []string{"p1", "p2", "p3"}) if err != nil { t.Fatal(err) } if mine["p1"] != 1 || mine["p2"] != -1 { t.Fatalf("account votes = %v", mine) } if _, ok := mine["p3"]; ok { t.Fatal("unvoted post present") } // Empty account (anonymous) asks for nothing and gets nothing. if none, _ := db.ForumAccountVotes("r", "", []string{"p1"}); len(none) != 0 { t.Fatalf("anonymous votes = %v, want empty", none) } } func TestPurgeRepoSweepsForumVotes(t *testing.T) { db := testDB(t) if err := db.SetForumVote("gone", "alice", "p1", "t1", 1); err != nil { t.Fatal(err) } if err := db.PurgeRepo("gone"); err != nil { t.Fatal(err) } scores, err := db.ForumPostScores("gone", []string{"p1"}) if err != nil { t.Fatal(err) } if len(scores) != 0 { t.Fatalf("votes survived purge: %v", scores) } }