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["元石"]) } }