package books import ( "os" "os/exec" "path/filepath" "strings" "testing" "textmachine/platform/internal/ingest" "textmachine/platform/internal/runner" ) // The one claim about this render that no unit test can make: that what it produces is a // configuration THE ENGINE LOADS. // // Everything else here is checked against this zone's own idea of the engine's schema, and that idea // is exactly what goes stale — a required key added upstream, a stricter decoder, a field whose type // changed. So the assertion is made by running the real binary: `tmctl manifest` is $0, needs no // provider key, and fails loudly on a configuration it cannot load, which is precisely the question. // // It is GATED and named out loud, in the shape this zone already uses for its database tests: a // battery on a bare clone has no engine binary and must stay green. Run it with // // TM_PLATFORM_TEST_ENGINE_BIN= \ // TM_PLATFORM_TEST_BOOK_TEMPLATE= go test ./internal/books/ func TestTheRenderedConfigurationIsOneTheEngineActuallyLoads(t *testing.T) { bin := os.Getenv("TM_PLATFORM_TEST_ENGINE_BIN") tpl := os.Getenv("TM_PLATFORM_TEST_BOOK_TEMPLATE") if bin == "" || tpl == "" { t.Skip("TM_PLATFORM_TEST_ENGINE_BIN and TM_PLATFORM_TEST_BOOK_TEMPLATE not set: " + "the rendered configuration is not checked against a real engine") } dir := t.TempDir() // The source the intake would have written, under the name the intake gives it. Three chapters so // the manifest has something to count. var body strings.Builder for i := 1; i <= 3; i++ { body.WriteString("第" + string(rune('0'+i)) + "章 测试\n") body.WriteString(strings.Repeat("这是一个测试文本。", 40)) body.WriteString("\n\n") } if err := os.WriteFile(filepath.Join(dir, SourceName+".txt"), []byte(body.String()), 0o600); err != nil { t.Fatal(err) } svc := &Service{Cfg: Config{BooksDir: filepath.Dir(dir), BookTemplate: tpl}} if err := svc.provision(t.Context(), dir, bookConfig{ ID: "bk_LIVEPROBE", Title: "蛊真人", SourceLang: "zh", TargetLang: "ru", }); err != nil { t.Fatalf("provision: %v", err) } cmd := exec.CommandContext(t.Context(), bin, runner.ManifestArgs(dir)...) cmd.Dir = dir var errOut strings.Builder cmd.Stderr = &errOut out, err := cmd.Output() if err != nil { rendered, _ := os.ReadFile(filepath.Join(dir, runner.ConfigFile)) t.Fatalf("the engine refused the rendered configuration: %v\n--- stderr ---\n%s\n--- book.yaml ---\n%s", err, errOut.String(), rendered) } m, err := ingest.DecodeManifest(out) if err != nil { t.Fatalf("the manifest did not decode: %v", err) } if m.ChaptersTotal != 3 { t.Errorf("the engine cut %d chapters out of three", m.ChaptersTotal) } // The identity the platform wrote is the identity the engine read back: one book id on both sides // of the seam, which is what lets the handshake's book_id be compared with the row at all. if m.ChunkerVersion == "" || m.SourceSHA256 == "" { t.Errorf("the manifest carries no provenance: %+v", m) } }