package build_test
import (
"os"
"path/filepath"
"slices"
"testing"
"chirami/internal/dict"
"chirami/internal/dict/build"
)
func TestBuildFromFixtures(t *testing.T) {
jmdictFile, err := os.Open("../testdata/jmdict.json")
if err != nil {
t.Fatalf("open jmdict: %v", err)
}
defer jmdictFile.Close()
kanjidicFile, err := os.Open("../testdata/kanjidic.json")
if err != nil {
t.Fatalf("open kanjidic: %v", err)
}
defer kanjidicFile.Close()
accentsFile, err := os.Open("../testdata/accents.txt")
if err != nil {
t.Fatalf("open accents: %v", err)
}
defer accentsFile.Close()
xmlFile, err := os.Open("../testdata/jmdict.xml")
if err != nil {
t.Fatalf("open jmdict.xml: %v", err)
}
defer xmlFile.Close()
furiFile, err := os.Open("../testdata/furigana.json")
if err != nil {
t.Fatalf("open furigana.json: %v", err)
}
defer furiFile.Close()
kradFile, err := os.Open("../testdata/kradfile.json")
if err != nil {
t.Fatalf("open kradfile.json: %v", err)
}
defer kradFile.Close()
radkFile, err := os.Open("../testdata/radkfile.json")
if err != nil {
t.Fatalf("open radkfile.json: %v", err)
}
defer radkFile.Close()
outPath := filepath.Join(t.TempDir(), "dict.bin")
err = build.Build(
jmdictFile, kanjidicFile, accentsFile, outPath,
build.WithPriorities(xmlFile),
build.WithFurigana(furiFile),
build.WithKradfile(kradFile),
build.WithRadkfile(radkFile),
)
if err != nil {
t.Fatalf("build: %v", err)
}
d, err := dict.Open(outPath)
if err != nil {
t.Fatalf("open: %v", err)
}
defer d.Close()
entries := d.Lookup("食べる")
if len(entries) == 0 {
t.Fatalf("lookup 食べる returned 0 entries")
}
rubies, ok := d.Furigana("食べる", "たべる")
if !ok {
t.Fatalf("expected furigana for 食べる")
}
want := []dict.Ruby{
{Text: "食", Ruby: "た"},
{Text: "べる", Ruby: ""},
}
if !slices.Equal(rubies, want) {
t.Errorf("got %+v, want %+v", rubies, want)
}
// Check Components
comps := d.Components('食')
if !slices.Equal(comps, []rune{'食'}) {
t.Errorf("Components('食') = %v, want ['食']", comps)
}
// Check KanjiWith
kw := d.KanjiWith('艮', 5)
if len(kw) != 3 || kw[0] != '銀' || kw[1] != '限' || kw[2] != '良' {
t.Errorf("KanjiWith('艮', 5) = %v, want ['銀', '限', '良']", kw)
}
// Check ComponentName
if name := d.ComponentName('⺅'); name != "person" {
t.Errorf("ComponentName('⺅') = %q, want 'person'", name)
}
if name := d.ComponentName('食'); name != "eat" {
t.Errorf("ComponentName('食') = %q, want 'eat'", name)
}
// Check WordsWith
words := d.WordsWith('食', 5)
if len(words) < 2 {
t.Fatalf("WordsWith('食', 5) returned %d entries, want at least 2", len(words))
}
if words[0].Kanji[0].Text != "食べる" {
t.Errorf("words[0] = %q, want '食べる'", words[0].Kanji[0].Text)
}
// Check table of 10 kanji (休 花 働 語 読 海 道 家 想 校)
table := []struct {
kanji rune
comps []rune
names []string
}{
{'休', []rune{'⺅', '木'}, []string{"person", "tree"}},
{'花', []rune{'⺅', '匕', '艹'}, []string{"person", "spoon", "grass"}},
{'働', []rune{'丨', '一', '⺅', '力', '日', '丿'}, []string{"line", "one", "person", "power", "sun", "slash"}},
{'語', []rune{'言', '口', '五'}, []string{"words", "mouth", "five"}},
{'読', []rune{'言', '士', '儿', '冖'}, []string{"words", "scholar", "legs", "cover"}},
{'海', []rune{'氵', '母', '毋', '乞'}, []string{"water", "mother", "do not", "beg"}},
{'道', []rune{'辶', '自', '丷', '首'}, []string{"walk", "oneself", "horns", "head"}},
{'家', []rune{'宀', '豕'}, []string{"roof", "pig"}},
{'想', []rune{'心', '木', '目'}, []string{"heart", "tree", "eye"}},
{'校', []rune{'父', '木', '亠'}, []string{"father", "tree", "lid"}},
}
for _, tc := range table {
gotComps := d.Components(tc.kanji)
if !slices.Equal(gotComps, tc.comps) {
t.Errorf("Components(%c) = %v (%c), want %v (%c)", tc.kanji, gotComps, gotComps, tc.comps, tc.comps)
}
gotNames := make([]string, len(gotComps))
for i, c := range gotComps {
gotNames[i] = d.ComponentName(c)
}
if !slices.Equal(gotNames, tc.names) {
t.Errorf("ComponentNames for %c = %v, want %v", tc.kanji, gotNames, tc.names)
}
}
}