45 lines
2.4 KiB
Go
45 lines
2.4 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"textmachine/backend/internal/membank"
|
|
"textmachine/backend/internal/store"
|
|
)
|
|
|
|
// TestMinedDeltaSeedCollisions covers both paths of the D39.20 deviation-#1 crash guard: a mined-delta
|
|
// term whose UNIQUE key (src, sense, since_ch, until_ch) already exists in the seed must be reported
|
|
// (would crash ReplaceGlossary), while a disjoint delta reports nothing. It also asserts a SAME-dst
|
|
// duplicate is caught (membank.ApprovedSharedKeyCollisions skips it, so this guard is the one that must fire).
|
|
func TestMinedDeltaSeedCollisions(t *testing.T) {
|
|
seed := []store.GlossaryEntry{
|
|
{Src: "元", Dst: "первооснова", Sense: "корень", Status: "approved"},
|
|
{Src: "赤城", Dst: "Чичэн", Status: "approved"},
|
|
}
|
|
|
|
// Path A — a mined-delta term duplicating the seed's UNIQUE key (different dst) → loud.
|
|
minedDiff := []store.GlossaryEntry{{Src: "元", Dst: "юань", Sense: "корень", Status: "approved", Source: "mined"}}
|
|
if dups := membank.MinedDeltaSeedCollisions(seed, minedDiff); len(dups) != 1 {
|
|
t.Fatalf("different-dst duplicate: want 1 collision, got %d (%v)", len(dups), dups)
|
|
} else if !strings.Contains(dups[0], "元") {
|
|
t.Fatalf("collision message should name the duplicated src: %q", dups[0])
|
|
}
|
|
|
|
// Path A' — a SAME-dst duplicate (membank.ApprovedSharedKeyCollisions skips these; this guard must still fire,
|
|
// since the UNIQUE INSERT crashes regardless of dst).
|
|
minedSame := []store.GlossaryEntry{{Src: "元", Dst: "первооснова", Sense: "корень", Status: "approved", Source: "mined"}}
|
|
if dups := membank.MinedDeltaSeedCollisions(seed, minedSame); len(dups) != 1 {
|
|
t.Fatalf("same-dst duplicate: want 1 collision (the INSERT crashes regardless of dst), got %d", len(dups))
|
|
}
|
|
|
|
// Path B — a disjoint delta (a genuinely new term, or the same src in a DIFFERENT spoiler window) →
|
|
// nothing to report; the append is safe.
|
|
minedOK := []store.GlossaryEntry{
|
|
{Src: "春秋蝉", Dst: "Весенне-осенняя цикада", Status: "approved", Source: "mined"},
|
|
{Src: "元", Dst: "юань (валюта)", Sense: "деньги", Status: "approved", Source: "mined"}, // different sense → different UNIQUE key
|
|
}
|
|
if dups := membank.MinedDeltaSeedCollisions(seed, minedOK); len(dups) != 0 {
|
|
t.Fatalf("disjoint delta: want 0 collisions, got %d (%v)", len(dups), dups)
|
|
}
|
|
}
|