1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package calendar_test
// Reproduction tests for three named EF precedence defects (colitur's
// differential/oracle audit against lectio's ~66-line EF precedence
// approximation, internal/calendar/precedence_ef.go). Each test fails before
// its fix and passes after -- see the report for the exact pre-fix failure
// message. These exercise the REAL tridentine sanctoral data
// (caldata.Tridentine()) through the public Compute entry point, since the
// bugs are about how real fixed-date feasts interact with the temporal
// calendar, not about precedenceEF's arithmetic in isolation (that is
// covered separately, package-internal, in precedence_ef_test.go).
import (
"testing"
"time"
"github.com/lukaszkasprzak/lectio/internal/caldata"
"github.com/lukaszkasprzak/lectio/internal/calendar"
)
func efCompute(date string) calendar.LiturgicalDay {
sel := calendar.DefaultSelection()
sel.Form = "old"
d, _ := time.Parse("2006-01-02", date)
return calendar.Compute(d.UTC(), sel, []calendar.Layer{caldata.Tridentine()})
}
// TestJosephYieldsToSundayOfLent: RG 91 entry 6 (Sundays of Lent, I class)
// vs entry 11 (I-class feasts of the universal Church not above) -- the
// Sunday holds; St Joseph (19 March) transfers to the next free day (RG 95,
// RG 96), landing on the 20th. Before the fix (defect 4: Sunday ranks), Lent
// Sundays were wrongly II class, so Joseph (I class) won outright every time
// this collision occurred.
func TestJosephYieldsToSundayOfLent(t *testing.T) {
for _, year := range []string{"2006", "2017", "2023", "2028", "2034", "2045"} {
sunday := efCompute(year + "-03-19")
if sunday.Observed.Slug == "joseph-spouse-of-the-bl-virgin-mary" {
t.Errorf("%s-03-19 observed = %q want the Lent Sunday (RG 91 entry 6 beats entry 11)", year, sunday.Observed.Slug)
}
next := efCompute(year + "-03-20")
if next.Observed.Slug != "joseph-spouse-of-the-bl-virgin-mary" {
t.Errorf("%s-03-20 observed = %q want joseph-spouse-of-the-bl-virgin-mary (transferred one day, RG 96)", year, next.Observed.Slug)
}
}
}
// TestTransferSkipsBothIAndIIClass: RG 96 -- an impeded I-class feast
// transfers to the next day that is NOT ITSELF I OR II CLASS (not merely "not
// I class"). 2011: the Sacred Heart (Friday after the Corpus Christi octave)
// falls on 1 July and impedes the Precious Blood (also 1 July, fixed). 2
// July is the Visitation (II class, fixed); 3 July is an ordinary II-class
// Sunday. Both must be skipped; the Precious Blood lands on 4 July, and the
// Visitation is observed, undisplaced, on its own day.
func TestTransferSkipsBothIAndIIClass(t *testing.T) {
if got := efCompute("2011-07-01").Observed.Slug; got != "ef-sacred-heart" {
t.Fatalf("2011-07-01 observed = %q want ef-sacred-heart", got)
}
if got := efCompute("2011-07-02").Observed.Slug; got != "visitation-of-the-blessed-virgin-mary" {
t.Errorf("2011-07-02 observed = %q want visitation-of-the-blessed-virgin-mary (RG 96: the Precious Blood must skip past it, not displace it)", got)
}
if got := efCompute("2011-07-03").Observed.Slug; got != "ef-time-after-pentecost-sunday-3" {
t.Errorf("2011-07-03 observed = %q want ef-time-after-pentecost-sunday-3 (an ordinary II-class Sunday also blocks a I-class transfer)", got)
}
if got := efCompute("2011-07-04").Observed.Slug; got != "precious-blood-of-our-lord-jesus-christ" {
t.Errorf("2011-07-04 observed = %q want precious-blood-of-our-lord-jesus-christ (RG 96: first day that is neither I nor II class)", got)
}
}
// TestMatthewBeatsSeptemberEmberWednesday: RG 91 -- St Matthew (21 September,
// II class) and the September Ember Wednesday are both II class; the table
// decides the tie. Entry 16 (II-class feasts of the universal Church) sits
// ABOVE entry 18 (II-class ferias, including the Ember days) -- the feast
// wins, the Ember feria is only commemorated.
func TestMatthewBeatsSeptemberEmberWednesday(t *testing.T) {
// 21 September falls on the September Ember Wednesday whenever the third
// Sunday of September is the 18th -- 2016 and 2022 both qualify.
for _, date := range []string{"2016-09-21", "2022-09-21"} {
day := efCompute(date)
if day.Observed.Slug != "matthew" {
t.Errorf("%s observed = %q want matthew (RG 91 entry 16 beats entry 18)", date, day.Observed.Slug)
}
}
}
// TestImmaculateConceptionBeatsAdventSunday: found, not named among the
// seven, while verifying defect 4 (Sunday ranks) against the real sanctoral
// data. RG 91 entry 4 (Immaculate Conception, Assumption BVM) sits ABOVE
// entry 6 (Sundays of Advent/Lent/Passiontide) -- unlike an ORDINARY
// I-class feast (entry 11, e.g. St Joseph), the Immaculate Conception
// (8 December) is not impeded by the Advent Sunday it falls on at all. Before
// defect 4's own fix, Advent Sundays were wrongly II class, so this was
// accidentally right (I class beats II class outright); once Sundays became
// I class the tie mattered for the first time.
func TestImmaculateConceptionBeatsAdventSunday(t *testing.T) {
for _, year := range []string{"2013", "2019", "2024"} {
day := efCompute(year + "-12-08")
if day.Observed.Slug != "immaculate-conception-of-the-blessed-virgin-mary" {
t.Errorf("%s-12-08 observed = %q want immaculate-conception-of-the-blessed-virgin-mary (RG 91 entry 4 beats entry 6)", year, day.Observed.Slug)
}
}
}
// TestVigilOfChristmasSurvivesAdventSunday: found, not named among the
// seven, while verifying defect 4 against the real sanctoral data -- and
// worse than a wrong winner. RG 91 entry 5 (Vigil & Octave day of the
// Nativity) also sits above entry 6, so the Vigil of Christmas (24 December)
// is not impeded by falling on Advent IV either. Without this, defect 4
// alone would have made the Advent Sunday win a genuine tie, sending the
// Vigil into transferIfImpededEF's forward walk -- which has no way to
// re-place a transfer that crosses the Dec31/Jan1 boundary (celebrationDate
// re-resolves a fixed date using the year of whatever day is being queried,
// so a walk landing in the following January can never match the query that
// produced it). The Vigil did not move to the wrong day; it vanished for the
// whole year.
func TestVigilOfChristmasSurvivesAdventSunday(t *testing.T) {
for _, year := range []string{"2006", "2017", "2023", "2028"} {
day := efCompute(year + "-12-24")
if day.Observed.Slug != "vigil-of-christmas" {
t.Errorf("%s-12-24 observed = %q want vigil-of-christmas (RG 91 entry 5 beats entry 6; must not vanish)", year, day.Observed.Slug)
}
}
}
|