Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Arrays.asList from critical stubbing path in GenericMetadataSu… #3610

Merged
merged 1 commit into from
Mar 14, 2025

Conversation

adrianroos
Copy link
Contributor

@adrianroos adrianroos commented Mar 13, 2025

…pport

On Android, the implementation of java.util.Arrays.ArrayList.toArray has a non-trivial implementation that ends up calling into android.os.Process.myUid().

Consequently, attempting to stub static methods in android.os.Process with doReturn will end up calling into myUid() before the stubbing completes, triggering an infinite recursion.

To work around that, replace the addAll(asList(...)) call with Collections.addAll. As an added benefit this avoids an array copy.

This upstreams https://r.android.com/3500336.

The infinitely recursing stack trace was triggered by ExtendedMockito.doReturn(true).when(() -> Process.isSdkSandbox());:

        ...
	at android.os.Process.myUid(Unknown Source:29)
	at android.app.AppCompatCallbacks.reportChange(AppCompatCallbacks.java:85)
	at android.app.AppCompatCallbacks.isChangeEnabled(AppCompatCallbacks.java:80)
	at android.compat.Compatibility.isChangeEnabled(Compatibility.java:87)
	at java.util.Arrays$ArrayList.toArray(Arrays.java:4570)
	at java.util.LinkedList.addAll(LinkedList.java:419)
	at java.util.LinkedList.addAll(LinkedList.java:398)
	at org.mockito.internal.util.reflection.GenericMetadataSupport.registerAllTypeVariables(GenericMetadataSupport.java:94)
	at org.mockito.internal.util.reflection.GenericMetadataSupport$FromClassGenericMetadataSupport.<init>(GenericMetadataSupport.java:365)
	at org.mockito.internal.util.reflection.GenericMetadataSupport.inferFrom(GenericMetadataSupport.java:334)
	at org.mockito.internal.stubbing.answers.InvocationInfo.isVoid(InvocationInfo.java:56)
	at org.mockito.internal.stubbing.answers.Returns.validateFor(Returns.java:34)
	at org.mockito.internal.stubbing.InvocationContainerImpl.addAnswer(InvocationContainerImpl.java:65)
	at org.mockito.internal.stubbing.InvocationContainerImpl.setMethodForStubbing(InvocationContainerImpl.java:125)
	at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:55)
	at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
	at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
	at com.android.dx.mockito.inline.InvocationHandlerAdapter.interceptEntryHook(InvocationHandlerAdapter.java:75)
	at com.android.dx.mockito.inline.StaticMockMethodAdvice.handle(StaticMockMethodAdvice.java:248)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.dx.mockito.inline.MockMethodDispatcher.handle(MockMethodDispatcher.java:79)
	at android.os.Process.myUid(Unknown Source:29)
        ...

Checklist

  • Read the contributing guide
  • PR should be motivated, i.e. what does it fix, why, and if relevant how
  • If possible / relevant include an example in the description, that could help all readers
    including project members to get a better picture of the change
  • Avoid other runtime dependencies
  • Meaningful commit history ; intention is important please rebase your commit history so that each
    commit is meaningful and help the people that will explore a change in 2 years
  • The pull request follows coding style
  • Mention Fixes #<issue number> in the description if relevant
  • At least one commit should mention Fixes #<issue number> if relevant

…pport

On Android, the implementation of java.util.Arrays.ArrayList.toArray has a non-trivial implementation that ends up calling into android.os.Process.myUid().

Consequently, attempting to stub static methods in android.os.Process with doReturn will end up calling into myUid() before the stubbing completes, triggering an infinite recursion.

To work around that, replace the addAll(asList(...)) call with Collections.addAll. As an added benefit this avoids an array copy.

This upstreams https://r.android.com/3500336.
@adrianroos adrianroos marked this pull request as ready for review March 13, 2025 10:28
@TimvdLippe
Copy link
Contributor

Please add a regression test to https://github.com/mockito/mockito/tree/main/mockito-integration-tests/android-tests/src/ so we can ensure this remains fixed. Thanks for upstreaming this effort 👍

@codecov-commenter
Copy link

codecov-commenter commented Mar 13, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 85.56%. Comparing base (c81be5d) to head (e4e91a7).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #3610   +/-   ##
=========================================
  Coverage     85.56%   85.56%           
  Complexity     2957     2957           
=========================================
  Files           341      341           
  Lines          9028     9028           
  Branches       1119     1119           
=========================================
  Hits           7725     7725           
  Misses         1013     1013           
  Partials        290      290           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@adrianroos
Copy link
Contributor Author

Thank you for the review!

I considered adding a test for this, but reproducing the issue requires both static mocking and running on the Android runtime; the Android platform tests use ExtendedMockito to achieve that, but the latest version of that doesn't work with Mockito 5.

@TimvdLippe TimvdLippe merged commit 0215884 into mockito:main Mar 14, 2025
18 checks passed
svc-squareup-copybara pushed a commit to cashapp/misk that referenced this pull request Mar 17, 2025
| Package | Type | Package file | Manager | Update | Change |
|---|---|---|---|---|---|
| [org.mockito:mockito-core](https://github.com/mockito/mockito) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`5.16.0` -> `5.16.1` |
| [org.junit.jupiter:junit-jupiter-params](https://junit.org/junit5/)
([source](https://github.com/junit-team/junit5)) | dependencies |
misk/gradle/libs.versions.toml | gradle | patch | `5.12.0` -> `5.12.1` |
| [org.junit.jupiter:junit-jupiter-engine](https://junit.org/junit5/)
([source](https://github.com/junit-team/junit5)) | dependencies |
misk/gradle/libs.versions.toml | gradle | patch | `5.12.0` -> `5.12.1` |
| [org.junit.jupiter:junit-jupiter-api](https://junit.org/junit5/)
([source](https://github.com/junit-team/junit5)) | dependencies |
misk/gradle/libs.versions.toml | gradle | patch | `5.12.0` -> `5.12.1` |
| [software.amazon.awssdk:sdk-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
| [software.amazon.awssdk:sqs](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
|
[software.amazon.awssdk:dynamodb-enhanced](https://aws.amazon.com/sdkforjava)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
| [software.amazon.awssdk:dynamodb](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
| [software.amazon.awssdk:aws-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
| [software.amazon.awssdk:bom](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |
| [software.amazon.awssdk:auth](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.31.0` -> `2.31.1` |

---

### Release Notes

<details>
<summary>mockito/mockito (org.mockito:mockito-core)</summary>

### [`v5.16.1`](https://github.com/mockito/mockito/releases/tag/v5.16.1)

<sup><sup>*Changelog generated by [Shipkit Changelog Gradle
Plugin](https://github.com/shipkit/shipkit-changelog)*</sup></sup>

##### 5.16.1

- 2025-03-15 - [3
commit(s)](mockito/mockito@v5.16.0...v5.16.1)
by Adrian Roos, Jérôme Prinet, Rafael Winterhalter
- Remove Arrays.asList from critical stubbing path in GenericMetadataSu…
[(#&#8203;3610)](mockito/mockito#3610)
- Rework of injection strategy in the context of modules
[(#&#8203;3608)](mockito/mockito#3608)
- Adjust inline mocking snippet to allow task relocatability
[(#&#8203;3606)](mockito/mockito#3606)
- Inline mocking configuration snippet for Gradle should allow task
relocatability
[(#&#8203;3605)](mockito/mockito#3605)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 6pm every weekday,before 2am
every weekday" in timezone Australia/Melbourne, Automerge - At any time
(no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://github.com/renovatebot/renovate).

GitOrigin-RevId: 1939516a6a445b5c4812a6d4f27f483cdb66b66e
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