Skip to content

NullPointerException when there are racy resources #2456

Description

@TWiStErRob

Only happened once, cannot reproduce, but reading the code confirms there's a bug here:

List<String> busyResources = idlingResourceRegistry.getBusyResources();
conditionName =
String.format(
Locale.ROOT,
"%s(busy resources=%s)",
conditionName,
StringJoinerKt.joinToString(busyResources, ","));

fun joinToString(iterable: Iterable<kotlin.Any>, delimiter: String): String {

the above expects a non-null list, but the below returns null:

List<String> getBusyResources() {
List<String> busyResourceNames = new ArrayList<>();
List<IdlingState> racyResources = new ArrayList<>();
for (IdlingState state : idlingStates) {
if (!state.idle) {
if (state.resource.isIdleNow()) {
// We have not been notified of a BUSY -> IDLE transition, but the resource is telling us
// its that its idle. Either it's a race condition or is this resource buggy.
racyResources.add(state);
} else {
busyResourceNames.add(state.resource.getName());
}
}
}
if (!racyResources.isEmpty()) {
Message raceBuster =
handler.obtainMessage(POSSIBLE_RACE_CONDITION_DETECTED, TIMEOUT_MESSAGE_TAG);
raceBuster.obj = racyResources;
handler.sendMessage(raceBuster);
return null;

java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.test.espresso.util.StringJoinerKt.joinToString, parameter iterable
    at androidx.test.espresso.Espresso.onIdle(Espresso.java:357)
    at androidx.test.espresso.Espresso.onIdle(Espresso.java:378)
    at androidx.compose.ui.test.EspressoLink_androidKt.runEspressoOnIdle(EspressoLink.android.kt:88)
    at androidx.compose.ui.test.EspressoLink.runUntilIdle(EspressoLink.android.kt:82)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.waitForIdle(ComposeUiTest.android.kt:596)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$waitForIdle(ComposeUiTest.android.kt:391)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidTestOwner.getRoots(ComposeUiTest.android.kt:822)
    at androidx.compose.ui.test.TestOwnerKt.getAllSemanticsNodes(TestOwner.kt:81)
    at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNodes$ui_test_release(SemanticsNodeInteraction.kt:64)
    at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNodes$ui_test_release$default(SemanticsNodeInteraction.kt:59)
    at androidx.compose.ui.test.AndroidAssertions_androidKt.checkIsDisplayed(AndroidAssertions.android.kt:29)
    at androidx.compose.ui.test.AssertionsKt.isDisplayed(Assertions.kt:351)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.waitUntil(ComposeUiTest.android.kt:747)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule.waitUntil(AndroidComposeTestRule.android.kt:362)
    at com.example.MyTest.myTest(MyTest.kt:78)
    at java.lang.reflect.Method.invoke(Native Method)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
    at androidx.test.rule.GrantPermissionRule$RequestPermissionStatement.evaluate(GrantPermissionRule.java:150)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$testWithDisposal$1.evaluate(AndroidComposeTestRule.android.kt:306)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invokeSuspend(AndroidComposeTestRule.android.kt:318)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(Unknown Source:8)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(Unknown Source:4)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invokeSuspend(ComposeUiTest.android.kt:569)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invoke(Unknown Source:8)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invoke(Unknown Source:2)
    at androidx.compose.ui.test.EspressoLink.withStrategy(EspressoLink.android.kt:69)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invokeSuspend(ComposeUiTest.android.kt:566)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(Unknown Source:8)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(Unknown Source:4)
    at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$1.invokeSuspend(TestBuilders.kt:317)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
    at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:24)
    at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:99)
    at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:326)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:263)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:94)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:70)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
    at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
    at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:10)
    at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:309)
    at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
    at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:167)
    at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.runTest(ComposeUiTest.android.kt:549)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1.evaluate(AndroidComposeTestRule.android.kt:318)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:68)
    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:467)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2594)
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.test.espresso.util.StringJoinerKt.joinToString, parameter iterable
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at androidx.test.espresso.Espresso.onIdle(Espresso.java:349)
... 100 more
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.test.espresso.util.StringJoinerKt.joinToString, parameter iterable
    at androidx.test.espresso.util.StringJoinerKt.joinToString(Unknown Source:2)
    at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:559)
    at androidx.test.espresso.base.UiControllerImpl.loopMainThreadUntilIdle(UiControllerImpl.java:434)
    at androidx.test.espresso.Espresso.lambda$onIdle$2(Espresso.java:340)
    at androidx.test.espresso.Espresso$$ExternalSyntheticLambda1.call(D8$$SyntheticClass:0)
    at java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:232)
    at android.os.Looper.loop(Looper.java:317)
    at android.app.ActivityThread.main(ActivityThread.java:8705)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions