Loading packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt +181 −138 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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() Loading @@ -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) Loading @@ -71,15 +82,22 @@ class RepeatWhenAttachedTest : SysuiTestCase() { block = Block() } @After fun tearDown() { Dispatchers.resetMain() } @Test(expected = IllegalStateException::class) fun `repeatWhenAttached - enforces main thread`() = runBlockingTest { fun `repeatWhenAttached - enforces main thread`() = testScope.runTest { Assert.setTestThread(null) repeatWhenAttached() } @Test(expected = IllegalStateException::class) fun `repeatWhenAttached - dispose enforces main thread`() = runBlockingTest { fun `repeatWhenAttached - dispose enforces main thread`() = testScope.runTest { val disposableHandle = repeatWhenAttached() Assert.setTestThread(null) Loading @@ -87,7 +105,8 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test fun `repeatWhenAttached - view starts detached - runs block when attached`() = runBlockingTest { fun `repeatWhenAttached - view starts detached - runs block when attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(false) repeatWhenAttached() assertThat(block.invocationCount).isEqualTo(0) Loading @@ -95,56 +114,66 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 - view already attached - immediately runs block`() = runBlockingTest { fun `repeatWhenAttached - view already attached - immediately runs block`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED) } @Test fun `repeatWhenAttached - starts visible without focus - STARTED`() = runBlockingTest { fun `repeatWhenAttached - starts visible without focus - STARTED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) whenever(view.windowVisibility).thenReturn(View.VISIBLE) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED) } @Test fun `repeatWhenAttached - starts with focus but invisible - CREATED`() = runBlockingTest { fun `repeatWhenAttached - starts with focus but invisible - CREATED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) whenever(view.hasWindowFocus()).thenReturn(true) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED) } @Test fun `repeatWhenAttached - starts visible and with focus - RESUMED`() = runBlockingTest { 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) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED) } @Test fun `repeatWhenAttached - becomes visible without focus - STARTED`() = runBlockingTest { fun `repeatWhenAttached - becomes visible without focus - STARTED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>() Loading @@ -153,12 +182,14 @@ class RepeatWhenAttachedTest : SysuiTestCase() { whenever(view.windowVisibility).thenReturn(View.VISIBLE) listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE) runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED) } @Test fun `repeatWhenAttached - gains focus but invisible - CREATED`() = runBlockingTest { fun `repeatWhenAttached - gains focus but invisible - CREATED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>() Loading @@ -167,12 +198,14 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { fun `repeatWhenAttached - becomes visible and gains focus - RESUMED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val visibleCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>() Loading @@ -185,24 +218,28 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { 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) runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED) } @Test fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() = runBlockingTest { fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() whenever(view.isAttachedToWindow).thenReturn(false) Loading @@ -211,25 +248,29 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { fun `repeatWhenAttached - dispose attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) val handle = repeatWhenAttached() handle.dispose() runCurrent() assertThat(attachListeners).isEmpty() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED) } @Test fun `repeatWhenAttached - dispose never attached`() = runBlockingTest { fun `repeatWhenAttached - dispose never attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(false) val handle = repeatWhenAttached() Loading @@ -240,13 +281,15 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test fun `repeatWhenAttached - dispose previously attached now detached`() = runBlockingTest { 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) Loading Loading
packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt +181 −138 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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() Loading @@ -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) Loading @@ -71,15 +82,22 @@ class RepeatWhenAttachedTest : SysuiTestCase() { block = Block() } @After fun tearDown() { Dispatchers.resetMain() } @Test(expected = IllegalStateException::class) fun `repeatWhenAttached - enforces main thread`() = runBlockingTest { fun `repeatWhenAttached - enforces main thread`() = testScope.runTest { Assert.setTestThread(null) repeatWhenAttached() } @Test(expected = IllegalStateException::class) fun `repeatWhenAttached - dispose enforces main thread`() = runBlockingTest { fun `repeatWhenAttached - dispose enforces main thread`() = testScope.runTest { val disposableHandle = repeatWhenAttached() Assert.setTestThread(null) Loading @@ -87,7 +105,8 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test fun `repeatWhenAttached - view starts detached - runs block when attached`() = runBlockingTest { fun `repeatWhenAttached - view starts detached - runs block when attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(false) repeatWhenAttached() assertThat(block.invocationCount).isEqualTo(0) Loading @@ -95,56 +114,66 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 - view already attached - immediately runs block`() = runBlockingTest { fun `repeatWhenAttached - view already attached - immediately runs block`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED) } @Test fun `repeatWhenAttached - starts visible without focus - STARTED`() = runBlockingTest { fun `repeatWhenAttached - starts visible without focus - STARTED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) whenever(view.windowVisibility).thenReturn(View.VISIBLE) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED) } @Test fun `repeatWhenAttached - starts with focus but invisible - CREATED`() = runBlockingTest { fun `repeatWhenAttached - starts with focus but invisible - CREATED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) whenever(view.hasWindowFocus()).thenReturn(true) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.CREATED) } @Test fun `repeatWhenAttached - starts visible and with focus - RESUMED`() = runBlockingTest { 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) repeatWhenAttached() runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.RESUMED) } @Test fun `repeatWhenAttached - becomes visible without focus - STARTED`() = runBlockingTest { fun `repeatWhenAttached - becomes visible without focus - STARTED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>() Loading @@ -153,12 +182,14 @@ class RepeatWhenAttachedTest : SysuiTestCase() { whenever(view.windowVisibility).thenReturn(View.VISIBLE) listenerCaptor.value.onWindowVisibilityChanged(View.VISIBLE) runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.STARTED) } @Test fun `repeatWhenAttached - gains focus but invisible - CREATED`() = runBlockingTest { fun `repeatWhenAttached - gains focus but invisible - CREATED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val listenerCaptor = argumentCaptor<ViewTreeObserver.OnWindowFocusChangeListener>() Loading @@ -167,12 +198,14 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { fun `repeatWhenAttached - becomes visible and gains focus - RESUMED`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() val visibleCaptor = argumentCaptor<ViewTreeObserver.OnWindowVisibilityChangeListener>() Loading @@ -185,24 +218,28 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { 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) runCurrent() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED) } @Test fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() = runBlockingTest { fun `repeatWhenAttached - view gets reattached - recreates a lifecycle`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) repeatWhenAttached() whenever(view.isAttachedToWindow).thenReturn(false) Loading @@ -211,25 +248,29 @@ class RepeatWhenAttachedTest : SysuiTestCase() { 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 { fun `repeatWhenAttached - dispose attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(true) val handle = repeatWhenAttached() handle.dispose() runCurrent() assertThat(attachListeners).isEmpty() assertThat(block.invocationCount).isEqualTo(1) assertThat(block.latestLifecycleState).isEqualTo(Lifecycle.State.DESTROYED) } @Test fun `repeatWhenAttached - dispose never attached`() = runBlockingTest { fun `repeatWhenAttached - dispose never attached`() = testScope.runTest { whenever(view.isAttachedToWindow).thenReturn(false) val handle = repeatWhenAttached() Loading @@ -240,13 +281,15 @@ class RepeatWhenAttachedTest : SysuiTestCase() { } @Test fun `repeatWhenAttached - dispose previously attached now detached`() = runBlockingTest { 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) Loading