Skip to content

fix(perry-ffi): unbreak cargo test -p perry-ffi (undefined js_register_ffi_handle_exists_probe)#5088

Merged
proggeramlug merged 1 commit into
mainfrom
fix/perry-ffi-test-link-handle-probe
Jun 13, 2026
Merged

fix(perry-ffi): unbreak cargo test -p perry-ffi (undefined js_register_ffi_handle_exists_probe)#5088
proggeramlug merged 1 commit into
mainfrom
fix/perry-ffi-test-link-handle-probe

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

The cargo-test CI gate is red on main (e.g. #5083's own run, and every PR branched off it — including #5086). The failure is a link error, not a test failure — every test result line shows 0 failed, then the job dies at cc:

perry_ffi ... undefined reference to `js_register_ffi_handle_exists_probe'
collect2: error: ld returned 1 exit status
error: could not compile `perry-ffi` (lib test) due to 1 previous error

Root cause

#5083 added a js_register_ffi_handle_exists_probe(...) call inside register_handle (crates/perry-ffi/src/handle.rs) to wire up the runtime's handle-vs-timer disambiguation probe. That symbol is defined in perry-runtime, which perry-ffi only pulls in behind its runtime-link feature (off by default).

perry-ffi's handle-registry tests live in a bare #[cfg(test)] module (unlike every other perry-ffi test module, which gates on #[cfg(all(test, feature = "runtime-link"))]). They call register_handle, so once #5083 made register_handle reference the runtime symbol, the default test binary retained an undefined reference. It only surfaces in isolation because CI runs cargo test -p $package per-package in a loop (see .github/workflows/test.yml) — there's no cargo test --workspace, so feature unification from the perry-ext-* dev-deps never pulls runtime-link in.

Fix

Gating the handle tests on runtime-link like the other modules would drop them from CI entirely (the per-package loop never enables the feature). Instead, add a test-only no-op stub for the symbol, gated #[cfg(all(test, not(feature = "runtime-link")))], so the registry tests keep running and the binary links. The real extern declaration is gated out of that exact configuration to avoid an E0428 name clash.

The stub can never collide with perry-runtime's real definition — it exists only in perry-ffi's own test binary with runtime-link off:

  • runtime-link on → stub excluded, real perry-runtime symbol used.
  • non-test lib builds (npm wrappers) → stub excluded; final binary links libperry_runtime.a.

Verification

  • cargo test -p perry-ffi (default, the failing config) → links + passes, 13 tests.
  • cargo test -p perry-ffi --features runtime-link → uses the real perry-runtime symbol, passes, 35 tests, no E0428, no duplicate-symbol.

Touches only crates/perry-ffi/src/handle.rs (+ version/changelog).


This unblocks the cargo-test gate for the whole repo. Recommended to merge before #5086 (the loop-guard perf PR), which currently inherits this same red cargo-test; after this lands I'll rebase #5086 and its CI will go green.

Summary by CodeRabbit

  • Chores
    • Resolved test infrastructure conflicts by updating conditional declarations, allowing unit tests to run successfully in specific build configurations.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 808c4521-9247-434f-a024-dd52929cce77

📥 Commits

Reviewing files that changed from the base of the PR and between defdf41 and 3a1c5ef.

📒 Files selected for processing (1)
  • crates/perry-ffi/src/handle.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/perry-ffi/src/handle.rs

📝 Walkthrough

Walkthrough

The PR adds conditional compilation logic to crates/perry-ffi/src/handle.rs that gates the js_register_ffi_handle_exists_probe extern declaration and provides a no-op stub implementation when building unit tests without the runtime-link feature, resolving undefined symbol linking errors.

Changes

FFI Symbol Stub for Test Linking

Layer / File(s) Summary
FFI symbol stub for test linking
crates/perry-ffi/src/handle.rs
Conditionally gates the js_register_ffi_handle_exists_probe extern declaration behind a feature check, and provides a #[no_mangle] unsafe extern "C" no-op stub implementation under cfg(all(test, not(feature = "runtime-link"))) so handle-registry tests can link and run during per-package test builds.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A stub for the probe, the symbols aligned,
Test builds now link with the feature design,
One little no-op stub saves the day,
FFI tests run without dismay! 🧪✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the fix: unbreaking cargo test -p perry-ffi by resolving an undefined reference to js_register_ffi_handle_exists_probe. It directly matches the main change in the PR.
Description check ✅ Passed The PR description comprehensively covers the problem, root cause, fix, and verification with commands tested. However, the required test plan checklist items are not marked, and changes/related issue sections are missing from the structured format.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/perry-ffi-test-link-handle-probe

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 1-30: Remove the changelog entry introduced in this PR: delete the
"## v0.5.1164 — fix(perry-ffi): unbreak `cargo test -p perry-ffi` (undefined
`js_register_ffi_handle_exists_probe`)" section from CHANGELOG.md (the entire
paragraph shown in the diff) so the PR does not modify release notes; leave the
rest of the file untouched or restore it to the state prior to this PR.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 005afe20-4855-4d19-8cce-badd66a8c1a6

📥 Commits

Reviewing files that changed from the base of the PR and between 9b6bbe0 and defdf41.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • crates/perry-ffi/src/handle.rs

Comment thread CHANGELOG.md Outdated
Comment on lines +1 to +30
## v0.5.1164 — fix(perry-ffi): unbreak `cargo test -p perry-ffi` (undefined `js_register_ffi_handle_exists_probe`)

The `cargo-test` CI gate was red on `main`: #5083 added a
`js_register_ffi_handle_exists_probe(...)` call inside `register_handle`
(`crates/perry-ffi/src/handle.rs`) to wire up the runtime's handle-vs-timer
disambiguation probe. That symbol is defined in `perry-runtime`, but
`perry-ffi`'s `runtime-link` feature (which pulls `perry-runtime` into the
Cargo graph) is **off** by default, and CI runs `cargo test -p perry-ffi`
per-package in isolation — no `--workspace` feature unification. So the
handle-registry tests (a bare `#[cfg(test)]` module that calls
`register_handle`) retained a reference to a symbol that wasn't linked, and the
test binary failed at `cc` with `undefined reference to
js_register_ffi_handle_exists_probe`.

All other `perry-ffi` test modules avoid this by gating on
`#[cfg(all(test, feature = "runtime-link"))]`, but gating the handle tests the
same way would drop them from CI entirely (the per-package loop never enables
the feature). Instead, this adds a **test-only no-op stub** for the symbol,
gated `#[cfg(all(test, not(feature = "runtime-link")))]`, so the registry tests
keep running and the binary links. The real `extern` declaration is gated out
of that exact configuration to avoid an `E0428` name clash. The stub can never
collide with `perry-runtime`'s real definition: it exists only in `perry-ffi`'s
own `test` binary with `runtime-link` off — not in `runtime-link`-on builds
(real symbol used) nor in the lib builds that npm wrappers link against
`libperry_runtime.a`.

Verified: `cargo test -p perry-ffi` now links and passes (13 tests); `cargo test
-p perry-ffi --features runtime-link` still uses the real perry-runtime symbol
and passes (35 tests), no collision.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove this changelog entry from the PR.

This release note belongs in the maintainer merge step, not in an external-contributor PR. As per coding guidelines, CHANGELOG.md is updated when changes land on main, and the recorded learning says contributors should not modify it here. As per coding guidelines, CHANGELOG.md entries are required for every change that lands on main; according to the repo learning, external contributor PRs should not modify CHANGELOG.md, and the maintainer adds release notes at merge time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 1 - 30, Remove the changelog entry introduced in
this PR: delete the "## v0.5.1164 — fix(perry-ffi): unbreak `cargo test -p
perry-ffi` (undefined `js_register_ffi_handle_exists_probe`)" section from
CHANGELOG.md (the entire paragraph shown in the diff) so the PR does not modify
release notes; leave the rest of the file untouched or restore it to the state
prior to this PR.

Sources: Coding guidelines, Learnings

…ter_ffi_handle_exists_probe)

#5083 added a `js_register_ffi_handle_exists_probe(...)` call inside
`register_handle` (handle.rs) for the runtime's handle-vs-timer disambiguation
probe. That symbol is defined in perry-runtime, but perry-ffi's `runtime-link`
feature is off by default and CI runs `cargo test -p perry-ffi` per-package in
isolation (no --workspace feature unification). The handle-registry tests
(bare `#[cfg(test)]`) call `register_handle`, so the test binary retained a
reference to an unlinked symbol and failed at `cc` with `undefined reference`.

Gating the handle tests on `runtime-link` (the pattern other perry-ffi test
modules use) would drop them from CI entirely (the per-package loop never
enables the feature). Instead add a test-only no-op stub gated
`#[cfg(all(test, not(feature = "runtime-link")))]` so the registry tests keep
running and the binary links; the real extern declaration is gated out of that
exact config to avoid an E0428 name clash. The stub can never collide with
perry-runtime's real definition (it exists only in perry-ffi's own test binary
with runtime-link off).

Verified: `cargo test -p perry-ffi` links + passes (13); `cargo test -p
perry-ffi --features runtime-link` uses the real symbol + passes (35).
@proggeramlug proggeramlug force-pushed the fix/perry-ffi-test-link-handle-probe branch from defdf41 to 3a1c5ef Compare June 13, 2026 13:40
@proggeramlug proggeramlug merged commit 12ae086 into main Jun 13, 2026
14 checks passed
@proggeramlug proggeramlug deleted the fix/perry-ffi-test-link-handle-probe branch June 13, 2026 13:42
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