textmachine/backend/cmd/tmctl/echoheadline_test.go

124 lines
5.5 KiB
Go

package main
import (
"strings"
"testing"
"textmachine/backend/internal/pipeline"
)
// echoheadline_test.go: the QUALITY headline the operator reads — the two lines that say how much of the
// book has an answer and how much of the model's echo cost us something.
//
// ⛔ THE HOLE THIS CLOSES WAS IN THE GATE, NOT IN THE CODE. The recovered share was added to the editor's
// half of the STRIPS/ECHO line, and the catalogue carried an entry whose prose was about exactly that
// sentence — but its planting edited the pipeline FIELD and its catcher asserted the field, so a reader of
// the catalogue concluded the operator's line was guarded when nothing asked for it: measured by mutating
// `editRecovered` away on a copy of this file, `./cmd/tmctl/` stayed green end to end. The draft half had
// never been pinned either, which is how the copy arrived without the guarantee.
//
// The fixture keeps every number DIFFERENT on purpose (draft 4/50.0%/3 against edit 2/25.0%/1): with equal
// counts a writer that printed one stage's share in the other's slot would pass, and that is the shape the
// money defect took in the first place.
// echoLineOf returns the one STRIPS/ECHO line out of the report, failing if the report does not carry
// exactly one: a pin that silently scanned a report with no such line would assert about nothing.
func echoLineOf(t *testing.T, out string) string {
t.Helper()
var found []string
for _, l := range strings.Split(out, "\n") {
if strings.HasPrefix(l, "STRIPS/ECHO:") {
found = append(found, l)
}
}
if len(found) != 1 {
t.Fatalf("the report must carry exactly one STRIPS/ECHO line, it carries %d:\n%s", len(found), out)
}
return found[0]
}
func qualityHeadlineFixture() *pipeline.QualityReport {
return &pipeline.QualityReport{
TotalUnits: 6, ProcessedUnits: 5, TextUnits: 3,
CosmeticStripUnits: 2, CosmeticStripRate: 0.4,
EchoDraftChunks: 4, EchoDraftRate: 0.5, EchoDraftRecovered: 3,
EchoEditUnits: 2, EchoEditRate: 0.25, EchoEditRecovered: 1,
}
}
// TestTheOperatorsEchoLineCarriesBothRecoveredShares pins the whole line rather than a substring of it:
// the defect was a MISSING clause, and a test that asks only for what it expects to find cannot see one.
func TestTheOperatorsEchoLineCarriesBothRecoveredShares(t *testing.T) {
var b strings.Builder
if err := renderQuality(&b, qualityHeadlineFixture()); err != nil {
t.Fatal(err)
}
out := b.String()
t.Logf("what the operator reads:\n%s", out)
want := "STRIPS/ECHO: cosmetic-strip units=2 (40.0%, markdown+CJK) · echo draft=4 (50.0%, 3 recovered by escalation) · echo edit=2 (25.0%, 1 recovered)"
if !strings.Contains(out, want) {
t.Fatalf("the echo line must read exactly\n\t%s\ngot:\n%s", want, out)
}
// The first line is the denominator of everything below it, and the middle slot is the one a stop mark
// lands in: an operator who reads «reached final» over a position the run was stopped on tops up the
// ceiling for a book he thinks is finished.
if w := "total units=6 · with a final-stage row=5 · with export text=3"; !strings.Contains(out, w) {
t.Fatalf("the totals line must read %q:\n%s", w, out)
}
if strings.Contains(out, "reached final") {
t.Fatalf("«reached final» is false of a stop-marked position — the line must not claim it:\n%s", out)
}
}
// TestTheRecoveredSharesAreAbsentWhenNothingWasRecovered is the control, and without it the pin above
// passes on a writer that prints the clause always — which would tell the operator a book recovered
// echoes it never had.
func TestTheRecoveredSharesAreAbsentWhenNothingWasRecovered(t *testing.T) {
q := qualityHeadlineFixture()
q.EchoDraftRecovered, q.EchoEditRecovered = 0, 0
var b strings.Builder
if err := renderQuality(&b, q); err != nil {
t.Fatal(err)
}
out := b.String()
want := "STRIPS/ECHO: cosmetic-strip units=2 (40.0%, markdown+CJK) · echo draft=4 (50.0%) · echo edit=2 (25.0%)"
if !strings.Contains(out, want) {
t.Fatalf("with nothing recovered the line must read exactly\n\t%s\ngot:\n%s", want, out)
}
// Asked of the ECHO LINE and not of the whole report: `renderQuality` writes two dozen conditional
// sections, and a later line that happens to contain the word would turn this pin red for a reason that
// has nothing to do with its subject.
line := echoLineOf(t, out)
if strings.Contains(line, "recovered") {
t.Fatalf("a book that recovered no echo must not grow a recovered clause:\n%s", line)
}
}
// TestOneStagesRecoveryDoesNotFillTheOtherStagesSlot: the two shares are independent, and the fixture
// where only ONE of them is non-zero is what tells a correct writer from one that computes both clauses
// from a single counter (the defect's own shape: the numerator was copied from the draft side, the guard
// was not).
func TestOneStagesRecoveryDoesNotFillTheOtherStagesSlot(t *testing.T) {
for _, tc := range []struct {
name string
draftRec, editRec int
want string
}{
{name: "only the editor's echo was cured", editRec: 1,
want: "echo draft=4 (50.0%) · echo edit=2 (25.0%, 1 recovered)"},
{name: "only the translator's echo was cured", draftRec: 3,
want: "echo draft=4 (50.0%, 3 recovered by escalation) · echo edit=2 (25.0%)"},
} {
t.Run(tc.name, func(t *testing.T) {
q := qualityHeadlineFixture()
q.EchoDraftRecovered, q.EchoEditRecovered = tc.draftRec, tc.editRec
var b strings.Builder
if err := renderQuality(&b, q); err != nil {
t.Fatal(err)
}
if out := b.String(); !strings.Contains(out, tc.want) {
t.Fatalf("the line must read %q:\n%s", tc.want, out)
}
})
}
}