Artifact ef44539ebf68cd2f5e8e9d823c49f20198d82f9d71484b30fd34962933a31c00:
- File
internal/evt/evt_test.go
— part of check-in
[f1a6be9a77]
at
2026-08-24 19:59:53
on branch praise
— Praise: vocabulary, storage, ops
Any signed-in account may praise any repository it can SEE — no capability letter, because the read gate has already decided whether the repository exists for this caller and past that gate praising is not a privilege anyone needs granting.
Per account, not per contributor: someone who has never authored an artifact can still say a repository is worth attention, which is why this cannot hang off the contributor pages.
praise.list filters by the VIEWER, never the owner. Praise is public; the existence of a private repository is not, and this is where the two meet.
UI deferred: the button belongs in the repo stats strip, which is on the unlanded clone-counts branch. (user: dmestas, size: 4904) [annotate] [blame] [check-ins using] [more...]
package evt import "testing" // A subscription naming a noun selects every action on it, including ones // added after the subscription was written. That is the entire argument for // noun-and-action over Gitea's one-name-per-verb, so it is the thing to pin. func TestANounSelectsEveryActionOnIt(t *testing.T) { if !TicketClosed.Matches("ticket") { t.Error(`"ticket" does not select ticket.closed`) } if !TicketOpened.Matches("ticket") { t.Error(`"ticket" does not select ticket.opened`) } if !TicketClosed.Matches("ticket.closed") { t.Error("an exact kind does not select itself") } // Precision is available where it is wanted. if TicketOpened.Matches("ticket.closed") { t.Error("ticket.closed selected ticket.opened") } // A noun does not reach across nouns, however similar the names. if LandingOpened.Matches("ticket") { t.Error("a noun selected another noun's event") } // A pattern naming a noun that does not exist selects nothing rather // than everything — the failure of a typo must be silence, not a // firehose. if TicketClosed.Matches("tickets") || TicketClosed.Matches("") { t.Error("a bad pattern matched") } } // The bus is a one-hour window, so what happens to a missed event depends on // whether it can be re-derived from the store. Getting this classification // wrong is how an operational fact — a failed mirror pull — silently does not // happen, so each noun is asserted rather than the rule restated. func TestDerivedEventsAreExactlyTheOnesTheStoreHolds(t *testing.T) { for _, k := range []Kind{CheckinCreated, BranchMoved, TagCreated, TicketClosed, WikiEdited, TechnoteCreated, ForumPosted, LandingAccepted} { if !k.Derived() { t.Errorf("%s is a reading of stored artifacts and should be derived", k) } } // None of these is in the DAG: missing one loses the fact, so each // must be recorded in OLTP as it is raised. for _, k := range []Kind{CICompleted, MirrorFailed, RepoCreated, AccountCaps, CloneCloned} { if k.Derived() { t.Errorf("%s is not in the store and must not be treated as re-derivable", k) } } } // An unknown name is refused where the subscription is written. A pipeline // that never runs and a pipeline that runs and fails look nothing alike to // the person waiting for it. func TestUnknownKindsAreRefused(t *testing.T) { for _, bad := range []Kind{"ticket.exploded", "issue.opened", "checkin", ""} { if bad.Valid() { t.Errorf("%q was accepted into the vocabulary", bad) } } for _, k := range All { if !k.Valid() { t.Errorf("%s is in All but not Valid", k) } if k.Noun() == "" || k.Action() == "" { t.Errorf("%s is not noun.action", k) } } } // The vocabulary is a published interface: a name in someone else's pipeline // definition. This pins the set so a rename is a deliberate act with a // failing test attached, not a refactor that quietly breaks every store. func TestTheVocabularyIsFixed(t *testing.T) { if got, want := len(All), 37; got != want { t.Errorf("the vocabulary changed size: %d, was %d — if deliberate, say so in RFC 0005", got, want) } want := []string{"checkin", "branch", "tag", "ticket", "wiki", "technote", "forum", "landing", "ci", "mirror", "repo", "account", "praise", "clone"} got := Nouns() if len(got) != len(want) { t.Fatalf("nouns = %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("nouns = %v, want %v", got, want) } } } // The subject is the subscription interface: dagnats triggers take a NATS // subject filter, so the vocabulary has to survive being taken apart by // wildcards. A noun or action containing a dot would silently break every // filter that assumed the shape. func TestEverySubjectHasExactlyFiveTokens(t *testing.T) { for _, k := range All { got := k.Subject("quarry") if n := len(splitDots(got)); n != 5 { t.Errorf("%s -> %s has %d tokens, want 5 (quarry.evt.repo.noun.action)", k, got, n) } } if got, want := LandingOpened.Subject("quarry"), "quarry.evt.quarry.landing.opened"; got != want { t.Errorf("subject = %q, want %q", got, want) } } func splitDots(s string) []string { var out []string start := 0 for i := 0; i < len(s); i++ { if s[i] == '.' { out = append(out, s[start:i]) start = i + 1 } } return append(out, s[start:]) } // The vocabulary must stay off zit's DAG-transport root. The ingest // pipeline's fold consumer subscribes to `zit.evt.<repo>.>` and parses // everything it receives as an artifact, so an event published under that // root is not merely sharing a stream — it is handed to a consumer that // will try to fold it. This test is the tripwire on moving it back. func TestVocabularyStaysOffTheIngestRoot(t *testing.T) { for _, k := range All { if s := k.Subject("quarry"); len(s) < 7 || s[:7] != "quarry." { t.Fatalf("%s publishes to %q; the vocabulary root must be quarry.", k, s) } } }