[go: nahoru, domu]

blob: daaa8da1e17a2fe4fb1811404d9cb152e18ed5f3 [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.ui.test
import androidx.activity.ComponentActivity
import androidx.compose.Composable
import androidx.compose.mutableStateOf
import androidx.compose.state
import androidx.test.espresso.AppNotIdleException
import androidx.test.espresso.IdlingPolicies
import androidx.test.espresso.IdlingPolicy
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.filters.LargeTest
import androidx.ui.core.Modifier
import androidx.ui.core.onPositioned
import androidx.compose.foundation.Box
import androidx.compose.foundation.Text
import androidx.compose.foundation.layout.Stack
import androidx.ui.test.android.createAndroidComposeRule
import androidx.ui.test.android.ComposeNotIdleException
import androidx.ui.test.util.expectError
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.util.concurrent.TimeUnit
@LargeTest
@RunWith(JUnit4::class)
class TimeOutTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
private var idlingResourcePolicy: IdlingPolicy? = null
private var masterPolicy: IdlingPolicy? = null
private val expectedErrorDueToRecompositions =
".*ComposeIdlingResource is busy due to pending recompositions.*"
@Before
fun backupTimeOutPolicies() {
idlingResourcePolicy = IdlingPolicies.getDynamicIdlingResourceErrorPolicy()
masterPolicy = IdlingPolicies.getMasterIdlingPolicy()
}
@After
fun restoreTimeOutPolicies() {
IdlingRegistry.getInstance().unregister(InfiniteResource)
IdlingPolicies.setIdlingResourceTimeout(
idlingResourcePolicy!!.idleTimeout, idlingResourcePolicy!!.idleTimeoutUnit)
IdlingPolicies.setMasterPolicyTimeout(
masterPolicy!!.idleTimeout, masterPolicy!!.idleTimeoutUnit)
}
@Composable
fun infiniteCase() {
Stack {
val infiniteCounter = state { 0 }
Box(Modifier.onPositioned {
infiniteCounter.value += 1
}) {
Text("Hello")
}
Text("Hello ${infiniteCounter.value}")
}
}
@Test(timeout = 5000)
fun infiniteRecompositions_resourceTimeout() {
IdlingPolicies.setIdlingResourceTimeout(300, TimeUnit.MILLISECONDS)
expectError<ComposeNotIdleException>(expectedMessage = expectedErrorDueToRecompositions) {
composeTestRule.setContent {
infiniteCase()
}
}
}
@Test(timeout = 5000)
fun infiniteRecompositions_masterTimeout() {
IdlingPolicies.setMasterPolicyTimeout(300, TimeUnit.MILLISECONDS)
expectError<ComposeNotIdleException>(expectedMessage = expectedErrorDueToRecompositions) {
composeTestRule.setContent {
infiniteCase()
}
}
}
@Test(timeout = 5000)
fun delayInfiniteTrigger() {
// This test checks that we properly time out on infinite recompositions that happen later
// down the road (not right during setContent).
val count = mutableStateOf(0)
composeTestRule.setContent {
Text("Hello ${count.value}")
if (count.value > 0) {
count.value++
}
}
onNodeWithText("Hello 0").assertExists()
count.value++ // Start infinite re-compositions
IdlingPolicies.setMasterPolicyTimeout(300, TimeUnit.MILLISECONDS)
expectError<ComposeNotIdleException>(expectedMessage = expectedErrorDueToRecompositions) {
onNodeWithText("Hello").assertExists()
}
}
@Test(timeout = 10_000)
fun emptyComposition_masterTimeout_fromIndependentIdlingResource() {
// This test checks that if we fail to sync on some unrelated idling resource we don't
// override the vanilla errors from Espresso.
IdlingPolicies.setMasterPolicyTimeout(300, TimeUnit.MILLISECONDS)
IdlingRegistry.getInstance().register(InfiniteResource)
expectError<AppNotIdleException> {
composeTestRule.setContent { }
}
}
@Test(timeout = 5000)
fun timeout_testIsolation_check() {
// This test is here to guarantee that even if we crash on infinite recompositions after
// we set a content. We still recover and the old composition is no longer running in the
// background causing further delays. This verifies that our tests run in isolation.
val androidTestRule = composeTestRule
// Start infinite case and die on infinite recompositions
IdlingPolicies.setMasterPolicyTimeout(300, TimeUnit.MILLISECONDS)
expectError<ComposeNotIdleException> {
composeTestRule.setContent {
infiniteCase()
}
}
// Act like we are tearing down the test
runOnUiThread {
androidTestRule.disposeContentHook!!.invoke()
androidTestRule.disposeContentHook = null
}
// Kick of simple composition again (like if we run new test)
composeTestRule.setContent {
Text("Hello")
}
// No timeout should happen this time
onNodeWithText("Hello").assertExists()
}
private object InfiniteResource : IdlingResource {
override fun getName(): String {
return "InfiniteResource"
}
override fun isIdleNow(): Boolean {
return false
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {}
}
}