package lexicon import "testing" // TestClosedSetsAreComplete — the point of the package. A closed class can be // finished, so the test names the members that were MISSING from the inline Go // lists this package replaced (Vikunja #525) and every one of them has to be // there. Add to this list when a form turns up unhandled. func TestClosedSetsAreComplete(t *testing.T) { inter := map[string]bool{} for _, w := range Interrogatives() { inter[w] = true } // Instrumental and prepositional cases of что and кто, and the declined // какой. The old list had что/чего and nothing else, so "чем ты занята" and // "в каком часу" carried no interrogative at all. for _, w := range []string{"чем", "чём", "чему", "кем", "ком", "каком", "какими", "насколько"} { if !inter[w] { t.Errorf("interrogatives is missing %q", w) } } for _, tc := range []struct { word string want int }{ {"ноль", 0}, {"одна", 1}, {"две", 2}, {"одиннадцать", 11}, {"пятнадцать", 15}, {"двадцать", 20}, {"сорок", 40}, {"девяносто", 90}, {"сто", 100}, {"twelve", 12}, } { got, ok := Cardinal(tc.word) if !ok || got != tc.want { t.Errorf("Cardinal(%q) = %d, %v; want %d, true", tc.word, got, ok, tc.want) } } if _, ok := Cardinal("бэкап"); ok { t.Error("Cardinal must not answer for a word that is not a number") } } // TestDayOffsetHasNoOrderingTrap — the defect a lookup removes. The callers this // replaced used strings.Contains in a switch, so "послезавтра" had to be tested // before "завтра" by hand or the day after tomorrow read as tomorrow. func TestDayOffsetHasNoOrderingTrap(t *testing.T) { for _, tc := range []struct { text string want int ok bool }{ {"послезавтра", 2, true}, {"завтра", 1, true}, {"сегодня", 0, true}, {"вчера", -1, true}, {"позавчера", -2, true}, {"встреча послезавтра в 14:30", 2, true}, {"Tomorrow at 09:00", 1, true}, {"не сегодня, а послезавтра", 2, true}, {"в четверг", 0, false}, {"завтраком", 0, false}, } { got, ok := DayOffsetIn(tc.text) if ok != tc.ok || (ok && got != tc.want) { t.Errorf("DayOffsetIn(%q) = %d, %v; want %d, %v", tc.text, got, ok, tc.want, tc.ok) } } // "сегодня" is offset 0, which is also the zero value, so the second return // is the only thing that separates a hit from a miss. if n, ok := DayOffset("сегодня"); n != 0 || !ok { t.Errorf("DayOffset(сегодня) = %d, %v; want 0, true", n, ok) } } // TestIndexedSetsLineUpWithTheirCallers — weekdays start at Sunday because Go's // time.Weekday does, and months are 1-indexed so a month number needs no // arithmetic. Off-by-one here is a wrong date spoken out loud. func TestIndexedSetsLineUpWithTheirCallers(t *testing.T) { if got := Weekday(0); got != "воскресенье" { t.Errorf("Weekday(0) = %q, want воскресенье", got) } if got := Weekday(1); got != "понедельник" { t.Errorf("Weekday(1) = %q, want понедельник", got) } if got := MonthGenitive(1); got != "января" { t.Errorf("MonthGenitive(1) = %q, want января", got) } if got := MonthGenitive(12); got != "декабря" { t.Errorf("MonthGenitive(12) = %q, want декабря", got) } if got := MonthGenitive(0); got != "" { t.Errorf("MonthGenitive(0) = %q, want the empty slot", got) } if got := HourSpoken(23); got != "двадцать три" { t.Errorf("HourSpoken(23) = %q, want двадцать три", got) } for _, i := range []int{-1, 7, 13, 24} { if got := Weekday(i); i >= 7 && got != "" { t.Errorf("Weekday(%d) = %q, want empty", i, got) } } if got := HourSpoken(24); got != "" { t.Errorf("HourSpoken(24) = %q, want empty", got) } } // TestCallerCannotEditTheLexicon — the sets are handed out as copies. A caller // that sorted the slice it was given would otherwise reorder weekdays for // everybody. func TestCallerCannotEditTheLexicon(t *testing.T) { first := Interrogatives() first[0] = "мутировало" if again := Interrogatives(); again[0] == "мутировало" { t.Fatal("the lexicon handed out its own backing array") } }