package pipeline import ( "context" "testing" ) // export_pairs_test.go: WS5 `tmctl export --pairs` — the src↔target column the polygon needs for the // DC1/DC2 false-positive measure (§5(д)). Default export is target-only (Source omitted); --pairs adds // the $0 manifest source per chunk, matching what the runner chunked. func TestExportPairsIncludesSource(t *testing.T) { rec := &reqRec{} srv := newJSONProvider(rec, draftEdit) defer srv.Close() bookPath := setupProjectOpts(t, srv.URL, projectOpts{source: "静かな図書館の朝。"}) ctx := context.Background() r := newRunner(t, bookPath) defer r.Close() if _, err := r.TranslateBook(ctx); err != nil { t.Fatal(err) } // Recover the manifest source the runner chunked, to compare against the --pairs column. manifest, err := r.bookChunks() if err != nil { t.Fatal(err) } bySource := map[[2]int]string{} for _, ch := range manifest { bySource[[2]int{ch.Chapter, ch.ChunkIdx}] = ch.Text } // Default export: Source omitted (target-only contract). plain, err := r.Export(false) if err != nil { t.Fatal(err) } for _, ce := range plain.Chunks { if ce.Source != "" { t.Fatalf("default export must omit Source, got %q for ch%d/%d", ce.Source, ce.Chapter, ce.ChunkIdx) } } // --pairs export: Source populated with the exact manifest source per chunk. pairs, err := r.Export(true) if err != nil { t.Fatal(err) } if len(pairs.Chunks) == 0 { t.Fatal("export produced no chunks") } for _, ce := range pairs.Chunks { want := bySource[[2]int{ce.Chapter, ce.ChunkIdx}] if ce.Source != want { t.Fatalf("--pairs ch%d/%d Source = %q, want the manifest source %q", ce.Chapter, ce.ChunkIdx, ce.Source, want) } if ce.Source == "" { t.Fatalf("--pairs must populate a non-empty Source for a real chunk (ch%d/%d)", ce.Chapter, ce.ChunkIdx) } } }