Skip to content

test: cover what core.ts actually produces - #291

Merged
l2ysho merged 1 commit into
mainfrom
test/core-mutants
Aug 29, 2026
Merged

test: cover what core.ts actually produces#291
l2ysho merged 1 commit into
mainfrom
test/core-mutants

Conversation

@l2ysho

@l2ysho l2ysho commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Third mutant-killing PR from the report at l2ysho.github.io/afpp.

The gap

Every existing core.ts test asserted the page count and stopped:

const data = await pdf2image(input);
assert.equal(data.length, 9);

Nine items came back, so the test passes — whatever is in them. 64 of the 193 mutants survived.

The tests

Text is joined with single spaces. Pinning the start of page one kills the mutants that empty the separator (parts.join(' ')parts.join('')) or seed the parts array with junk.

Rendered pages honour the scale. Page one is 595x841 at scale 1 and 1190x1683 at scale 2. Both numbers sit in the png IHDR header, so no image library is needed. This kills getViewport({ scale })getViewport({}), which silently falls back to scale 1.

A pooled canvas is resized before reuse. test/example-page-sizes.pdf is a hand-written two-page PDF whose pages are 200x100 and 100x300. The first page's canvas goes back to the pool and is handed to the second, so dropping the reset call produces a page rendered at the wrong size. 682 bytes of plain ASCII.

Pages without text are rendered, not emptied. In mixed mode a page with no text items is rasterised and handed to the callback as a Buffer; a text page arrives as a string. example-img.pdf gives nine buffers, example.pdf nine strings. Nothing covered that split.

The callback guard works. A missing callback and a non-function callback both reject.

The scale bounds are accepted, not just their outside rejected. The suite rejected 0, -1, 0.01, 100 and NaN, but never checked that 0.1 and 10 are allowed — so scale < 0.1 could become scale <= 0.1 unnoticed. Folded into the existing scale validation block.

Result

Before After
src/core.ts 64.55 % 74.60 %
All files 67.92 % 70.94 %
Survived in core.ts 64 47

Why I stopped at 47

The rest is not worth a test. Broken down:

  • 13 mutants pick between the pooled canvas factory and pdf.js's own. Both render identical output.
  • 10 mutants are page.cleanup(), canvasFactory.destroy() and finally blocks. Resource handling with no observable result.
  • 10 mutants are canvas pool internals — pool size caps and reuse checks. Performance behaviour, same output either way.
  • 3 mutants replace Array.from({ length: numPages }) with Array.from({}). The array is filled by index afterwards, so it is equivalent.
  • The remainder are equivalent or need a machine with more than 8 cores to observe.

Killing these means exporting internals or asserting on things no caller can see. That trades real test quality for a number.

Every core.ts test asserted the number of pages and nothing else, so 64
of its 193 mutants survived. The tests now check the output itself.

- Text extraction joins page items with single spaces. Pinning the start
  of page one kills the mutants that empty the separator or seed the
  parts array.
- Rendered pages honour the scale, so page one is 595x841 at scale 1 and
  1190x1683 at scale 2. The png header carries both numbers.
- A pooled canvas has to be resized before another page uses it. The new
  example-page-sizes.pdf holds two pages of different sizes, so a canvas
  handed on without a reset produces the wrong dimensions.
- A page without text is rendered and handed to the callback as a buffer,
  a page with text as a string. Nothing covered that split before.
- The callback guard rejects a missing callback and a callback that is
  not a function.
- Scale 0.1 and 10 are accepted. Rejecting what lies outside the range
  never pinned the bounds themselves.

core.ts goes from 64.55 to 74.60 and the project from 67.92 to 70.94.
Survived mutants in the file drop from 64 to 47.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@l2ysho
l2ysho force-pushed the test/core-mutants branch from fad9903 to 3b47351 Compare August 29, 2026 17:53
@l2ysho
l2ysho changed the base branch from test/plimit-concurrency-and-break-threshold to main August 29, 2026 17:53
@l2ysho
l2ysho merged commit 140200c into main Aug 29, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant