fix: Test::Unit::Lite — three bug fixes + caller() line-number for both backends#656
Merged
fix: Test::Unit::Lite — three bug fixes + caller() line-number for both backends#656
Conversation
1. FileSpec.splitdir scalar context: `scalar File::Spec->splitdir($dir)` was
returning the last component instead of the component count. Fixed by adding
a scalar-context branch that returns `dirs.length` as a RuntimeScalar.
Affected Test::Unit::Lite::AllTests::suite() path-depth calculation.
2. Symbol::qualify_to_ref returned GLOB instead of GLOBREFERENCE: the Java
implementation was using `new RuntimeScalar().set(new RuntimeGlob(...))` which
creates a GLOB-typed scalar, not a reference-to-glob. Changed to
`new RuntimeGlob(object.toString()).createReference()` which produces
GLOBREFERENCE (type=GLOBREFERENCE), matching how gensym() works.
Without this fix, `keys %{ *{Symbol::qualify_to_ref("Pkg::")} }` returned
empty, so list_tests() found 0 test methods.
3. IOOperator.select auto-vivification: when `select $var` is called with an
undefined scalar, Perl auto-vivifies it into an anonymous GLOB reference
(enabling the idiom `select select my $fh_null; tie *$fh_null, 'Class'`).
Added the same pattern used by open/socket/pipe: create a new RuntimeGlob,
wrap a fresh RuntimeIO in it, create a GLOBREFERENCE, and set() it back on
the lvalue via runtimeList.getFirst().
Also added unit tests for cases 1 and 2 in directory.t and typeglob.t.
After these fixes: Test::Unit::Lite goes from 0/39 passing to 37/39 passing.
Remaining 2 failures are a pre-existing caller() line-number off-by-one for
multi-line function calls (not introduced by this PR).
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
In handleArrowOperator (Dereference.java) and handleApplyOperator (EmitSubroutine.java), the JVM line number at the callCached/apply INVOKESTATIC was set to the token index of the closing ')' of the argument list, not to the token index of the call site itself. This caused caller() inside a called subroutine to report the wrong source line — specifically the last line of the argument list rather than the line where the call begins. Fix: emit setDebugInfoLineNumber with node.left.getIndex() (the token index of the receiver object / function name) immediately before the INVOKESTATIC instruction in both call paths. This anchors the JVM bytecode to the Perl line where the call starts, so caller() returns the correct line number. Verified by ./jcpan -t Test::Unit::Lite: all 39 subtests now pass (was 37/39; test_assert_deep_equals and test_fail_assert_not_equals had been failing because check_failures() verified caller() line numbers from assertion failures). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The caller() line number fix resolved the 2 remaining failures. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Same root cause as the JVM fix (af48192): CALL_SUB and CALL_METHOD instructions in the interpreter's bytecode had their pcToTokenIndex entries pointing to the token AFTER the closing ')' (inherited from the statement-level emit), instead of the token at the call-site. Fix all three interpreter call-emit sites: - CompileBinaryOperator.java, coderef->() path: use emitWithToken with node.left.getIndex() (the coderef token index). - CompileBinaryOperator.java, ->method() path: same, with the invocant's token index. - CompileBinaryOperatorHelper.java, "()" switch case: change from emit() to emitWithToken(), driven by the call-site tokenIndex now passed from CompileBinaryOperator (node.left.getIndex()). After fix: --interpreter and JVM both report the same line as system Perl for caller() inside a called subroutine with multi-line args. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2 tasks
…eparator On Windows, File.separator is '\', so the previous code split only on backslash, returning 1 component for forward-slash paths like "a/b/c". Perl's File::Spec::Win32::splitdir splits on [/\\] (both separators). Mirror that by using a platform-aware regex: "[/\\\\]" on Windows and Pattern.quote(File.separator) elsewhere. Fixes unit/directory.t test 10 on Windows CI. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.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 three bugs uncovered by
./jcpan -t Test::Unit::Lite, plus theunderlying
caller()line-number issue that prevented the last 2/39subtests from passing. All 39/39 subtests now pass.
Bug 1 —
File::Spec->splitdirscalar contextsplitdirwas always returning a list; in scalar context it now returnsthe count, matching Perl's behaviour.
Bug 2 —
Symbol::qualify_to_refreturn typeWas returning a plain GLOB instead of a GLOB reference. Fixed to return
\*{"pkg::name"}.Bug 3 —
selectauto-vivification of undef scalarselect select my $fhnow auto-vivifies$fhinto an anonymous GLOBreference (matching Perl's open-my-filehandle behaviour), so a
subsequent
tie *$fh, ...works correctly.Bug 4 —
caller()line numbers for multi-line calls (JVM backend)handleArrowOperator(Dereference.java) andhandleApplyOperator(
EmitSubroutine.java) emittedcallCached/applywith the JVMline-number attribute pointing to the closing
)token, not thecall-site token. Added
ByteCodeSourceMapper.setDebugInfoLineNumberwith
node.left.getIndex()immediately before each call instruction.Bug 5 — same
caller()fix for the interpreter backendCALL_METHODandCALL_SUBopcodes inCompileBinaryOperator.javaand
CompileBinaryOperatorHelper.javawere emitted without apcToTokenIndexentry, sogetCallSiteInfo()fell back to thestatement-level entry (token after
)). Changed toemitWithTokenusing
node.left.getIndex()at all three call-emit sites.After both fixes,
./jperland./jperl --interpreteragree withsystem Perl on the line reported by
caller()inside a calledsubroutine whose argument list spans multiple lines.
Test plan
make— all unit tests pass./jcpan -t Test::Unit::Lite— 39/39 subtests pass (was 37/39)dev/cpan-reports/cpan-compatibility.md: PARTIAL → PASSGenerated with Devin