Skip to content

feat: add file_passthrough() for strict-mode-compatible real FS access#280

Open
Koan-Bot wants to merge 3 commits intocpanel:masterfrom
atoomic:koan.atoomic/file-passthrough
Open

feat: add file_passthrough() for strict-mode-compatible real FS access#280
Koan-Bot wants to merge 3 commits intocpanel:masterfrom
atoomic:koan.atoomic/file-passthrough

Conversation

@Koan-Bot
Copy link
Contributor

@Koan-Bot Koan-Bot commented Mar 3, 2026

Summary

  • Adds Test::MockFile->file_passthrough($path) which registers a path with strict mode but delegates all I/O to the real filesystem
  • Solves the DBD::SQLite / DBI compatibility issue where XS-based modules perform C-level I/O that bypasses Perl's overrides

Why

When using Test::MockFile in strict mode, XS modules like DBD::SQLite that use C-level file operations (not Perl's open) fail because strict mode blocks access to unmocked paths. file_passthrough adds a strict rule allowing all operations on the given path while intentionally NOT registering it in %files_being_mocked, so all overrides fall through to CORE::*.

How

  • file_passthrough($path) creates a strict-mode rule (allow-all for exact path) and returns a blessed object
  • The object is NOT in %files_being_mocked, so _mock_stat, __open, etc. all fall through to real filesystem
  • On DESTROY, the strict rule is removed but the real file is NOT deleted

Testing

  • 5 subtests in t/file_passthrough.t: object creation, real FS delegation (write/read/stat/unlink), coexistence with regular mocks, scope cleanup, input validation

Closes #91

🤖 Generated with Claude Code

@toddr
Copy link
Member

toddr commented Mar 19, 2026

@Koan-Bot rebase

@toddr toddr marked this pull request as ready for review March 19, 2026 05:35
Koan-Bot and others added 3 commits March 19, 2026 09:43
Cover untested paths in FileHandle.pm WRITE and READ tied methods:

syswrite:
- zero-length write (len=0) returns 0, writes nothing
- O_APPEND mode always appends even after seek
- seek past EOF then write creates null-byte gap
- float len truncated to int (2.9 → 2)
- non-numeric len warns + EINVAL
- negative len warns + EINVAL
- empty buffer with len=0

sysread:
- non-numeric len warns + returns undef + EINVAL
- negative len warns + returns undef + EINVAL
- float len truncated to int (3.7 → 3)
- zero-length read returns 0
- undef buffer initialized to empty string
- undef buffer with offset pads null bytes
- write-only handle returns undef + EBADF
- read at EOF returns 0
- write then read in O_RDWR mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract _default_mock_attrs() and _new_nonexistent_file_mock() to
centralize mock object construction defaults that were duplicated
across new(), _create_file_through_broken_symlink(), and
_maybe_autovivify(). Changes to defaults now only need to happen
in one place.

Add _maybe_throw_autodie() helper that combines the check-and-throw
pattern (_throw_autodie + _caller_has_autodie_for) into a single
call, reducing 50 two-line boilerplate patterns to one-liners.

Remove dead $set_error variable in __chown — it was declared but
never set to true, so the conditional guards were always no-ops.

Fix CAEATS typo in POD (now CAVEATS).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…em access

Adds Test::MockFile->file_passthrough($path) which registers a path
with strict mode but delegates all I/O to the real filesystem. This
allows XS-based modules like DBD::SQLite that perform C-level I/O to
create and use files while Perl-level checks (-f, stat, open) remain
consistent under strict mode.

The passthrough object adds a strict rule (allow-all for the path) and
intentionally does NOT register in %files_being_mocked, so all
overrides fall through to CORE::*. On scope exit (DESTROY), the strict
rule is removed but the real file is not deleted.

Closes cpanel#91

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Koan-Bot Koan-Bot force-pushed the koan.atoomic/file-passthrough branch from 5e8323a to a69e0ba Compare March 19, 2026 15:44
@Koan-Bot
Copy link
Contributor Author

Rebase: feat: add file_passthrough() for strict-mode-compatible real FS access

Branch koan.atoomic/file-passthrough rebased onto master and force-pushed.

Diff: 2 files changed, 210 insertions(+)

Review feedback was analyzed and applied.

Actions

  • Rebased koan.atoomic/file-passthrough onto upstream/master
  • Force-pushed koan.atoomic/file-passthrough to origin
  • CI passed

CI

CI passed.


Automated by Kōan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Test::MockFile & DBD::SQLite

2 participants