diff options
Diffstat (limited to 'internal/calendar')
| -rw-r--r-- | internal/calendar/oracle_ef_test.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/internal/calendar/oracle_ef_test.go b/internal/calendar/oracle_ef_test.go index 6d63220..a2bb6a5 100644 --- a/internal/calendar/oracle_ef_test.go +++ b/internal/calendar/oracle_ef_test.go @@ -339,3 +339,65 @@ func TestOracleEF(t *testing.T) { t.Fatalf("%d/%d EF colour mismatches vs missalemeum (not allow-listed)", colourMiss, total) } } + +// TestEFLectionaryKeysAreReachableSlugs asserts that every section name in the +// EF temporal lectionary is a slug the calendar can actually compute. A key +// nothing ever matches is dead data: the reading sits in the file, the lookup +// misses it, and the day silently falls back to the preceding Sunday's Mass — +// which looks like a plausible answer, so nothing downstream notices. +// +// This is not hypothetical. Three sections were filed as ef-lent-1-{wednesday, +// friday,saturday} while temporal_ef.go's efEmberSlug computes +// ef-lent-ember-{wed,fri,sat}, so the Lenten Ember days served Lent I Sunday's +// Mass for as long as the data existed. The keys were stale: they predate Lent +// being added to efEmberSlug, and scripts/genlect.go — which keys off +// day.Observed.Slug — would already write the correct names if re-run. +// +// It survived every existing test because the wrong answer is a real Mass, and +// it survived cross-checking against colitur (the sibling OCaml engine) +// because colitur had bootstrapped the same wrong keys from this very file. +// Two engines agreeing is not evidence when one was seeded from the other. +func TestEFLectionaryKeysAreReachableSlugs(t *testing.T) { + raw, err := os.ReadFile("../caldata/tridentine-lectionary.ini") + if err != nil { + t.Fatalf("read lectionary: %v", err) + } + + keys := map[string]bool{} + for _, line := range strings.Split(string(raw), "\n") { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + keys[line[1:len(line)-1]] = true + } + } + if len(keys) == 0 { + t.Fatal("no sections parsed from the lectionary") + } + + sel := calendar.DefaultSelection() + sel.Form = "old" + layers := []calendar.Layer{caldata.Tridentine()} + + // Twelve years. Every key in the shipped file is reached within five (the + // movable ones recur annually; the Ember and vigil days are the only + // awkward cases and they occur every year too), so this is a bit over + // double the margin actually needed. Widening it costs test time linearly + // and buys nothing measurable — 46 years took 91s, this takes a quarter of + // that — but narrowing below five would start reporting live keys as dead. + seen := map[string]bool{} + for d := time.Date(2005, 1, 1, 0, 0, 0, 0, time.UTC); d.Year() <= 2016; d = d.AddDate(0, 0, 1) { + seen[calendar.Compute(d, sel, layers).Observed.Slug] = true + } + + var dead []string + for k := range keys { + if !seen[k] { + dead = append(dead, k) + } + } + sort.Strings(dead) + if len(dead) > 0 { + t.Errorf("lectionary keys no computed slug ever matches (dead data, the day "+ + "silently falls back to the preceding Sunday): %v", dead) + } +} |
