package tts import ( "os" "path/filepath" "testing" ) func TestLexiconRewritesNames(t *testing.T) { lex := NewLexicon(map[string]string{ "Vikunja": "Викунья", "Home Assistant": "Хоум Ассистент", "Home": "Хоум", "GPU": "джи-пи-ю", }) for _, tc := range []struct{ in, want string }{ {"задача в Vikunja готова", "задача в Викунья готова"}, // Case-insensitive: the router and the model both change the case of a // name on the way through. {"открой vikunja.", "открой Викунья."}, // Longest first, or "Home Assistant" is read as "Хоум Assistant". {"Home Assistant не отвечает", "Хоум Ассистент не отвечает"}, // Two names in a row share the space between them, which one pass // would consume. {"GPU GPU", "джи-пи-ю джи-пи-ю"}, // Not a word boundary: a name inside a longer token is left alone. {"vikunjaless", "vikunjaless"}, {"ничего не совпало", "ничего не совпало"}, {"", ""}, } { if got := lex.Apply(tc.in); got != tc.want { t.Errorf("Apply(%q) = %q, want %q", tc.in, got, tc.want) } } } // The zero value and an unconfigured path rewrite nothing, so a daemon with no // dictionary behaves as it did before this existed. func TestLexiconOffByDefault(t *testing.T) { var zero *Lexicon if got := zero.Apply("Vikunja"); got != "Vikunja" { t.Errorf("nil lexicon rewrote %q", got) } lex, err := LoadLexicon("") if err != nil { t.Fatalf("LoadLexicon(\"\"): %v", err) } if lex.Size() != 0 || lex.Apply("Vikunja") != "Vikunja" { t.Errorf("empty path produced a live lexicon of %d names", lex.Size()) } } // A path he set and that cannot be read is a startup failure. Saying names // wrong in silence is what the dictionary exists to stop. func TestLexiconLoadErrors(t *testing.T) { if _, err := LoadLexicon(filepath.Join(t.TempDir(), "nope.json")); err == nil { t.Error("a missing dictionary must be an error") } bad := filepath.Join(t.TempDir(), "bad.json") if err := os.WriteFile(bad, []byte("{not json"), 0o644); err != nil { t.Fatal(err) } if _, err := LoadLexicon(bad); err == nil { t.Error("an unparseable dictionary must be an error") } } func TestLexiconRoundTripsAFile(t *testing.T) { path := filepath.Join(t.TempDir(), "lex.json") if err := os.WriteFile(path, []byte(`{"Praxis":"Праксис"," ":"skipped","Nexus":""}`), 0o644); err != nil { t.Fatal(err) } lex, err := LoadLexicon(path) if err != nil { t.Fatalf("LoadLexicon: %v", err) } // Blank names and blank spellings are dropped: an entry that says nothing // would delete the word it matched. if lex.Size() != 1 { t.Fatalf("Size = %d, want 1", lex.Size()) } if got := lex.Apply("Praxis молчит"); got != "Праксис молчит" { t.Errorf("Apply = %q", got) } }