summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt319
1 files changed, 181 insertions, 138 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
index 91a6de6ae4c0..ea11f01ed580 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.lifecycle
-import android.testing.TestableLooper.RunWithLooper
import android.view.View
import android.view.ViewTreeObserver
import androidx.lifecycle.Lifecycle
@@ -28,8 +27,16 @@ import com.android.systemui.util.Assert
import com.android.systemui.util.mockito.argumentCaptor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -41,9 +48,9 @@ import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
-@RunWithLooper
class RepeatWhenAttachedTest : SysuiTestCase() {
@JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -54,9 +61,13 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
private lateinit var block: Block
private lateinit var attachListeners: MutableList<View.OnAttachStateChangeListener>
+ private lateinit var testScope: TestScope
@Before
fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+ Dispatchers.setMain(testDispatcher)
Assert.setTestThread(Thread.currentThread())
whenever(view.viewTreeObserver).thenReturn(viewTreeObserver)
whenever(view.windowVisibility).thenReturn(View.GONE)
@@ -71,186 +82,218 @@ class RepeatWhenAttachedTest : SysuiTestCase() {
block = Block()
}
- @Test(expected = IllegalStateException::class)
- fun `repeatWhenAttached - enforces main thread`() = runBlockingTest {
- Assert.setTestThread(null)
-
- repeatWhenAttached()
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
}
@Test(expected = IllegalStateException::class)
- fun `repeatWhenAttached - dispose enforces main thread`() = runBlockingTest {
- val disposableHandle = repeatWhenAttached()
- Assert.setTestThread(null)
+ fun `repeatWhenAttached - enforces main thread`() =
+ testScope.runTest {
+ Assert.setTestThread(null)
- disposableHandle.dispose()
- }
-
- @Test
- fun `repeatWhenAttached - view starts detached - runs block when attached`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(false)
- repeatWhenAttached()
- assertThat(block.invocationCount).isEqualTo(0)
+ repeatWhenAttached()
+ }
- whenever(view.isAttachedToWindow).thenReturn(true)
- attachListeners.last().onViewAttachedToWindow(view)
+ @Test(expected = IllegalStateException::class)
+ fun `repeatWhenAttached - dispose enforces main thread`() =
+ testScope.runTest {
+ val disposableHandle = repeatWhenAttached()
+ Assert.setTestThread(null)
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
- }
+ disposableHandle.dispose()
+ }
@Test
- fun `repeatWhenAttached - view already attached - immediately runs block`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
-
- repeatWhenAttached()
-
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
- }
+ fun `repeatWhenAttached - view starts detached - runs block when attached`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ repeatWhenAttached()
+ assertThat(block.invocationCount).isEqualTo(0)
+
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ attachListeners.last().onViewAttachedToWindow(view)
+
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
+ }
@Test
- fun `repeatWhenAttached - starts visible without focus - STARTED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ fun `repeatWhenAttached - view already attached - immediately runs block`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
+ repeatWhenAttached()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED)
- }
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
+ }
@Test
- fun `repeatWhenAttached - starts with focus but invisible - CREATED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- whenever(view.hasWindowFocus()).thenReturn(true)
+ fun `repeatWhenAttached - starts visible without focus - STARTED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- repeatWhenAttached()
+ repeatWhenAttached()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
- }
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED)
+ }
@Test
- fun `repeatWhenAttached - starts visible and with focus - RESUMED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- whenever(view.hasWindowFocus()).thenReturn(true)
+ fun `repeatWhenAttached - starts with focus but invisible - CREATED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.hasWindowFocus()).thenReturn(true)
- repeatWhenAttached()
+ repeatWhenAttached()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED)
- }
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
+ }
@Test
- fun `repeatWhenAttached - becomes visible without focus - STARTED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
- val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>()
- verify(viewTreeObserver).addOnWindowVisibilityChangeListener(listenerCaptor.capture())
+ fun `repeatWhenAttached - starts visible and with focus - RESUMED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ whenever(view.hasWindowFocus()).thenReturn(true)
- whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
+ repeatWhenAttached()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED)
- }
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED)
+ }
@Test
- fun `repeatWhenAttached - gains focus but invisible - CREATED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
- val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>()
- verify(viewTreeObserver).addOnWindowFocusChangeListener(listenerCaptor.capture())
-
- whenever(view.hasWindowFocus()).thenReturn(true)
- listenerCaptor.value.onWindowFocusChanged(true)
+ fun `repeatWhenAttached - becomes visible without focus - STARTED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ repeatWhenAttached()
+ val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>()
+ verify(viewTreeObserver).addOnWindowVisibilityChangeListener(listenerCaptor.capture())
+
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
+
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED)
+ }
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
- }
+ @Test
+ fun `repeatWhenAttached - gains focus but invisible - CREATED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ repeatWhenAttached()
+ val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>()
+ verify(viewTreeObserver).addOnWindowFocusChangeListener(listenerCaptor.capture())
+
+ whenever(view.hasWindowFocus()).thenReturn(true)
+ listenerCaptor.value.onWindowFocusChanged(true)
+
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED)
+ }
@Test
- fun `repeatWhenAttached - becomes visible and gains focus - RESUMED`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
- val visibleCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>()
- verify(viewTreeObserver).addOnWindowVisibilityChangeListener(visibleCaptor.capture())
- val focusCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>()
- verify(viewTreeObserver).addOnWindowFocusChangeListener(focusCaptor.capture())
-
- whenever(view.windowVisibility).thenReturn(View.VISIBLE)
- visibleCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
- whenever(view.hasWindowFocus()).thenReturn(true)
- focusCaptor.value.onWindowFocusChanged(true)
-
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED)
- }
+ fun `repeatWhenAttached - becomes visible and gains focus - RESUMED`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ repeatWhenAttached()
+ val visibleCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>()
+ verify(viewTreeObserver).addOnWindowVisibilityChangeListener(visibleCaptor.capture())
+ val focusCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>()
+ verify(viewTreeObserver).addOnWindowFocusChangeListener(focusCaptor.capture())
+
+ whenever(view.windowVisibility).thenReturn(View.VISIBLE)
+ visibleCaptor.value.onWindowVisibilityChanged(View.VISIBLE)
+ whenever(view.hasWindowFocus()).thenReturn(true)
+ focusCaptor.value.onWindowFocusChanged(true)
+
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED)
+ }
@Test
- fun `repeatWhenAttached - view gets detached - destroys the lifecycle`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
+ fun `repeatWhenAttached - view gets detached - destroys the lifecycle`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ repeatWhenAttached()
- whenever(view.isAttachedToWindow).thenReturn(false)
- attachListeners.last().onViewDetachedFromWindow(view)
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ attachListeners.last().onViewDetachedFromWindow(view)
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
- }
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
+ }
@Test
- fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- repeatWhenAttached()
- whenever(view.isAttachedToWindow).thenReturn(false)
- attachListeners.last().onViewDetachedFromWindow(view)
-
- whenever(view.isAttachedToWindow).thenReturn(true)
- attachListeners.last().onViewAttachedToWindow(view)
-
- assertThat(block.invocationCount).isEqualTo(2)
- assertThat(block.invocations[0].lifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
- assertThat(block.invocations[1].lifecycleState).isEqualTo(Lifecycle.State.CREATED)
- }
+ fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ repeatWhenAttached()
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ attachListeners.last().onViewDetachedFromWindow(view)
+
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ attachListeners.last().onViewAttachedToWindow(view)
+
+ runCurrent()
+ assertThat(block.invocationCount).isEqualTo(2)
+ assertThat(block.invocations[0].lifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
+ assertThat(block.invocations[1].lifecycleState).isEqualTo(Lifecycle.State.CREATED)
+ }
@Test
- fun `repeatWhenAttached - dispose attached`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- val handle = repeatWhenAttached()
+ fun `repeatWhenAttached - dispose attached`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ val handle = repeatWhenAttached()
- handle.dispose()
+ handle.dispose()
- assertThat(attachListeners).isEmpty()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
- }
+ runCurrent()
+ assertThat(attachListeners).isEmpty()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
+ }
@Test
- fun `repeatWhenAttached - dispose never attached`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(false)
- val handle = repeatWhenAttached()
+ fun `repeatWhenAttached - dispose never attached`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(false)
+ val handle = repeatWhenAttached()
- handle.dispose()
+ handle.dispose()
- assertThat(attachListeners).isEmpty()
- assertThat(block.invocationCount).isEqualTo(0)
- }
+ assertThat(attachListeners).isEmpty()
+ assertThat(block.invocationCount).isEqualTo(0)
+ }
@Test
- fun `repeatWhenAttached - dispose previously attached now detached`() = runBlockingTest {
- whenever(view.isAttachedToWindow).thenReturn(true)
- val handle = repeatWhenAttached()
- attachListeners.last().onViewDetachedFromWindow(view)
-
- handle.dispose()
-
- assertThat(attachListeners).isEmpty()
- assertThat(block.invocationCount).isEqualTo(1)
- assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
- }
+ fun `repeatWhenAttached - dispose previously attached now detached`() =
+ testScope.runTest {
+ whenever(view.isAttachedToWindow).thenReturn(true)
+ val handle = repeatWhenAttached()
+ attachListeners.last().onViewDetachedFromWindow(view)
+
+ handle.dispose()
+
+ runCurrent()
+ assertThat(attachListeners).isEmpty()
+ assertThat(block.invocationCount).isEqualTo(1)
+ assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED)
+ }
private fun CoroutineScope.repeatWhenAttached(): DisposableHandle {
return view.repeatWhenAttached(