- чистка стоит на каждой точке входа значения метабазы в план — сборка матча, копия кандидата для ревью, набор закреплённых значений источника и его чтение: гарантия, поставленная только на запись, обходится данными, сохранёнными прежними версиями - название, непригодное как имя каталога (пустое или без единой буквы и цифры), не подставляется — раздача уходит в review с названной причиной - гейт подтверждения матча не сдвинут: сравнение с планом идёт по значениям провайдера, чистится только копия, уходящая дальше
103 lines
3.8 KiB
Go
103 lines
3.8 KiB
Go
package recognize
|
||
|
||
import (
|
||
"bytes"
|
||
"log/slog"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
func TestFoldHomoglyphs(t *testing.T) {
|
||
cases := map[string]string{
|
||
// Latin-доминантный токен: кириллический двойник 'а' (U+0430) → 'a'.
|
||
"Hаrold and the Purple Crayon": "Harold and the Purple Crayon",
|
||
// Честная кириллица — не трогаем.
|
||
"Тёмный рыцарь": "Тёмный рыцарь",
|
||
// Честная латиница — не трогаем.
|
||
"The Dark Knight": "The Dark Knight",
|
||
// Cyrillic-доминантный токен (М р з) с латинскими 'o' (U+006F) → 'о'.
|
||
"Мoрoз": "Мороз",
|
||
// Равенство скриптов в токене (кир. О U+041E + лат. k) — не трогаем.
|
||
"Оk": "Оk",
|
||
// Двуязычные, но одно-скриптовые токены — каждый нетронут.
|
||
"Fargo Фарго": "Fargo Фарго",
|
||
// Буква-меньшинство без двойника в таблице (кир. 'б' U+0431) остаётся.
|
||
"Harбld": "Harбld",
|
||
// Пустая строка.
|
||
"": "",
|
||
}
|
||
for in, want := range cases {
|
||
if got := foldHomoglyphs(in); got != want {
|
||
t.Errorf("foldHomoglyphs(%q) = %q, want %q", in, got, want)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestSanitizeTitle(t *testing.T) {
|
||
cases := map[string]string{
|
||
// Zero-width (U+200B) внутри слова удаляется, слово склеивается.
|
||
"a\u200bb": "ab",
|
||
// Zero-width + двойник + лишние пробелы → strip + fold + collapse + trim.
|
||
" Hаrold\u200b Crayon ": "Harold Crayon",
|
||
// Табы/переводы строк как пробелы, сведены к одиночным.
|
||
"Harold\tand the": "Harold and the",
|
||
// Управляющий символ (BEL U+0007) удаляется.
|
||
"Harold\u0007": "Harold",
|
||
// BOM (U+FEFF) удаляется.
|
||
"\ufeffFargo": "Fargo",
|
||
// Уже чистое — без изменений.
|
||
"The Matrix": "The Matrix",
|
||
}
|
||
for in, want := range cases {
|
||
if got := SanitizeTitle(in); got != want {
|
||
t.Errorf("SanitizeTitle(%q) = %q, want %q", in, got, want)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestSanitizePlan_FieldsCleanedSrcUntouched(t *testing.T) {
|
||
// src намеренно содержит кириллический двойник — sanitizePlan его не трогает.
|
||
dirtySrc := "Hаrold.mkv"
|
||
p := Plan{
|
||
Title: "Hаrold",
|
||
OriginalTitle: " spaced ",
|
||
ProviderHint: "clean\u200b",
|
||
Files: []PlanFile{{Src: dirtySrc, Role: RoleMain}},
|
||
}
|
||
sanitizePlan(&p, nil)
|
||
|
||
if p.Title != "Harold" {
|
||
t.Errorf("Title = %q, want %q", p.Title, "Harold")
|
||
}
|
||
if p.OriginalTitle != "spaced" {
|
||
t.Errorf("OriginalTitle = %q, want %q", p.OriginalTitle, "spaced")
|
||
}
|
||
if p.ProviderHint != "clean" {
|
||
t.Errorf("ProviderHint = %q, want %q", p.ProviderHint, "clean")
|
||
}
|
||
if p.Files[0].Src != dirtySrc {
|
||
t.Errorf("files[].src изменён санитайзингом: %q != %q", p.Files[0].Src, dirtySrc)
|
||
}
|
||
}
|
||
|
||
func TestSanitizePlan_LogsOnChange(t *testing.T) {
|
||
var buf bytes.Buffer
|
||
log := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelDebug}))
|
||
p := Plan{Title: "Hаrold"} // 'а' — кириллица, санитайзинг перепишет
|
||
sanitizePlan(&p, log)
|
||
out := buf.String()
|
||
if !strings.Contains(out, "recognition plan field sanitized") || !strings.Contains(out, "field=title") {
|
||
t.Errorf("ожидался Debug-лог о санитайзинге title, got: %q", out)
|
||
}
|
||
}
|
||
|
||
func TestSanitizePlan_NoLogWhenClean(t *testing.T) {
|
||
var buf bytes.Buffer
|
||
log := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelDebug}))
|
||
p := Plan{Title: "Harold", OriginalTitle: "The Matrix"}
|
||
sanitizePlan(&p, log)
|
||
if buf.Len() != 0 {
|
||
t.Errorf("для чистых полей лога быть не должно, got: %q", buf.String())
|
||
}
|
||
}
|