Merge changes from topic "testutils-lifecycle" into androidx-main
* changes:
Move `LifecycleOwnerUtils` to `testutils-lifecycle`
Convert `LifecycleOwnerUtils` to Kotlin
Move `FakeLifecycleOwner` to `testutils-lifecycle`
Add empty `testutils-lifecycle` module
diff --git a/appcompat/appcompat/build.gradle b/appcompat/appcompat/build.gradle
index a133dd5..2e18a39 100644
--- a/appcompat/appcompat/build.gradle
+++ b/appcompat/appcompat/build.gradle
@@ -58,6 +58,7 @@
exclude group: "androidx.lifecycle", module: "lifecycle-runtime-ktx"
})
androidTestImplementation(project(":internal-testutils-runtime"))
+ androidTestImplementation(project(":internal-testutils-lifecycle"))
androidTestImplementation(project(":internal-testutils-appcompat"), {
exclude group: "androidx.appcompat", module: "appcompat"
exclude group: "androidx.core", module: "core"
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesChangeWhenInBackground.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesChangeWhenInBackground.kt
index 140a237..047175d 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesChangeWhenInBackground.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesChangeWhenInBackground.kt
@@ -27,7 +27,7 @@
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.TestCase.assertNotSame
import org.junit.Before
import org.junit.Rule
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesForegroundDialogTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesForegroundDialogTestCase.kt
index b43260e..f705ffb 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesForegroundDialogTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesForegroundDialogTestCase.kt
@@ -25,7 +25,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.TestCase.assertNotSame
import org.junit.Before
import org.junit.Ignore
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesLateOnCreateTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesLateOnCreateTestCase.kt
index 6789203..996d45c 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesLateOnCreateTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesLateOnCreateTestCase.kt
@@ -26,7 +26,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateDoesNotRecreateActivityTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateDoesNotRecreateActivityTestCase.kt
index df74d85..6abd953 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateDoesNotRecreateActivityTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateDoesNotRecreateActivityTestCase.kt
@@ -28,7 +28,7 @@
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import org.junit.After
import org.junit.Assert.assertNotSame
import org.junit.Assert.assertSame
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateRecreatesActivityWithConfigTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateRecreatesActivityWithConfigTestCase.kt
index 74862a3..9b5f903 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateRecreatesActivityWithConfigTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesRotateRecreatesActivityWithConfigTestCase.kt
@@ -30,7 +30,7 @@
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import org.junit.After
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesStackedHandlingTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesStackedHandlingTestCase.kt
index e6dd610..23d0e79 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesStackedHandlingTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/LocalesStackedHandlingTestCase.kt
@@ -33,7 +33,7 @@
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertNotSame
import org.junit.After
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeDefaultOnlyTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeDefaultOnlyTestCase.kt
index 3cc4620..5563c84 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeDefaultOnlyTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeDefaultOnlyTestCase.kt
@@ -27,7 +27,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.TestCase.assertNotSame
import org.junit.Rule
import org.junit.Test
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeForegroundDialogTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeForegroundDialogTestCase.kt
index 2ee588c..54c95bf 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeForegroundDialogTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeForegroundDialogTestCase.kt
@@ -25,7 +25,7 @@
import androidx.lifecycle.Lifecycle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.TestCase.assertNotSame
import org.junit.Ignore
import org.junit.Rule
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeLateOnCreateTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeLateOnCreateTestCase.kt
index 736520b..dca5cdc 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeLateOnCreateTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeLateOnCreateTestCase.kt
@@ -24,7 +24,7 @@
import androidx.lifecycle.Lifecycle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModePreventOverrideConfigTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModePreventOverrideConfigTestCase.kt
index 7c7254a..12e0102 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModePreventOverrideConfigTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModePreventOverrideConfigTestCase.kt
@@ -24,7 +24,7 @@
import androidx.appcompat.testutils.NightModeUtils.setNightModeAndWaitForRecreate
import androidx.lifecycle.Lifecycle
import androidx.test.filters.LargeTest
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
index c698bba..539d258 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateDoesNotRecreateActivityTestCase.kt
@@ -30,7 +30,7 @@
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import org.junit.After
import org.junit.Assert.assertNotSame
import org.junit.Assert.assertSame
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateRecreatesActivityWithConfigTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateRecreatesActivityWithConfigTestCase.kt
index 962dfd5..e813d41 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateRecreatesActivityWithConfigTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRotateRecreatesActivityWithConfigTestCase.kt
@@ -32,7 +32,7 @@
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import org.junit.After
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeStackedHandlingTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeStackedHandlingTestCase.kt
index ceed8d6..a2a65e8 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeStackedHandlingTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeStackedHandlingTestCase.kt
@@ -32,7 +32,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertNotSame
import org.junit.Test
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestCase.kt
index b14c6ae..7333865 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestCase.kt
@@ -38,7 +38,7 @@
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitForRecreation
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitForRecreation
import androidx.testutils.waitForExecution
import java.util.concurrent.CountDownLatch
import org.junit.Assert.assertEquals
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTest.kt
index 953836e..3df5b6f 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTest.kt
@@ -24,7 +24,7 @@
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import androidx.testutils.withActivity
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.TimeUnit
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTestWithCustomDefault.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTestWithCustomDefault.kt
index 52949dc..340b0b7 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTestWithCustomDefault.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/FilternatorTestWithCustomDefault.kt
@@ -25,7 +25,7 @@
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import androidx.testutils.withActivity
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.TimeUnit
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/NavDrawerActivityTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/NavDrawerActivityTest.kt
index f72d0cf..3975a65 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/NavDrawerActivityTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/g3/NavDrawerActivityTest.kt
@@ -29,7 +29,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils.waitUntilState
+import androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/LocalesUtils.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/LocalesUtils.kt
index bad3a2a..9fbdafb 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/LocalesUtils.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/LocalesUtils.kt
@@ -25,8 +25,8 @@
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.Lifecycle
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils
import androidx.testutils.PollingCheck
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import java.util.Locale
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
index 630a1d0..633827f 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
@@ -26,8 +26,8 @@
import androidx.appcompat.app.AppCompatDelegate.NightMode
import androidx.lifecycle.Lifecycle
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.testutils.LifecycleOwnerUtils
import androidx.testutils.PollingCheck
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseViewTest.java b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseViewTest.java
index 83fa83c4..d87f8fb 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseViewTest.java
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseViewTest.java
@@ -25,7 +25,7 @@
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.testutils.LifecycleOwnerUtils.waitUntilState;
+import static androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState;
import static androidx.testutils.PollingCheck.waitFor;
import static org.junit.Assert.assertNull;
diff --git a/camera/integration-tests/coretestapp/build.gradle b/camera/integration-tests/coretestapp/build.gradle
index 4dda00a..b514d3b 100644
--- a/camera/integration-tests/coretestapp/build.gradle
+++ b/camera/integration-tests/coretestapp/build.gradle
@@ -120,6 +120,7 @@
androidTestImplementation(project(":concurrent:concurrent-futures"))
androidTestImplementation(project(":concurrent:concurrent-futures-ktx"))
androidTestImplementation(project(":internal-testutils-runtime"))
+ androidTestImplementation(project(":internal-testutils-lifecycle"))
androidTestImplementation(project(":internal-testutils-truth"))
androidTestImplementation("androidx.lifecycle:lifecycle-runtime-testing:2.3.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXServiceTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXServiceTest.kt
index 7bb399c..d65e176 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXServiceTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXServiceTest.kt
@@ -51,7 +51,7 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.LargeTest
import androidx.test.rule.GrantPermissionRule
-import androidx.testutils.LifecycleOwnerUtils
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CompletableDeferred
diff --git a/core/core/build.gradle b/core/core/build.gradle
index 5f369e5..9b69c43 100644
--- a/core/core/build.gradle
+++ b/core/core/build.gradle
@@ -59,6 +59,7 @@
androidTestImplementation(project(":internal-testutils-runtime"), {
exclude group: "androidx.core", module: "core"
})
+ androidTestImplementation(project(":internal-testutils-lifecycle"))
androidTestImplementation(project(":internal-testutils-fonts"))
androidTestImplementation(project(":internal-testutils-mockito"))
diff --git a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateFromLifecycleStatesTestCase.kt b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateFromLifecycleStatesTestCase.kt
index 7c99d87..75585d3 100644
--- a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateFromLifecycleStatesTestCase.kt
+++ b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateFromLifecycleStatesTestCase.kt
@@ -22,8 +22,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.ActivityTestRule
-import androidx.testutils.LifecycleOwnerUtils
import androidx.testutils.PollingCheck
+import androidx.testutils.lifecycle.LifecycleOwnerUtils
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import junit.framework.Assert.assertEquals
diff --git a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateTestCase.java b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateTestCase.java
index 4a7f0f3..dfeb63c 100644
--- a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateTestCase.java
+++ b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatRecreateTestCase.java
@@ -16,7 +16,7 @@
package androidx.core.app;
-import static androidx.testutils.LifecycleOwnerUtils.waitUntilState;
+import static androidx.testutils.lifecycle.LifecycleOwnerUtils.waitUntilState;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
diff --git a/lifecycle/lifecycle-runtime/build.gradle b/lifecycle/lifecycle-runtime/build.gradle
index 47432e7..cd82e0c 100644
--- a/lifecycle/lifecycle-runtime/build.gradle
+++ b/lifecycle/lifecycle-runtime/build.gradle
@@ -42,6 +42,7 @@
commonTest {
dependencies {
+ implementation(project(":internal-testutils-lifecycle"))
implementation(libs.kotlinCoroutinesTest)
implementation(libs.kotlinTest)
implementation(project(":kruth:kruth"))
@@ -61,6 +62,7 @@
}
desktopTest {
+ dependsOn(commonTest)
dependencies {
implementation(libs.kotlinCoroutinesSwing)
}
diff --git a/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/LaunchWhenTest.kt b/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/LaunchWhenTest.kt
index 332464f..c0df6da 100644
--- a/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/LaunchWhenTest.kt
+++ b/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/LaunchWhenTest.kt
@@ -18,6 +18,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
+import androidx.testutils.lifecycle.FakeLifecycleOwner
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.junit.Test
diff --git a/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/PausingDispatcherTest.kt b/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/PausingDispatcherTest.kt
index a45777d..1193f09 100644
--- a/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/PausingDispatcherTest.kt
+++ b/lifecycle/lifecycle-runtime/src/androidInstrumentedTest/kotlin/androidx/lifecycle/PausingDispatcherTest.kt
@@ -19,6 +19,7 @@
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import androidx.testutils.lifecycle.FakeLifecycleOwner
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
diff --git a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FlowWithLifecycleTest.kt b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FlowWithLifecycleTest.kt
index 112eec4..c33fd1c 100644
--- a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FlowWithLifecycleTest.kt
+++ b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FlowWithLifecycleTest.kt
@@ -17,6 +17,7 @@
package androidx.lifecycle
import androidx.kruth.assertThat
+import androidx.testutils.lifecycle.FakeLifecycleOwner
import kotlin.test.Test
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
diff --git a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/RepeatOnLifecycleTest.kt b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/RepeatOnLifecycleTest.kt
index 08220d6..af3f9dc 100644
--- a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/RepeatOnLifecycleTest.kt
+++ b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/RepeatOnLifecycleTest.kt
@@ -17,6 +17,7 @@
package androidx.lifecycle
import androidx.kruth.assertThat
+import androidx.testutils.lifecycle.FakeLifecycleOwner
import kotlin.test.Test
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineExceptionHandler
diff --git a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/WithLifecycleStateTest.kt b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/WithLifecycleStateTest.kt
index 7c7f760..039f2e5 100644
--- a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/WithLifecycleStateTest.kt
+++ b/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/WithLifecycleStateTest.kt
@@ -17,6 +17,7 @@
package androidx.lifecycle
import androidx.kruth.assertWithMessage
+import androidx.testutils.lifecycle.FakeLifecycleOwner
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
diff --git a/settings.gradle b/settings.gradle
index 5f6211e..2c98097 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1133,6 +1133,7 @@
includeProject(":internal-testutils-paging", "testutils/testutils-paging", [BuildType.MAIN, BuildType.COMPOSE])
includeProject(":internal-testutils-gradle-plugin", "testutils/testutils-gradle-plugin", [BuildType.MAIN, BuildType.FLAN, BuildType.COMPOSE, BuildType.TOOLS])
includeProject(":internal-testutils-mockito", "testutils/testutils-mockito", [BuildType.MAIN, BuildType.MEDIA, BuildType.FLAN, BuildType.COMPOSE])
+includeProject(":internal-testutils-lifecycle", "testutils/testutils-lifecycle", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN, BuildType.KMP])
includeProject(":kruth:kruth", [BuildType.MAIN, BuildType.INFRAROGUE, BuildType.KMP, BuildType.COMPOSE])
/////////////////////////////
diff --git a/testutils/testutils-lifecycle/build.gradle b/testutils/testutils-lifecycle/build.gradle
new file mode 100644
index 0000000..1da51cc
--- /dev/null
+++ b/testutils/testutils-lifecycle/build.gradle
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+/**
+ * This file was created using the `create_project.py` script located in the
+ * `<AndroidX root>/development/project-creator` directory.
+ *
+ * Please use that script when creating a new project, rather than copying an existing project and
+ * modifying its settings.
+ */
+import androidx.build.LibraryType
+import androidx.build.PlatformIdentifier
+import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+}
+
+androidXMultiplatform {
+ android()
+ desktop()
+ mac()
+ linux()
+ ios()
+
+ kotlin {
+ explicitApi = ExplicitApiMode.Strict
+ }
+
+ defaultPlatform(PlatformIdentifier.ANDROID)
+
+ sourceSets {
+ commonMain {
+ dependencies {
+ api(projectOrArtifact(":lifecycle:lifecycle-runtime"))
+ api("androidx.annotation:annotation:1.8.0")
+
+ api(libs.kotlinStdlib)
+ api(libs.kotlinCoroutinesCore)
+ api(libs.kotlinCoroutinesTest)
+ }
+ }
+
+ androidMain {
+ dependsOn(commonMain)
+ dependencies {
+ api(libs.testRules)
+ implementation(libs.testExtJunit)
+ implementation(libs.testCore)
+ }
+ }
+ }
+}
+
+android {
+ namespace "androidx.testutils.lifecycle"
+}
+
+androidx {
+ type = LibraryType.INTERNAL_TEST_LIBRARY
+}
diff --git a/testutils/testutils-lifecycle/src/androidMain/kotlin/androidx/testutils/lifecycle/LifecycleOwnerUtils.android.kt b/testutils/testutils-lifecycle/src/androidMain/kotlin/androidx/testutils/lifecycle/LifecycleOwnerUtils.android.kt
new file mode 100644
index 0000000..abddfe6
--- /dev/null
+++ b/testutils/testutils-lifecycle/src/androidMain/kotlin/androidx/testutils/lifecycle/LifecycleOwnerUtils.android.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2019 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.testutils.lifecycle
+
+import android.app.Activity
+import android.app.Instrumentation.ActivityMonitor
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.test.platform.app.InstrumentationRegistry
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import org.hamcrest.CoreMatchers
+import org.hamcrest.MatcherAssert
+
+/** Utility methods for testing LifecycleOwners */
+public object LifecycleOwnerUtils {
+
+ private const val TIMEOUT_MS: Long = 5000
+
+ private val DO_NOTHING = Runnable {}
+
+ /**
+ * Waits until the given [LifecycleOwner] has the specified
+ * [androidx.lifecycle.Lifecycle.State]. If the owner has not hit that state within a suitable
+ * time period, it asserts that the current state equals the given state.
+ */
+ @JvmStatic
+ @Throws(Throwable::class)
+ public fun waitUntilState(owner: LifecycleOwner, state: Lifecycle.State) {
+ if (owner.lifecycle.currentState == state) {
+ return
+ }
+
+ val instrumentation = InstrumentationRegistry.getInstrumentation()
+ val latch = CountDownLatch(1)
+
+ instrumentation.runOnMainSync {
+ if (owner.lifecycle.currentState == state) {
+ latch.countDown()
+ return@runOnMainSync
+ }
+
+ val observer =
+ object : LifecycleEventObserver {
+ override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+ if (source.lifecycle.currentState == state) {
+ source.lifecycle.removeObserver(this)
+ latch.countDown()
+ }
+ }
+ }
+
+ owner.lifecycle.addObserver(observer)
+ }
+
+ val isCountZero = latch.await(15, TimeUnit.SECONDS)
+ MatcherAssert.assertThat(
+ "Expected state $state never happened to $owner. " +
+ "Current state: ${owner.lifecycle.currentState}",
+ isCountZero,
+ CoreMatchers.`is`(true)
+ )
+
+ // wait for another loop to ensure all observers are called
+ instrumentation.runOnMainSync(DO_NOTHING)
+ }
+
+ /**
+ * Waits until the given the current [Activity] has been recreated, and the new instance is
+ * resumed.
+ */
+ @Throws(Throwable::class)
+ public fun <T> waitForRecreation(
+ @Suppress("deprecation") activityRule: androidx.test.rule.ActivityTestRule<T>
+ ): T where T : Activity, T : LifecycleOwner {
+ return waitForRecreation(activityRule.activity)
+ }
+
+ /**
+ * Waits until the given the given [Activity] has been recreated, and the new instance is
+ * resumed.
+ */
+ @Throws(Throwable::class)
+ public fun <T> waitForRecreation(activity: T): T where T : Activity, T : LifecycleOwner {
+ return waitForRecreation(activity, null)
+ }
+
+ /**
+ * Waits until the given [Activity] and [LifecycleOwner] has been recreated, and the new
+ * instance is resumed.
+ */
+ @Throws(Throwable::class)
+ public fun <T> waitForRecreation(activity: T, actionOnUiThread: Runnable?): T where
+ T : Activity,
+ T : LifecycleOwner {
+ val monitor = ActivityMonitor(activity::class.qualifiedName, null, false)
+ val instrumentation = InstrumentationRegistry.getInstrumentation()
+ instrumentation.addMonitor(monitor)
+
+ if (actionOnUiThread != null) {
+ instrumentation.runOnMainSync(actionOnUiThread)
+ }
+
+ // Wait for the old activity to be destroyed. This helps avoid flakiness on test devices
+ // (ex. API 26) where the system takes a long time to go from STOPPED to DESTROYED.
+ waitUntilState(activity, Lifecycle.State.DESTROYED)
+
+ var recreatedActivity: T
+
+ // this guarantee that we will reinstall monitor between notifications about onDestroy
+ // and onCreate
+ // noinspection SynchronizationOnLocalVariableOrMethodParameter
+ try {
+ synchronized(monitor) {
+ do {
+ // The documentation says "Block until an Activity is created
+ // that matches this monitor." This statement is true, but there are some other
+ // true statements like: "Block until an Activity is destroyed" or
+ // "Block until an Activity is resumed"...
+ // this call will release synchronization monitor's monitor
+ @Suppress("UNCHECKED_CAST")
+ recreatedActivity =
+ monitor.waitForActivityWithTimeout(TIMEOUT_MS) as? T
+ ?: throw RuntimeException("Timeout. Activity was not recreated.")
+ } while (recreatedActivity == activity)
+ }
+ } finally {
+ instrumentation.removeMonitor(monitor)
+ }
+
+ // Finally wait for the recreated Activity to be resumed
+ waitUntilState(recreatedActivity, Lifecycle.State.RESUMED)
+
+ return recreatedActivity
+ }
+}
diff --git a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FakeLifecycleOwner.kt b/testutils/testutils-lifecycle/src/commonMain/kotlin/androidx/testutils/lifecycle/FakeLifecycleOwner.kt
similarity index 85%
rename from lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FakeLifecycleOwner.kt
rename to testutils/testutils-lifecycle/src/commonMain/kotlin/androidx/testutils/lifecycle/FakeLifecycleOwner.kt
index 60ace27..bdbb587 100644
--- a/lifecycle/lifecycle-runtime/src/commonTest/kotlin/androidx/lifecycle/FakeLifecycleOwner.kt
+++ b/testutils/testutils-lifecycle/src/commonMain/kotlin/androidx/testutils/lifecycle/FakeLifecycleOwner.kt
@@ -14,17 +14,22 @@
* limitations under the License.
*/
-package androidx.lifecycle
+package androidx.testutils.lifecycle
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withContext
public class FakeLifecycleOwner(initialState: Lifecycle.State? = null) : LifecycleOwner {
- private val registry: LifecycleRegistry = LifecycleRegistry.createUnsafe(this)
+
+ private val registry: LifecycleRegistry = LifecycleRegistry.createUnsafe(owner = this)
init {
- initialState?.let { setState(it) }
+ if (initialState != null) {
+ setState(initialState)
+ }
}
override val lifecycle: Lifecycle
@@ -53,8 +58,4 @@
public fun resume() {
runBlocking(Dispatchers.Main) { setState(Lifecycle.State.RESUMED) }
}
-
- private suspend fun getObserverCount(): Int {
- return withContext(Dispatchers.Main) { registry.observerCount }
- }
}
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java b/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java
deleted file mode 100644
index 9b1b6d5..0000000
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2019 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.testutils;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Utility methods for testing LifecycleOwners
- */
-public class LifecycleOwnerUtils {
- private static final long TIMEOUT_MS = 5000;
-
- private static final Runnable DO_NOTHING = new Runnable() {
- @Override
- public void run() {
- }
- };
-
- /**
- * Waits until the given {@link LifecycleOwner} has the specified
- * {@link androidx.lifecycle.Lifecycle.State}. If the owner has not hit that state within a
- * suitable time period, it asserts that the current state equals the given state.
- */
- public static void waitUntilState(final @NonNull LifecycleOwner owner,
- final @NonNull Lifecycle.State state) throws Throwable {
- final Lifecycle.State currentState = owner.getLifecycle().getCurrentState();
- if (currentState == state) {
- return;
- }
-
- final CountDownLatch latch = new CountDownLatch(1);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- final Lifecycle.State currentState = owner.getLifecycle().getCurrentState();
- if (currentState == state) {
- latch.countDown();
- return;
- }
- owner.getLifecycle().addObserver(new LifecycleEventObserver() {
- @Override
- public void onStateChanged(@NonNull LifecycleOwner provider,
- @NonNull Lifecycle.Event event) {
- if (provider.getLifecycle().getCurrentState() == state) {
- provider.getLifecycle().removeObserver(this);
- latch.countDown();
- }
- }
- });
- }
- });
- final boolean latchResult = latch.await(15, TimeUnit.SECONDS);
-
- assertThat("Expected " + state + " never happened to " + owner
- + ". Current state:" + owner.getLifecycle().getCurrentState(),
- latchResult,
- is(true));
-
- // wait for another loop to ensure all observers are called
- InstrumentationRegistry.getInstrumentation().runOnMainSync(DO_NOTHING);
- }
-
- /**
- * Waits until the given the current {@link Activity} has been recreated, and
- * the new instance is resumed.
- */
- @NonNull
- public static <T extends Activity & LifecycleOwner> T waitForRecreation(
- @SuppressWarnings("deprecation")
- @NonNull final androidx.test.rule.ActivityTestRule<T> activityRule
- ) throws Throwable {
- return waitForRecreation(activityRule.getActivity());
- }
-
- /**
- * Waits until the given the given {@link Activity} has been recreated, and
- * the new instance is resumed.
- */
- @NonNull
- public static <T extends Activity & LifecycleOwner> T waitForRecreation(
- @NonNull final T activity
- ) throws Throwable {
- return waitForRecreation(activity, null);
- }
-
- /**
- * Waits until the given {@link Activity} and {@link LifecycleOwner} has been recreated, and
- * the new instance is resumed.
- */
- @SuppressWarnings("unchecked")
- @NonNull
- public static <T extends Activity & LifecycleOwner> T waitForRecreation(
- @NonNull final T activity,
- @Nullable final Runnable actionOnUiThread
- ) throws Throwable {
- final Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
- activity.getClass().getName(), null, false);
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- instrumentation.addMonitor(monitor);
-
- if (actionOnUiThread != null) {
- instrumentation.runOnMainSync(actionOnUiThread);
- }
-
- // Wait for the old activity to be destroyed. This helps avoid flakiness on test devices
- // (ex. API 26) where the system takes a long time to go from STOPPED to DESTROYED.
- waitUntilState(activity, Lifecycle.State.DESTROYED);
-
- T result;
-
- // this guarantee that we will reinstall monitor between notifications about onDestroy
- // and onCreate
- // noinspection SynchronizationOnLocalVariableOrMethodParameter
- try {
- synchronized (monitor) {
- do {
- // The documentation says "Block until an Activity is created
- // that matches this monitor." This statement is true, but there are some other
- // true statements like: "Block until an Activity is destroyed" or
- // "Block until an Activity is resumed"...
- // this call will release synchronization monitor's monitor
- result = (T) monitor.waitForActivityWithTimeout(TIMEOUT_MS);
- if (result == null) {
- throw new RuntimeException("Timeout. Activity was not recreated.");
- }
- } while (result == activity);
- }
- } finally {
- instrumentation.removeMonitor(monitor);
- }
-
- // Finally wait for the recreated Activity to be resumed
- waitUntilState(result, Lifecycle.State.RESUMED);
-
- return result;
- }
-
- private LifecycleOwnerUtils() {
- }
-}