package pdftext_test // Owner review (P5a): output over MaxText fails fast, not at the deadline. The child writes more // than a pipe buffer (64 KiB), so it blocks on stdout until killed; Run must not wait for it to // exit on its own before checking the size. import ( "bytes" "context" "encoding/json" "errors" "testing" "time" "git.wntrmute.dev/kyle/sift/internal/pdftest" "git.wntrmute.dev/kyle/sift/internal/pdftext" ) func TestRunnerTooMuchTextFailsFast(t *testing.T) { var pages []string for p := 1; p <= 80; p++ { pages = append(pages, pdftest.Lorem(p, 40)) // ~2,700 characters a page, ~200 KiB in all } r := runner() r.MaxText = 1000 r.Deadline = 30 * time.Second start := time.Now() _, err := r.Run(context.Background(), pdftest.Build(pdftest.Doc{Pages: pages})) if !errors.Is(err, pdftext.ErrTooMuchText) { t.Fatalf("err %v, want ErrTooMuchText", err) } if d := time.Since(start); d > 5*time.Second { t.Errorf("ErrTooMuchText after %v; it waited for the deadline instead of killing the child", d) } } // Owner review (P5a): LaTeX (hyperref) and Acrobat outlines use named destinations through // the /Names tree and indirect titles; the first run returned no outline for any arXiv paper // or the NIST PDF. reader's Dict.Get answers reader.Null{} for a missing key, which hid /A. func TestOutlineNamedDestinations(t *testing.T) { b := pdftest.Build(pdftest.Doc{ Title: "Named", Pages: []string{"one", "two", "three"}, Outline: []pdftest.Outline{{Title: "1 Intro", Page: 1, Level: 1}, {Title: "2 Method", Page: 3, Level: 1}}, NamedDests: true, }) var out bytes.Buffer if err := pdftext.Extract(b, 10, &out); err != nil { t.Fatal(err) } var l struct{ Meta pdftext.Meta } line, _ := out.ReadBytes('\n') if err := json.Unmarshal(line, &l); err != nil { t.Fatal(err) } want := []pdftext.OutlineItem{{Title: "1 Intro", Page: 1, Level: 1}, {Title: "2 Method", Page: 3, Level: 1}} if len(l.Meta.Outline) != 2 || l.Meta.Outline[0] != want[0] || l.Meta.Outline[1] != want[1] { t.Errorf("outline = %+v, want %+v", l.Meta.Outline, want) } }