Artifact 598d000ccfbd656b107eeefc8607ea1a49eede57998e6febb597085edf7ebae5:
- File
internal/index/wiki_test.go
— part of check-in
[9b2b188ece]
at
2026-08-23 11:08:48
on branch trunk
— caps: private tickets exist for holders of e
The edge resolved a CapSet and threw it away; it now rides the context, so an op can ask which letters the caller holds. Private tickets list, count and resolve for e, and for nobody else. One privacyWhere() so a fourth read path cannot silently ship without the clause. (user: dmestas, size: 4911) [annotate] [blame] [check-ins using]
package index import ( "testing" "craftdesign.group/quarry/internal/artifact" "craftdesign.group/quarry/internal/markup" ) func foldWiki(t *testing.T, ix *Index, hash, title, date, body string) { t.Helper() if err := ix.FoldNow([]Parsed{{Hash: hash, Art: &artifact.Artifact{ Type: artifact.Wiki, WikiTitle: title, Date: date, User: "dan", Body: []byte(body), }}}); err != nil { t.Fatal(err) } } // Fossil deletes a wiki page by writing an edit with an EMPTY body. // A page whose newest edit is empty must vanish from the list and the // count — while its history stays fully readable, because the edits are // real artifacts and a deleted page is still part of the record. And a // page deleted then re-created is simply live again: the newest edit // decides, not any edit. func TestDeletedWikiPagesLeaveTheListButKeepTheirHistory(t *testing.T) { ix := openIndex(t) foldWiki(t, ix, "w1", "Guide", "2026-01-01T10:00:00", "how to") foldWiki(t, ix, "w2", "Scratch", "2026-01-02T10:00:00", "notes") foldWiki(t, ix, "w3", "Scratch", "2026-01-03T10:00:00", "") // deleted foldWiki(t, ix, "w4", "Phoenix", "2026-01-04T10:00:00", "v1") foldWiki(t, ix, "w5", "Phoenix", "2026-01-05T10:00:00", "") // deleted... foldWiki(t, ix, "w6", "Phoenix", "2026-01-06T10:00:00", "v2") // ...and back titles, err := ix.WikiTitles() if err != nil { t.Fatal(err) } var names []string for _, w := range titles { names = append(names, w.Title) } if len(names) != 2 || names[0] != "Guide" || names[1] != "Phoenix" { t.Fatalf("live pages = %v, want [Guide Phoenix]: newest edit decides", names) } // The count sits above the list and must agree with it — a count // that includes what the list hides is a confirmation leak in // miniature and simply wrong here. c, err := ix.Counts(false) if err != nil { t.Fatal(err) } if c.WikiPages != 2 { t.Fatalf("count = %d, want 2 (the list's own rule)", c.WikiPages) } // History intact: the deleted page's revisions still resolve. if edits, err := ix.WikiHistory("Scratch"); err != nil || len(edits) != 2 { t.Fatalf("deleted page's history: %d edits, err=%v; the record must survive deletion", len(edits), err) } if rev, ok, err := ix.WikiRevision("Scratch", ""); err != nil || !ok || len(rev.Body) != 0 { t.Fatalf("deleted page's latest revision unreadable (ok=%v err=%v)", ok, err) } old, ok, err := ix.WikiRevision("Scratch", "w2") if err != nil || !ok || string(old.Body) != "notes" { t.Fatalf("deleted page's old content unreadable (ok=%v err=%v body=%q)", ok, err, old.Body) } } // A wiki's two maintenance questions, which listing its pages cannot // answer: what can nobody reach, and what does it promise but not have. func TestWikiLinksFindsOrphansAndWantedPages(t *testing.T) { ix := openIndex(t) foldWiki(t, ix, "w1", "Home", "2026-01-01T10:00:00", "See [[Guide]] and [[Missing]].") foldWiki(t, ix, "w2", "Guide", "2026-01-02T10:00:00", "Back to [[Home]], also [[Missing]].") foldWiki(t, ix, "w3", "Lonely", "2026-01-03T10:00:00", "Nothing points here. [[Lonely]].") foldWiki(t, ix, "w4", "Gone", "2026-01-04T10:00:00", "[[Guide]]") foldWiki(t, ix, "w5", "Gone", "2026-01-05T10:00:00", "") // deleted st, err := ix.WikiLinks("Home", markup.WikiRefs) if err != nil { t.Fatal(err) } // Home is where a reader starts, so nothing needs to point at it; // a page that links only to itself is still unreachable. if len(st.Orphans) != 1 || st.Orphans[0] != "Lonely" { t.Fatalf("orphans = %v, want [Lonely]: Home is the entrance and a self-link is not an inbound link", st.Orphans) } // Two live pages ask for Missing; the deleted page's link to Guide // counts for nothing, because a deleted page is not live text. if len(st.Wanted) != 1 || st.Wanted[0].Title != "Missing" || st.Wanted[0].Links != 2 { t.Fatalf("wanted = %+v, want Missing asked for twice", st.Wanted) } } // Fossil renders [Name] as a link only when the page exists and leaves // it as prose otherwise. Reading it as a request for a page filled the // wanted list of fossil's own wiki with shell fragments and hashes — // ordinary sentences that happen to sit in square brackets. func TestFossilBracketsAreProseUntilTheyResolve(t *testing.T) { ix := openIndex(t) foldWiki(t, ix, "w1", "Home", "2026-01-01T10:00:00", "Run [ ! -z \"$text\" ] and see [Guide] and [[Wanted]].") foldWiki(t, ix, "w2", "Guide", "2026-01-02T10:00:00", "content") st, err := ix.WikiLinks("Home", markup.WikiRefs) if err != nil { t.Fatal(err) } // [Guide] resolves, so Guide is reached and not an orphan. for _, o := range st.Orphans { if o == "Guide" { t.Error("a resolving [Guide] did not count as an inbound link") } } // Only the double-bracket form asks for a page that is not there. if len(st.Wanted) != 1 || st.Wanted[0].Title != "Wanted" { t.Fatalf("wanted = %+v, want only the [[Wanted]] request", st.Wanted) } }