textmachine/backend/internal/chunk/ingestnotes_test.go

65 lines
2.5 KiB
Go

package chunk
import (
"reflect"
"strings"
"testing"
)
// TestEveryIngestCountReachesTheAlarm holds the counts to what they are FOR. They are the alarm this work
// ships instead of a validator, so a count that never reaches an operator is not a small omission — it is
// the mechanism missing, and it is invisible: the cut still looks fine.
//
// Written by reflection deliberately. The first version of this reporter logged two counts out of five and
// looked complete; a list written by hand would have been copied from that same wrong idea. A new counter
// field now fails this test until it is reported.
func TestEveryIngestCountReachesTheAlarm(t *testing.T) {
rt := reflect.TypeOf(Document{})
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
d := &Document{Chapters: []string{"x"}}
fv := reflect.ValueOf(d).Elem().Field(i)
// The field types that carry an alarm TODAY: ints, and the one slice a count grew into. ⚠ This switch
// is the guard's OWN limit — a counter of any other type falls into `default` and is skipped silently,
// so a new alarm field must be added here as well as to IngestNotes.
switch {
case f.Type.Kind() == reflect.Int:
fv.SetInt(1)
case f.Type == reflect.TypeOf([]ExcludedDocument{}):
fv.Set(reflect.ValueOf([]ExcludedDocument{{Entry: "e", Role: "toc", Runes: 1}}))
default:
continue // Chapters/Ruby/Titles/Structure are the reading itself, not notes about it
}
kv := d.IngestNotes()
if kv == nil {
t.Errorf("%s = 1 produces NO alarm: the count exists and reaches nobody", f.Name)
continue
}
var keys []string
for j := 0; j+1 < len(kv); j += 2 {
keys = append(keys, kv[j].(string))
}
// The field's own key must be among them — not merely "some alarm fired".
want := strings.ToLower(f.Name)
if f.Name == "Excluded" {
want = "documentsexcluded" // reported as a count PLUS the list itself
}
found := false
for _, k := range keys {
if strings.ReplaceAll(k, "_", "") == want {
found = true
}
}
if !found {
t.Errorf("%s = 1 fires an alarm that does not NAME it (keys: %v)", f.Name, keys)
}
}
}
// TestAQuietReadingSaysNothing: the alarm must stay silent on an ordinary book, or it becomes noise nobody
// reads — the failure mode that kills a gate faster than switching it off.
func TestAQuietReadingSaysNothing(t *testing.T) {
if kv := (&Document{Chapters: []string{"a", "b"}, Structure: StructureDetected}).IngestNotes(); kv != nil {
t.Fatalf("a clean reading must produce no notes, got %v", kv)
}
}