Skip to content

test(tar-xz): close remaining coverage gaps to 100% lines#125

Merged
oorabona merged 1 commit into
masterfrom
test/tarxz-final-coverage
Apr 30, 2026
Merged

test(tar-xz): close remaining coverage gaps to 100% lines#125
oorabona merged 1 commit into
masterfrom
test/tarxz-final-coverage

Conversation

@oorabona
Copy link
Copy Markdown
Owner

Summary

Final tar-xz coverage push : real tests for the genuinely-untested code paths + v8 ignore wraps for the defensive branches that PR-γ left. Brings tar-xz from 95.33% to 100% lines.

Tests added (13 cases in test/coverage-final.spec.ts)

Coverage target Test coverage
create.ts:88-104 AsyncIterable source 3 cases : multi-chunk async generator, single-chunk, ArrayBuffer branch
extract.ts:70-73 zero-byte entry 2 cases : bytes() returns empty Uint8Array, second call hits cache
file.ts:223 hardlink lstat ENOENT Forward-reference fixture : lstat ENOENT swallowed, link() ENOENT propagates
file.ts:225-229 symlink-as-source rejection Real symlink → hardlink fixture, asserts "Refusing hardlink"
file.ts:232 symlink-ancestor rejection Symlink dir → hasSymlinkAncestor returns true
file.ts:275 EACCES on open POSIX-only, it.skipIf for Windows / root
tar-parser.ts:254 mid-header truncation XZ-compressed 256-byte buffer + empty buffer variant
tar-parser.ts:338 mid-body during list() SKIP 512/1024 body bytes, no EOA
tar-parser.ts:361 mid-padding size=300 entry, 100/212 padding bytes truncated

v8 ignore wraps applied

File:Line Reason
extract.ts drainSkippedEntry L165-169 TAR_PARSER_INVARIANT rethrow — corrupt parser state unreachable via public API
extract.ts makeDataGen L205-210 Concurrent-iteration guard — makeTarEntryWithData calls dataPull() exactly once per entry
extract.ts extract() L299-303 Stray-chunk invariant — parseTar never emits chunk before entry
extract.ts bytes() L78-92 Overflow guard — parseTar clips chunks at bytesRemaining, so over-delivery cannot happen via extract()
file.ts openFileExclusive L343 Win32 TOCTOU retry rethrow — same race-window pattern as PR #114 hardening

Smart fixture finding

list() and extract() call streamXz() internally — raw TAR bytes passed directly fail with LZMAFormatError. All truncated-archive fixtures wrap bytes with xzSync() first. Locks the contract for future fixture writers.

Coverage delta

Metric Before After
tar-xz lines 95.33% 100%
tar-xz branches 89.45% 92.53%
tar-xz functions 100% 100%
create.ts lines ~95% 100%
extract.ts lines partial 100%
tar-parser.ts lines partial 100%
file.ts lines 96.6% 100%

Branch ceiling is 92.53% because v8 ignore start/stop suppresses body lines but the condition's branch counter still increments. Only /* v8 ignore next */ would suppress the condition, but that form is explicitly forbidden by the project convention.

Diff

3 files changed, +513 / 0 :

  • packages/tar-xz/src/node/extract.ts : +8 (4 wraps)
  • packages/tar-xz/src/node/file.ts : +2 (1 wrap)
  • packages/tar-xz/test/coverage-final.spec.ts : NEW, +503 LOC

Gates

  • pnpm install --frozen-lockfile : EXIT 0
  • pnpm --filter tar-xz build : EXIT 0
  • pnpm type-check : EXIT 0
  • pnpm exec biome check . : EXIT 0, 0 warnings
  • pnpm test : tar-xz 190 → 203 passing (+13), 3 skipped unchanged ; full workspace 489 root + 203 tar-xz + 63 nxz = 755 passing, 0 fail

Test plan

  • CI green
  • Codecov reflects tar-xz at 100% lines
  • Repo-wide coverage now at 100% lines (root + nxz + tar-xz)

Pair real test cases with v8 ignore wraps for the genuinely
defensive branches that PR-γ missed and one Win32 TOCTOU rethrow
that landed after PR-γ scope was closed.

Tests added (13 cases in test/coverage-final.spec.ts):
- create.ts AsyncIterable source — async generator and single-chunk
  variants ; ArrayBuffer source — locks the resolveSource contract.
- extract.ts zero-byte entry — bytes() returns the cached empty
  Uint8Array ; second call hits the cache.
- file.ts hardlink edges — forward-reference (lstat ENOENT
  swallowed, link() ENOENT propagates), symlink-as-source rejection,
  symlink-ancestor rejection, EACCES propagation on POSIX.
- tar-parser.ts truncated archive — three phases covered (mid-header
  256-byte XZ buffer, mid-body during list() SKIP, mid-padding
  with size=300 entry). All assert 'Unexpected end of archive'.

v8 ignore wraps in extract.ts (4 sites):
- drainSkippedEntry TAR_PARSER_INVARIANT rethrow — corrupt parser
  state unreachable via public API.
- makeDataGen concurrent-iteration guard — makeTarEntryWithData
  calls dataPull() exactly once per entry.
- extract() stray-chunk invariant — parseTar never emits chunk
  before entry.
- bytes() overflow guard — parseTar clips chunks at bytesRemaining,
  so over-delivery cannot happen via extract().

v8 ignore wrap in file.ts (1 site):
- openFileExclusive Win32 TOCTOU retry rethrow (line 343) — same
  race-window pattern as the other PR #114 hardening guards.

Coverage:
- tar-xz lines: 95.33% → 100%.
- tar-xz branches: 89.45% → 92.53% (v8-ignored bodies leave the
  condition counter active; only /* v8 ignore next */ would suppress
  it, which the project convention forbids).
- create.ts, extract.ts, tar-parser.ts, file.ts: all at 100% lines.

tar-xz tests: 190 → 203 passing (+13), 3 skipped unchanged.
Full workspace 707 → 720 passing, 0 failing.
@oorabona oorabona merged commit 7189f8e into master Apr 30, 2026
6 of 7 checks passed
@oorabona oorabona deleted the test/tarxz-final-coverage branch April 30, 2026 15:42
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