76 lines
3.8 KiB
Go
76 lines
3.8 KiB
Go
package store
|
|
|
|
import "testing"
|
|
|
|
// TestBasisStoreRefusesAnEmptyRendering pins the guarantee at the WRITE, which is where it has to live.
|
|
//
|
|
// ⛔ WHY AT THE WRITE AND NOT ONLY AT THE CALLER. The basis exists to hand an answer back. An empty
|
|
// rendering handed back is the silent regression the whole mechanism is built against: the emission drops
|
|
// to the raw first-chunk guess at status `auto`, the run looks cheaper and the bank gets poorer with
|
|
// nothing red. The pipeline also skips such rows before it calls this — belt AND braces — but a guarantee
|
|
// kept only by a caller is one the next caller can forget, and this is the money path.
|
|
func TestBasisStoreRefusesAnEmptyRendering(t *testing.T) {
|
|
s, _ := openTemp(t)
|
|
good := BankBasisRow{SrcKey: "元石", FPVersion: "v1", FPWhole: "abc", FPCanon: "def", Dst: "юаньши", Type: "name"}
|
|
bad := []BankBasisRow{
|
|
{SrcKey: "空", FPVersion: "v1", FPWhole: "abc", Dst: ""}, // no rendering: nothing to serve
|
|
{SrcKey: "", FPVersion: "v1", FPWhole: "abc", Dst: "что-то"}, // no key: it would answer for nobody
|
|
{SrcKey: "无", FPVersion: "v1", FPWhole: "", Dst: "что-то"}, // no fingerprint: nothing to compare
|
|
{SrcKey: "版", FPVersion: "", FPWhole: "abc", Dst: "что-то"}, // no shape: cannot say which rule decided it
|
|
}
|
|
if err := s.PutBankBasis("b", append([]BankBasisRow{good}, bad...)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := s.BankBasisForBook("b")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// The control first: the GOOD row landed, so «nothing was written» cannot masquerade as «the bad rows
|
|
// were refused».
|
|
if _, ok := got["元石"]; !ok {
|
|
t.Fatalf("the well-formed row did not land at all (%d row(s) stored): this test would then pass on a store that writes nothing", len(got))
|
|
}
|
|
for _, r := range bad {
|
|
if _, landed := got[r.SrcKey]; landed && r.SrcKey != "" {
|
|
t.Errorf("a row with src=%q dst=%q fp=%q shape=%q was STORED: a later purchase would serve it back, and an empty or unattributable answer served back is the loss this mechanism exists to prevent",
|
|
r.SrcKey, r.Dst, r.FPWhole, r.FPVersion)
|
|
}
|
|
}
|
|
if len(got) != 1 {
|
|
t.Errorf("stored %d row(s), want exactly the one well-formed row: %+v", len(got), got)
|
|
}
|
|
}
|
|
|
|
// TestBasisStoreReplacesRatherThanAccumulates pins the guarantee this table does NOT inherit from its
|
|
// neighbour. bank_stop_presented only grows and has no delete on purpose; a decision re-taken must
|
|
// OVERWRITE, or the predicate keeps comparing against evidence the book has moved past and serves an answer
|
|
// that was right two purchases ago.
|
|
func TestBasisStoreReplacesRatherThanAccumulates(t *testing.T) {
|
|
s, _ := openTemp(t)
|
|
first := BankBasisRow{SrcKey: "元石", FPVersion: "v1", FPWhole: "old", FPCanon: "oldc", Dst: "юаньши", Type: "name", Gender: "none"}
|
|
if err := s.PutBankBasis("b", []BankBasisRow{first}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
second := BankBasisRow{SrcKey: "元石", FPVersion: "v2", FPWhole: "new", FPCanon: "newc", Dst: "камень юань", Type: "term", Gender: "male"}
|
|
if err := s.PutBankBasis("b", []BankBasisRow{second}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := s.BankBasisForBook("b")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got) != 1 {
|
|
t.Fatalf("the same surface produced %d rows: the table accumulates where it must replace, and the predicate would meet two answers for one term", len(got))
|
|
}
|
|
if got["元石"] != second {
|
|
t.Fatalf("the row was not replaced: got %+v, want %+v", got["元石"], second)
|
|
}
|
|
// A different BOOK must not be touched by either write: the key is (book, surface), and a basis that
|
|
// leaked across books would answer one book's terms with another's canon.
|
|
if err := s.PutBankBasis("other", []BankBasisRow{first}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if again, _ := s.BankBasisForBook("b"); again["元石"] != second {
|
|
t.Fatalf("writing another book's basis changed this one: %+v", again["元石"])
|
|
}
|
|
}
|