Skip to content

fix: test pass rate quick wins (fileno, stat, switches, regex $1)#416

Merged
fglock merged 19 commits into
masterfrom
fix/test-pass-rate-quick-wins
Apr 1, 2026
Merged

fix: test pass rate quick wins (fileno, stat, switches, regex $1)#416
fglock merged 19 commits into
masterfrom
fix/test-pass-rate-quick-wins

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 1, 2026

Summary

Phase 1 quick wins from the test pass rate improvement plan:

  • fileno(): Return undef for closed/null ioHandle instead of NPE (fh.t: 0→6/8)
  • stat()/lstat(): Null guard after resolvePath() for NUL-in-filename (filetest.t: 227→231/436)
  • ArgumentParser: Uncomment System.exit(1) for unrecognized switches, fix exit code (switches.t)
  • RuntimeRegex: Preserve $1 across failed regex matches per Perl 5 semantics (universal.t: 90→122/142)

Combined estimated gain: ~75 tests across 4 test files.

Test plan

  • make passes (all unit tests green)
  • op/fh.t: 0/8 → 6/8
  • op/filetest.t: 227/436 → 231/436
  • op/universal.t: 90/142 → 122/142
  • Unrecognized switches now exit with code 1

Generated with Devin

fglock and others added 19 commits April 1, 2026 09:48
- fileno(): return undef for closed/null ioHandle instead of NPE (fh.t: 0→6/8)
- stat()/lstat(): null guard after resolvePath() for NUL-in-filename (filetest.t: 227→231/436)
- ArgumentParser: uncomment System.exit(1) for unrecognized switches (switches.t)
- RuntimeRegex: preserve $1 across failed matches per Perl 5 semantics (universal.t: 90→122/142)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Remove 'Invalid vec operation: ' prefix from error messages in RuntimeVecLvalue
- Fix unsigned 32-bit vec read using Integer.toUnsignedLong()
- Reorder vec read to check 64-bit before 32-bit

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…egex aliases

Map Perl 5.28+ alpha assertion aliases to their Java regex equivalents:
- (*pla:...) / (*positive_lookahead:...) -> (?=...)
- (*plb:...) / (*positive_lookbehind:...) -> (?<=...)
- (*nla:...) / (*negative_lookahead:...) -> (?!...)
- (*nlb:...) / (*negative_lookbehind:...) -> (?<!...)
- (*atomic:...) -> (?>...)

alpha_assertions.t: 2100→2188/2320 (+88 tests)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… notes

- Document batch 2 fixes (fileno, stat, switches, regex $1)
- Document batch 3 fixes (vec, alpha assertions)
- Add investigation notes for op/method.t indirect method parsing
- Add investigation notes for op/sort.t $$ prototype comparators
- Update next steps and corrected assessments (taint.t, sort.t, ref.t)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
In Perl 5, sort comparators with $$ prototype receive elements as
$_[0]/$_[1] instead of $a/$b. Detect prototype and populate @_
accordingly. (sort.t: 23→25/206)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
When assigning a tied scalar to a glob (*foo = $tied), call
tiedFetch() to get the underlying value before dispatching on type.
Fixes "typeglob assignment not implemented for 9" crash.
(tie_fetch_count.t: 1/343 → 64/343)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Perl 5 allows goto without arguments - it throws 'goto must have
label' at runtime. Previously PerlOnJava rejected this at parse time.
Now the parser accepts it, the interpreter GOTO_DYNAMIC handles
the empty-string label, and the JVM backend falls back to interpreter.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add CREATE_LAST_DYNAMIC/CREATE_NEXT_DYNAMIC/CREATE_REDO_DYNAMIC opcodes
for runtime-evaluated loop control labels (e.g. last $label). The JVM
backend falls back to interpreter for these. Unblocks loopctl.t from
0/0 to ~45/69.

Update test improvement plan with investigation notes for override.t,
loopctl.t, parser.t, and heredoc.t from subagent analysis.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…otype off-by-one

- BytecodeCompiler: add StringNode support for $ and & sigil handlers,
  fixing 'Unsupported $ operand: StringNode' crash that blocked parser.t
- PerlLanguageProvider: add VerifyError to needsInterpreterFallback() so
  invalid bytecode falls back to interpreter instead of crashing
- ListParser: save/restore heredoc state around wantFileHandle look-ahead
  to prevent heredoc corruption on backtrack
- PrototypeArgs: fix off-by-one in group prototype (\[$@%*]) parsing
  that skipped the character after the closing bracket
- Update test improvement plan with getlogin investigation for override.t

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…dings

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add opcodes 416-442 for getlogin, getpwnam, getpwuid, getgrnam,
getgrgid, getgrent, setgrent, endgrent, gethostbyaddr, getservbyname,
getservbyport, getprotobyname, getprotobynumber, endhostent, endnetent,
endprotoent, endservent, gethostent, getnetbyaddr, getnetbyname,
getnetent, getprotoent, getservent, sethostent, setnetent, setprotoent,
setservent.

These operators were already implemented in the JVM backend but missing
from the bytecode interpreter, causing 'Unsupported operator' crashes
when interpreter fallback was triggered.

Files changed: Opcodes.java, CompileOperator.java, MiscOpcodeHandler.java,
BytecodeInterpreter.java, Disassemble.java

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…patch

- BytecodeCompiler: add null guard in compileNode() to handle null AST
  elements from format declarations, preventing NullPointerException
  during interpreter fallback compilation
- BytecodeCompiler: make FormatNode visitor a no-op in the interpreter
  backend since formats are already registered by the JVM compiler.
  Fixes write.t crash from 'Formats not yet implemented'.
- StatementParser: dispatch 'use MODULE VERSION' through Perl method
  resolution (can + apply) instead of calling Universal.VERSION()
  directly. This allows custom VERSION methods to be called.
  Fixes leaky-magic.t: 0/0 -> 70/71.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Emit proper warnings when subroutines are redefined at compile time:
- "Prototype mismatch: sub NAME ..." - always on (default warning)
- "Constant subroutine NAME redefined" - always on (default warning)
- "Subroutine NAME redefined" - requires -w or use warnings 'redefine'

Matches Perl 5 behavior including:
- Format differences: ": none" vs " (proto)" display
- Warnings dispatched through $SIG{__WARN__}
- Proper $^W and lexical warnings checking

Result: comp/redef.t 1/20 -> 20/20

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…arnings

- OperatorParser.parseSelect(): Add GlobalVariable.getGlobalIO() autovivification
  before parseBarewordHandle(), matching the pattern used by readline/stat/etc.
  This fixes strict subs errors when using bareword filehandles with select().

- SubroutineParser: Skip prototype mismatch and redefinition warnings for
  Java-registered (XS-like) built-in methods being overridden by Perl stubs.
  Uses isStatic flag to detect built-in methods.

- warnings.pm: Add (;@) prototype to register_categories stub to match
  Java-registered prototype.

- overload.pm: Add ($) prototype to AddrRef stub to match Java-registered
  prototype.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add handling for GLOB and GLOBREFERENCE (reference to glob) types in
all three RuntimeCode.apply() method variants. When a glob or glob
reference is used as a subroutine (e.g., sort $glob_ref LIST), extract
the code slot from the glob name and dispatch to it.

This fixes sort with glob/globref comparators and general glob-as-code calls.

Result: op/sort.t 30/206 -> 125+/206 (test hangs on runperl tests)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Document all non-quick-fix test failures across 274 failing test files,
organized by missing feature/subsystem with difficulty ratings and
implementation notes. Covers taint tracking, format/write, regex code
blocks, delete local, caller() fields, attribute system, MRO invalidation,
in-place editing, and more.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Three fixes:
1. Sort comparator goto/last/next/redo detection: Check the return value
   (RuntimeControlFlowList) from apply() instead of the dead registry
   check. Now correctly throws pseudo block errors for control flow in sort.

2. Interpreter goto LABEL infinite loop: Use GOTO_DYNAMIC for unresolved
   forward gotos instead of GOTO with PC 0. Handles both forward references
   and non-local gotos to outer scopes correctly.

3. ArgumentParser -0/-l switch fix: Changed break to return index for
   switches that consume the rest of the argument string.

Results: sort.t 0/0->168/206, switches.t 67->72, uni/goto.t 2/4->4/4

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The previous fix (return index) broke clustered switches like -le, -0e,
-lpe where -l/-0 was combined with other switches. The handlers consumed
the entire rest of the arg string (including non-digit chars like 'e'),
preventing subsequent switches from being processed.

Now -0 and -l scan only valid octal digits (or hex with 0x prefix) from
the current arg inline, advance j past the consumed digits, and break to
continue processing remaining switches. This correctly handles:
- -le 'code': -l (no digits), then -e processes code
- -0777: -0 consumes '777' as octal, no remaining switches
- -l012e 'code': -l consumes '012', then -e processes code
- -0e 'code': -0 (no digits), then -e processes code

Restores: exec.t 27/41, dup.t 25/29, open.t 187/216, switcht.t 9/13,
term.t 7/7, srand.t 6/10, script.t 3/3. switches.t stays at 72/142.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock merged commit 74dc6ad into master Apr 1, 2026
2 checks passed
@fglock fglock deleted the fix/test-pass-rate-quick-wins branch April 1, 2026 12:30
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