feat: add autodie compatibility (#44)#208
Draft
Koan-Bot wants to merge 4 commits intocpanel:masterfrom
Draft
Conversation
118d48e to
81f5ef6
Compare
autodie installs per-package wrappers that call CORE::open directly, bypassing CORE::GLOBAL::open where Test::MockFile installs its overrides. Perl's resolution order is: package > CORE::GLOBAL > CORE. Fix by installing goto-transparent wrappers into the caller's namespace during import(), ensuring our overrides take precedence over autodie's. A CHECK block re-installs after all compilation for load-order safety. When autodie is in scope and a mocked operation fails, _autodie_croak() throws an autodie::exception (or a formatted die fallback), preserving autodie's die-on-failure contract. Changes: - import() now calls _install_package_overrides() for the caller - _install_package_overrides: goto wrappers for 14 overridden builtins - CHECK block: re-install overrides after all use statements - _autodie_croak: detect autodie via %^H hints, throw compatible exception - __open/__sysopen: skip goto when autodie loaded, check result, die - POD: document autodie compatibility in CAVEATS section - Tests: t/autodie_compat.t (autodie first) and t/autodie_compat_reverse.t Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81f5ef6 to
068a951
Compare
When autodie is loaded before Test::MockFile, the call chain is: __open → Fatal wrapper → user code. The stack walker stopped at Fatal's frame (first non-TMF caller) but Fatal's own code doesn't have 'use autodie' hints, so the exception was never thrown. Skip Fatal and autodie::* frames to reach the actual user code where autodie hints are in scope. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The second eval { require autodie::exception; 1 } always clears $@
on success, destroying the exception captured from the first eval
block. Save $@ to $err immediately after the first eval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Author
CI Fix:
|
Contributor
|
view issue from smokers, for example on Perl 5.10 |
${^GLOBAL_PHASE} doesn't exist before 5.14, so the CHECK block guard
always evaluated to false, causing "Too late to run CHECK block" warnings
on 5.10/5.12. Use $] version check instead.
Autodie exception detection via caller hints hash is unreliable on
Perl < 5.14, so skip the death-related subtests on those versions.
Core functionality (mocked file access with autodie) still works.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #44. Makes
Test::MockFilecompatible withautodie— both modules can now coexist regardless of load order.Root Cause
autodieinstalls per-package wrappers (e.g.,main::open) that callCORE::opendirectly, bypassingCORE::GLOBAL::openwhere Test::MockFile installs its overrides. Perl's builtin resolution order is:main::open) — autodie wins hereCORE::GLOBAL::open— T::MF installs here, but never reachedCORE::open— the C-level builtinSolution
import()now installsgoto-transparent wrappers into the caller's namespace, ensuring T::MF's overrides take precedence over autodie'suse autodieappears afteruse Test::MockFile_autodie_croak(): When autodie is lexically active (checked via%^Hhints) and a mocked operation fails, throws anautodie::exception(or formatted die fallback)Changes
_install_package_overrides(): installs goto wrappers for all 14 overridden builtins_autodie_croak(): detects autodie scope via caller hints, throws compatible exception__open/__sysopen: modified fallback paths to check results when autodie is activeTest plan
t/autodie_compat.t— autodie loaded before T::MF: read, write, append, die-on-failure, exception typet/autodie_compat_reverse.t— T::MF loaded before autodie: read, write, die-on-failure (tests CHECK block)use autodie; use Test::MockFileanduse Test::MockFile; use autodiework correctlyExample (from issue #44)
🤖 Generated with Claude Code