Skip to content

feat(r8-tests): Add R8 line number tests#75

Merged
romtsn merged 29 commits intomasterfrom
rz/feat/r8-tests-line-number-handling
Feb 16, 2026
Merged

feat(r8-tests): Add R8 line number tests#75
romtsn merged 29 commits intomasterfrom
rz/feat/r8-tests-line-number-handling

Conversation

@romtsn
Copy link
Copy Markdown
Member

@romtsn romtsn commented Jan 19, 2026

Part of #40

R8 Retrace Test Coverage

  • Inlining (13 tests) - inline frames, line numbers, source files, rewriteFrame rules
  • Ambiguous Methods (21 tests) - multiple methods → same obfuscated name, alternatives
  • Outlines (4 tests) - outline callsites, nested outlines, inline-in-outline
  • Synthetic/Lambda (3 tests) - lambda methods, synthetic bridges
  • Source File Edge Cases (7 tests) - colons, unicode, multiple dots, synthesized names
  • Line Number Handling (10 tests) - spans, preambles, invalid ranges, missing lines
  • Exception Handling (6 tests) - obfuscated exceptions, suppressed, circular refs
  • Method Overloading (4 tests) - overloads with/without ranges
  • Special Formats (4 tests) - Java 9+ modules, logcat format, auto-detect

@romtsn romtsn changed the title feat(r8-tests): Add R8 ambiguous tests feat(r8-tests): Add R8 line number tests Jan 19, 2026
@romtsn romtsn requested a review from loewenheim January 20, 2026 13:07
@romtsn romtsn changed the base branch from rz/feat/r8-tests-source-files to rz/fix/r8-tests-source-file-no-line January 28, 2026 21:52
… edge cases (#79)

- Split source file names by the last `:` occurrence 
- Additionally fixes no-line original line preservation
- Also removes `tests/r8-source-file-edge-cases.NOTES.md`
- Removes two tests that we agreed do not need fixing
Base automatically changed from rz/fix/r8-tests-source-file-no-line to rz/feat/r8-tests-source-files January 29, 2026 22:09
Base automatically changed from rz/feat/r8-tests-source-files to master January 30, 2026 09:56
romtsn and others added 8 commits January 30, 2026 11:12
## Summary
- Normalize inverted minified ranges (e.g. `5:3:void main() -> main`) by
swapping start/end values
- Normalize inverted original ranges (e.g. `2:5:void main():5:2 ->
main`) independently
- Fixes incorrect line interpolation for these edge cases (tests 7 and 8
in `r8-line-number-handling`)

## Test plan
- [x] `test_invalid_minified_range_stacktrace` now passes
- [x] `test_invalid_original_range_stacktrace` now passes
- [x] Full test suite passes with no regressions (`make test`, `make
format`, `make lint`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ze> (#83)

## Summary
- Changes `StackFrame.line` from `usize` to `Option<usize>` to
distinguish "no line info" (`None`) from "line 0" (`Some(0)`)
- This is a prerequisite for correctly handling R8's various no-line
mapping semantics
- All call sites updated with `unwrap_or(0)` to preserve current
behavior; no semantic changes

## Test plan
- [x] All existing tests pass (no regressions)
- [x] `test_multiple_lines_no_line_number_stacktrace` now passes as a
bonus (was previously failing)
- [x] 5 known-failing r8-line-number-handling tests remain (will be
fixed in subsequent PRs)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Make `startline`, `endline`, and `original_startline` fields
`Option`-typed on both `Member` (builder) and `MemberMapping` (mapper)
structs
- Replaces the earlier boolean flags (`has_minified_range`,
`has_line_mapping`) — presence/absence is now encoded directly:
`startline.is_some()` means a minified range was present,
`original_startline.is_some()`
   means a line mapping existed
- In the binary cache format, `u32::MAX` is used as a sentinel for
absent values (via `NONE_VALUE` constant)
- Change `StackFrame.line` from `usize` to `Option<usize>` to
distinguish "no line provided" from "line 0"
- Fix inverted line ranges in mapping parser (swap start/end when start
> end)
  - Bumps cache version 4 → 5

  ## Test plan
  - [x] All existing tests pass (no regressions)
- [x] Same 5 known-failing r8-line-number-handling tests remain (will be
fixed in subsequent PRs)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Rewrites no-line frame resolution in both mapper and cache paths to
properly handle different base entry types (0:0 range vs bare method vs
single-line mappings)
- Extracts resolution logic into `resolve_no_line_frames` /
`resolve_base_entries` helper functions that use `Option` field presence
(`startline.is_some()`, `original_startline.is_some()`) instead of the
removed
  boolean flags
- Simplifies `resolve_base_entries` from a two-pass Vec collection to a
single-pass approach
- Adds `pending_frames` buffer to cache `RemappedFrameIter` for
multi-frame base entry resolution
  - Removes unused `resolve_no_line_output_line` from utils

  ## Test plan
  - [x] All existing tests pass (50 unit + all integration tests)
- [x] 3 pre-existing failures in r8-line-number-handling remain
(targeted by subsequent PRs)
  - [x] No new warnings

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- When a base entry (no minified range) maps to a span of original lines
(e.g., `:42:44`), expand into one frame per original line instead of
just the first
- When a frame's line number falls outside all mapped member ranges,
fall back to class-only remapping (keeping the obfuscated method name
and original line)
- Adds `matched_any` tracking in cache iterator to prevent false
fallback triggers after successful matches

Fixes `test_different_line_number_span_stacktrace` and
`test_outside_line_range_stacktrace`.

## Test plan
- [x] All existing tests pass (50 lib + all integration tests)
- [x] `test_different_line_number_span_stacktrace` now passes (was
failing: 1 frame instead of 3)
- [x] `test_outside_line_range_stacktrace` now passes (was failing:
unremapped frame instead of class-only remap)
- [x] Only remaining failure is
`test_single_line_no_line_number_stacktrace` (Group F — ordering)
- [x] `make format` and `make lint` pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- When multiple no-range entries with different original method names
all have line mappings (`original_startline.is_some()`), sort them
alphabetically by original method name
- Bare method entries (`original_startline.is_none()`) continue to
preserve original mapping file order

Fixes `test_single_line_no_line_number_stacktrace` — all 10 R8 line
number handling tests now pass.

  ## Test plan
  - [x] All 138 tests + 11 doc tests pass
- [x] `test_single_line_no_line_number_stacktrace` now passes (ordering:
`main3` before `method3`)
- [x] `test_ambiguous_stacktrace` still passes (bare methods preserve
file order: `foo` before `bar`)
  - [x] `make format` and `make lint` pass

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@romtsn romtsn merged commit aad9410 into master Feb 16, 2026
8 checks passed
@romtsn romtsn deleted the rz/feat/r8-tests-line-number-handling branch February 16, 2026 13:50
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.

2 participants