Skip to content

Make JavaObject finalizer tests deterministic#1408

Merged
jonathanpeppers merged 6 commits intomainfrom
fix/deterministic-dispose-finalized
Apr 21, 2026
Merged

Make JavaObject finalizer tests deterministic#1408
jonathanpeppers merged 6 commits intomainfrom
fix/deterministic-dispose-finalized

Conversation

@simonrozsival
Copy link
Copy Markdown
Member

Summary

  • stop relying on WaitForGCBridgeProcessing timing in JavaObjectTest
  • wait on the finalizer or collection condition directly instead
  • bound the wait to 2 seconds so the test cannot hang indefinitely

Why

Dispose_Finalized is still a useful regression test, but the previous version depended on GC bridge timing rather than the actual contract under test. That became visible from dotnet/android PR #11119, where removing the bridge wait exposed the test as flaky.

This keeps the regression coverage while making the assertions deterministic and implementation-independent.

Validation

  • targeted JavaObjectTest.Dispose_Finalized
  • JavaObjectTest suite

Avoid relying on WaitForGCBridgeProcessing timing in JavaObjectTest.

Use explicit completion signals plus a bounded 2-second wait so Dispose_Finalized and the collection tests assert the behavior we actually care about without hanging indefinitely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 17, 2026 16:10
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR makes JavaObjectTest GC/finalizer-related assertions deterministic by waiting for specific conditions (object collected / finalizer ran) instead of relying on GC bridge processing timing, and by bounding those waits to a 2-second timeout.

Changes:

  • Updated UnreferencedInstanceIsCollected to wait until the WeakReference is dead and the peer is removed from the ValueManager.
  • Updated Dispose_Finalized to wait for the finalizer path using TaskCompletionSource signals instead of timing-based flags.
  • Replaced the old WaitForGC() helper with two overloads that wait on either a predicate or a Task, with a 2-second timeout.

Comment thread tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs Outdated
Comment thread tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs Outdated
Comment thread tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs Outdated
Comment thread tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs Outdated
Comment thread tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs Outdated
simonrozsival and others added 5 commits April 18, 2026 01:16
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert.IsFalse (d);
Assert.IsTrue (f);
await WaitForGC (
() => disposed.Task.IsCompleted || finalized.Task.IsCompleted,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be:

Suggested change
() => disposed.Task.IsCompleted || finalized.Task.IsCompleted,
() => disposed.Task.IsCompleted && finalized.Task.IsCompleted,

If one completes quicker than the other?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm convinced it's correct the way it is. The expectation is that finalized task completes and disposed does not. So we definitely need || for the passing scenario. Also, if disposed completes, the test will fail and there's no need to wait for the finalized task.

@jonathanpeppers jonathanpeppers merged commit a901f97 into main Apr 21, 2026
2 checks passed
@jonathanpeppers jonathanpeppers deleted the fix/deterministic-dispose-finalized branch April 21, 2026 13:41
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.

3 participants