From 8a046c897e42e9459aa99377589c80c773601efc Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Tue, 15 Sep 2026 00:02:37 +0200 Subject: tests read real documents from LibreOffice and pandoc; antiword's short-document limit documented --- CHANGELOG.md | 3 ++ docs/design.md | 11 ++++-- internal/extract/real_test.go | 57 +++++++++++++++++++++++++++++ internal/extract/testdata/real/book.epub | Bin 0 -> 4886 bytes internal/extract/testdata/real/doc.doc | Bin 0 -> 22528 bytes internal/extract/testdata/real/doc.docx | Bin 0 -> 6041 bytes internal/extract/testdata/real/doc.odt | Bin 0 -> 8506 bytes internal/extract/testdata/real/doc.pdf | Bin 0 -> 37442 bytes internal/extract/testdata/real/sheet.ods | Bin 0 -> 8686 bytes internal/extract/testdata/real/sheet.xls | Bin 0 -> 5632 bytes internal/extract/testdata/real/sheet.xlsx | Bin 0 -> 5538 bytes internal/extract/testdata/real/slides.pptx | Bin 0 -> 27659 bytes man/krino.conf.5 | 7 ++++ 13 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 internal/extract/real_test.go create mode 100644 internal/extract/testdata/real/book.epub create mode 100644 internal/extract/testdata/real/doc.doc create mode 100644 internal/extract/testdata/real/doc.docx create mode 100644 internal/extract/testdata/real/doc.odt create mode 100644 internal/extract/testdata/real/doc.pdf create mode 100644 internal/extract/testdata/real/sheet.ods create mode 100644 internal/extract/testdata/real/sheet.xls create mode 100644 internal/extract/testdata/real/sheet.xlsx create mode 100644 internal/extract/testdata/real/slides.pptx diff --git a/CHANGELOG.md b/CHANGELOG.md index bb6050b..572ecef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ unknown. - `krino log` marks a run "(partly undone)" while some of its reversible steps are not reversed, and "(undone)" only once every one is. +- Tests read real documents made by LibreOffice and pandoc (docx, odt, ods, + xlsx, pptx, epub, pdf, doc, xls), the tool formats when a tool is + installed; antiword's refusal of a very short `.doc` is documented. - Tests: a genuine apply error exits 1, and `w` in review stops krino even when applying fails, both through the real command; the undo projection's "about to be occupied" half. diff --git a/docs/design.md b/docs/design.md index 59c64bd..ca8d550 100644 --- a/docs/design.md +++ b/docs/design.md @@ -861,10 +861,15 @@ placeholder numbers, screenshots by date, cleaning up old installers). path against `git check-ignore --no-index` (skipped if git is absent). - **Conditions:** truth tables; a property test that random condition trees give the same result with and without cost reordering. -- **Extraction:** the tests generate their fixtures in temporary +- **Extraction:** most tests generate their fixtures in temporary directories and use fake tools for PDF and the legacy formats (doc, xls, - ppt); the real `pdftotext` test skips when the tool is missing. Real - office-suite files and real legacy-tool runs are not tested in 0.0.1. + ppt). `testdata/real` holds documents LibreOffice and pandoc made from + invented text (docx, odt, ods, xlsx, pptx, epub, pdf, doc, xls); each is + read, the tool formats only when a tool for them is installed. There is no + real `.ppt` or `.odp` fixture (LibreOffice could not convert pandoc's + pptx), and xls/ppt have only run through fake tools where `catdoc` is not + installed. antiword refuses a `.doc` with very little text; catdoc reads + it. - **Plan, apply, undo:** in temporary directories: build a tree, plan, apply, check; undo; check the tree is identical to the start (paths, contents, modes, mtimes). A cross-filesystem move test runs when a tmpfs is diff --git a/internal/extract/real_test.go b/internal/extract/real_test.go new file mode 100644 index 0000000..fd52f81 --- /dev/null +++ b/internal/extract/real_test.go @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package extract + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// TestRealDocuments reads documents made by the programs people use - +// LibreOffice 25.2 (docx, odt, doc, pdf, ods, xlsx, xls) and pandoc (pptx, +// epub) - from invented text, not ones built by hand in a test (triage +// 34s). The zip formats always run; a format that needs an external tool +// runs when that tool is installed and is skipped otherwise. +func TestRealDocuments(t *testing.T) { + e := newWithPath(os.Getenv("PATH")) + found := map[string]bool{} + for _, tool := range e.Tools() { + found[tool.Name] = tool.Path != "" + } + for _, c := range []struct { + file string + tools []string // any one of them will do; none means Go reads it + want string + }{ + {"doc.docx", nil, "acme ltd"}, + {"doc.odt", nil, "acme ltd"}, + {"sheet.ods", nil, "acme ltd"}, + {"sheet.xlsx", nil, "acme ltd"}, + {"slides.pptx", nil, "acme ltd"}, + {"book.epub", nil, "acme ltd"}, + {"doc.pdf", []string{"pdftotext"}, "acme ltd"}, + {"doc.doc", []string{"antiword", "catdoc"}, "acme ltd"}, + {"sheet.xls", []string{"xls2csv"}, "acme ltd"}, + } { + t.Run(c.file, func(t *testing.T) { + if len(c.tools) > 0 { + ok := false + for _, tool := range c.tools { + ok = ok || found[tool] + } + if !ok { + t.Skipf("none of %v installed", c.tools) + } + } + got, err := text(t, e, filepath.Join("testdata", "real", c.file), 0) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(got, c.want) { + t.Errorf("text of %s lacks %q:\n%q", c.file, c.want, got) + } + }) + } +} diff --git a/internal/extract/testdata/real/book.epub b/internal/extract/testdata/real/book.epub new file mode 100644 index 0000000..741b3a7 Binary files /dev/null and b/internal/extract/testdata/real/book.epub differ diff --git a/internal/extract/testdata/real/doc.doc b/internal/extract/testdata/real/doc.doc new file mode 100644 index 0000000..8520659 Binary files /dev/null and b/internal/extract/testdata/real/doc.doc differ diff --git a/internal/extract/testdata/real/doc.docx b/internal/extract/testdata/real/doc.docx new file mode 100644 index 0000000..7bc9d04 Binary files /dev/null and b/internal/extract/testdata/real/doc.docx differ diff --git a/internal/extract/testdata/real/doc.odt b/internal/extract/testdata/real/doc.odt new file mode 100644 index 0000000..d3d287e Binary files /dev/null and b/internal/extract/testdata/real/doc.odt differ diff --git a/internal/extract/testdata/real/doc.pdf b/internal/extract/testdata/real/doc.pdf new file mode 100644 index 0000000..b46e40e Binary files /dev/null and b/internal/extract/testdata/real/doc.pdf differ diff --git a/internal/extract/testdata/real/sheet.ods b/internal/extract/testdata/real/sheet.ods new file mode 100644 index 0000000..0bb783a Binary files /dev/null and b/internal/extract/testdata/real/sheet.ods differ diff --git a/internal/extract/testdata/real/sheet.xls b/internal/extract/testdata/real/sheet.xls new file mode 100644 index 0000000..ee64a9d Binary files /dev/null and b/internal/extract/testdata/real/sheet.xls differ diff --git a/internal/extract/testdata/real/sheet.xlsx b/internal/extract/testdata/real/sheet.xlsx new file mode 100644 index 0000000..9788970 Binary files /dev/null and b/internal/extract/testdata/real/sheet.xlsx differ diff --git a/internal/extract/testdata/real/slides.pptx b/internal/extract/testdata/real/slides.pptx new file mode 100644 index 0000000..5ee037c Binary files /dev/null and b/internal/extract/testdata/real/slides.pptx differ diff --git a/man/krino.conf.5 b/man/krino.conf.5 index c2df331..c9e823f 100644 --- a/man/krino.conf.5 +++ b/man/krino.conf.5 @@ -826,6 +826,13 @@ Duplicate conditions with different scopes do not share an original, so two such rules can between them move every copy of a group aside; nothing is deleted. .Sh KNOWN LIMITATIONS +.Xr antiword 1 +refuses a legacy Word document with very little text +.Pq Dq the text stream of this file is too small to handle ; +with only antiword installed such a file is content unreadable, while +.Xr catdoc 1 +reads it. +.Pp A .Ar dest whose -- cgit v1.3