// SPDX-License-Identifier: GPL-3.0-or-later package norm import "testing" func TestFold(t *testing.T) { tests := map[string]string{ "": "", "plain ASCII 123": "plain ASCII 123", "spółka z ograniczoną odpowiedzialnością": "spolka z ograniczona odpowiedzialnoscia", "Łódź": "Lodz", "ZAŻÓŁĆ GĘŚLĄ JAŹŃ": "ZAZOLC GESLA JAZN", "Straße": "Strasse", "STRAẞE": "STRASSE", "\xf3Á": "\ufffdA", // an invalid byte must not stop the next letter folding "Øresund": "Oresund", "Ærø": "AEro", "œuvre": "oeuvre", "déjà vu": "deja vu", "Đakovo": "Dakovo", "ħelp": "help", } for in, want := range tests { if got := Fold(in); got != want { t.Errorf("Fold(%q) = %q, want %q", in, got, want) } } } func TestText(t *testing.T) { tests := []struct { in string ignoreCase, fold bool want string }{ {" Hello\n\tWORLD ", true, false, "hello world"}, {"A B\r\nC", false, false, "A B C"}, {"ZAŻÓŁĆ gęślą", true, true, "zazolc gesla"}, {"Spółka", false, true, "Spolka"}, {"Faktura\u00A0VAT", true, false, "faktura vat"}, {"", true, true, ""}, {" ", true, true, ""}, } for _, tt := range tests { if got := Text(tt.in, tt.ignoreCase, tt.fold); got != tt.want { t.Errorf("Text(%q, %v, %v) = %q, want %q", tt.in, tt.ignoreCase, tt.fold, got, tt.want) } } } func TestTextIdempotent(t *testing.T) { for _, s := range []string{" Łódź\n\nMIASTO ", "a\tb", "Ærø Œuvre"} { once := Text(s, true, true) if twice := Text(once, true, true); twice != once { t.Errorf("Text not idempotent on %q: %q then %q", s, once, twice) } } } func TestName(t *testing.T) { if got := Name("Spółka.PDF", true); got != "Spolka.PDF" { t.Errorf("Name fold = %q", got) } if got := Name("Spółka.PDF", false); got != "Spółka.PDF" { t.Errorf("Name no fold = %q", got) } } func TestFoldASCIINoAlloc(t *testing.T) { s := "already plain ascii text" if n := testing.AllocsPerRun(100, func() { _ = Fold(s) }); n != 0 { t.Errorf("Fold allocates %v times on ASCII input", n) } } // TestFoldMappedSource: a part of the folded text leads back to the original // characters it came from, widened to whole characters and to the combining // marks that follow them (a decomposed name) - so a capture can be written // with its diacritics. func TestFoldMappedSource(t *testing.T) { cases := []struct { in, folded string a, b int want string }{ {"Łódź-faktura.pdf", "Lodz-faktura.pdf", 0, 4, "Łódź"}, {"Łódź-faktura.pdf", "Lodz-faktura.pdf", 5, 12, "faktura"}, {"straße", "strasse", 4, 5, "ß"}, {"a\u0301b", "ab", 0, 1, "a\u0301"}, {"e\u0301-x.pdf", "e-x.pdf", 0, 1, "e\u0301"}, {"\u0141o\u0301dz\u0301-f.pdf", "Lodz-f.pdf", 0, 4, "\u0141o\u0301dz\u0301"}, {"a\u0301b", "ab", 1, 2, "b"}, {"\xff\xfeé", "�e", 0, 3, "\xff\xfe"}, {"plain.txt", "plain.txt", 0, 5, "plain"}, {"Łódź", "Lodz", 2, 2, ""}, } for _, c := range cases { f := FoldMapped(c.in) if f.Text != c.folded || f.Text != Fold(c.in) { t.Errorf("FoldMapped(%q).Text = %q, want %q (Fold)", c.in, f.Text, c.folded) continue } if got := f.Source(c.a, c.b); got != c.want { t.Errorf("FoldMapped(%q).Source(%d, %d) = %q, want %q", c.in, c.a, c.b, got, c.want) } } }