101 lines
4.3 KiB
Go
101 lines
4.3 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
// flagseverity_test.go pins the chapter passport's "worst flag" ranking.
|
|
//
|
|
// ⚠ WHY THIS FILE EXISTS AT ALL. flagReasonSeverity had no test of any kind, and the shape of the bug it
|
|
// carried is the one this project keeps meeting: a hand-written list that stopped tracking the constants it
|
|
// lists. `off_target_lang` — the flag an entire pack was built to raise — was never added to the switch, so
|
|
// it fell to the default and became the MOST BENIGN reason in the passport, below `length`. A chapter that
|
|
// came back in the wrong language reported «length» as its worst problem. Nothing was wrong with the code;
|
|
// the list was simply not tied to anything.
|
|
|
|
// TestEveryFlagReasonIsRanked reads the FlagReason constants OUT OF THE SOURCE rather than retyping them
|
|
// here, because a hand-written list in the test would rot exactly like the hand-written list in the code —
|
|
// and would then certify the rot. This is the guarantee that the next flag someone adds cannot land in the
|
|
// unknown bucket silently: it fails here on the day it is declared, not on the day it is misreported.
|
|
func TestEveryFlagReasonIsRanked(t *testing.T) {
|
|
fset := token.NewFileSet()
|
|
f, err := parser.ParseFile(fset, "disposition.go", nil, 0)
|
|
if err != nil {
|
|
t.Fatalf("parse disposition.go: %v", err)
|
|
}
|
|
var found int
|
|
for _, d := range f.Decls {
|
|
gd, ok := d.(*ast.GenDecl)
|
|
if !ok || gd.Tok != token.CONST {
|
|
continue
|
|
}
|
|
var lastType string
|
|
for _, sp := range gd.Specs {
|
|
vs, ok := sp.(*ast.ValueSpec)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if id, ok := vs.Type.(*ast.Ident); ok {
|
|
lastType = id.Name
|
|
}
|
|
if lastType != "FlagReason" || len(vs.Values) == 0 {
|
|
continue
|
|
}
|
|
lit, ok := vs.Values[0].(*ast.BasicLit)
|
|
if !ok || lit.Kind != token.STRING {
|
|
continue
|
|
}
|
|
val, err := strconv.Unquote(lit.Value)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", vs.Names[0].Name, err)
|
|
}
|
|
if val == "" {
|
|
continue // reasonOK — the sentinel for "not a flag", deliberately unranked
|
|
}
|
|
found++
|
|
if _, ranked := flagSeverity[FlagReason(val)]; !ranked {
|
|
t.Errorf("%s (%q) has no entry in flagSeverity: it would rank %d — BELOW every real diagnosis, "+
|
|
"so it can never be reported as a chapter's worst flag", vs.Names[0].Name, val, severityUnknown)
|
|
}
|
|
}
|
|
}
|
|
// The reader of this test must know it actually read something: a parse that silently matched nothing
|
|
// would pass forever and guard nothing — the same failure class one layer up.
|
|
if found < 15 {
|
|
t.Fatalf("only %d FlagReason constants were read out of disposition.go — the walk stopped matching "+
|
|
"the source, and this test is no longer checking anything", found)
|
|
}
|
|
if len(flagSeverity) != found {
|
|
t.Errorf("flagSeverity has %d entries for %d declared reasons — a rank exists for a reason that no "+
|
|
"longer does", len(flagSeverity), found)
|
|
}
|
|
}
|
|
|
|
// TestOffTargetLangIsRankedWithTheContentFailures is the specific harm, asserted as a number and not as a
|
|
// membership: the flag must out-rank the budget symptoms, because those are what it was losing to.
|
|
func TestOffTargetLangIsRankedWithTheContentFailures(t *testing.T) {
|
|
off := flagReasonSeverity(string(FlagOffTargetLang))
|
|
if off == severityUnknown {
|
|
t.Fatal("off_target_lang fell to the unknown bucket — the exact defect this file was written for")
|
|
}
|
|
for _, milder := range []FlagReason{FlagLength, FlagEmpty, FlagGlossaryMiss, FlagSanitizerStripped} {
|
|
if off >= flagReasonSeverity(string(milder)) {
|
|
t.Errorf("off_target_lang (%d) must be WORSE than %s (%d): a chapter in the wrong language is not "+
|
|
"a budget symptom", off, milder, flagReasonSeverity(string(milder)))
|
|
}
|
|
}
|
|
// It is a content failure, ranked with the echo it sits beside in the classifier.
|
|
if off != flagReasonSeverity(string(FlagCJKArtifact)) {
|
|
t.Errorf("off_target_lang (%d) and cjk_artifact (%d) are the same class — «the output is not a "+
|
|
"translation of this text into the asked-for language» — and must rank together",
|
|
off, flagReasonSeverity(string(FlagCJKArtifact)))
|
|
}
|
|
// A refusal still outranks both: the provider said no, which is a different and worse fact.
|
|
if off <= flagReasonSeverity(string(FlagHardRefusal)) {
|
|
t.Error("a hard refusal must still outrank an off-target completion")
|
|
}
|
|
}
|