59 lines
2.6 KiB
Go
59 lines
2.6 KiB
Go
package terminology
|
||
|
||
import (
|
||
"reflect"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
func TestParseTypesKeepsOnlyAskedAndVocabulary(t *testing.T) {
|
||
id := func(s string) string { return s }
|
||
reply := strings.Join([]string{
|
||
"元石\tterm",
|
||
"方源 name", // spaces instead of a tab — tolerant split
|
||
"青茅山 | place", // padded pipe
|
||
"家老\tPERSON", // off-vocabulary → refused and counted
|
||
"陌生\tterm", // never asked → refused and counted
|
||
"元石\tname", // duplicate key → first answer wins
|
||
"мусор", // one field → refused and counted
|
||
}, "\n")
|
||
got, st := ParseTypes(reply, []string{"元石", "方源", "青茅山", "家老"}, id)
|
||
want := map[string]string{"元石": "term", "方源": "name", "青茅山": "place"}
|
||
if !reflect.DeepEqual(got, want) {
|
||
t.Fatalf("parse = %#v, want %#v", got, want)
|
||
}
|
||
// off-vocabulary PERSON + unasked 陌生 + malformed мусор = 3 bad lines (the duplicate is silently ignored,
|
||
// not counted, exactly like ParseReply).
|
||
if st.Bad != 3 {
|
||
t.Fatalf("unusable/off-vocabulary lines must be COUNTED, got %d", st.Bad)
|
||
}
|
||
}
|
||
|
||
func TestParseTypesNormalizesKey(t *testing.T) {
|
||
got, _ := ParseTypes("FANG\tname", []string{"fang"}, strings.ToLower)
|
||
if got["fang"] != "name" {
|
||
t.Fatalf("the reply key must be normalized by the caller's function, got %#v", got)
|
||
}
|
||
}
|
||
|
||
// TestTypeLabelMismatchesIsHonest pins the screen's DELIBERATE limit: it flags a name/place whose rendering
|
||
// was clearly translated (multi-word), but it is NOT a safety net — a mistyped name rendered as one token,
|
||
// lower-case (元石→юаньши) or capitalised (元海→Юаньхай), passes it clean. The classifier phase is what
|
||
// prevents that harm; asserting the miss keeps a future reader from mistaking this for the guard.
|
||
func TestTypeLabelMismatchesIsHonest(t *testing.T) {
|
||
rows := []LabelRow{
|
||
{Src: "花家", Type: "name", Dst: "Дом Хуа"}, // translated name → FLAG
|
||
{Src: "青茅山", Type: "place", Dst: "гора Цинмао"}, // translated place → FLAG
|
||
{Src: "元石", Type: "name", Dst: "юаньши"}, // the harm, single lower-case token → MISSED
|
||
{Src: "元海", Type: "name", Dst: "Юаньхай"}, // the harm, capitalised token → MISSED
|
||
{Src: "灵泉", Type: "term", Dst: "духовный источник"}, // term is not screened → not flagged
|
||
}
|
||
got := TypeLabelMismatches(rows)
|
||
var srcs []string
|
||
for _, r := range got {
|
||
srcs = append(srcs, r.Src)
|
||
}
|
||
if !reflect.DeepEqual(srcs, []string{"花家", "青茅山"}) {
|
||
t.Fatalf("only the translated name/place rows must flag, got %v", srcs)
|
||
}
|
||
}
|