textmachine/platform/internal/books/render_live_test.go

74 lines
3 KiB
Go

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=<path to tmctl> \
// TM_PLATFORM_TEST_BOOK_TEMPLATE=<path to a deployment 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)
}
}