diff --git a/build.gradle.kts b/build.gradle.kts index b9a22bae0..8de919c3e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -368,5 +368,10 @@ extensions.configure<ApiValidationExtension> { /** * Sub-projects that are excluded from API validation */ - ignoredProjects = mutableSetOf("dispatch-internal-test", "dispatch-sample", "samples") + ignoredProjects = mutableSetOf( + "dispatch-internal-test", + "dispatch-internal-test-android", + "dispatch-sample", + "samples" + ) } diff --git a/buildSrc/src/main/kotlin/Modules.kt b/buildSrc/src/main/kotlin/Modules.kt index 3f95974fc..6609d369a 100644 --- a/buildSrc/src/main/kotlin/Modules.kt +++ b/buildSrc/src/main/kotlin/Modules.kt @@ -31,14 +31,15 @@ object Modules { ":dispatch-core:samples", ":dispatch-detekt", ":dispatch-internal-test", + ":dispatch-internal-test-android", ":dispatch-sample", - "dispatch-test", - "dispatch-test-junit4", - "dispatch-test-junit4:samples", - "dispatch-test-junit5", - "dispatch-test-junit5:samples", - "dispatch-test:samples", - "dispatch-test:samples" + ":dispatch-test", + ":dispatch-test-junit4", + ":dispatch-test-junit4:samples", + ":dispatch-test-junit5", + ":dispatch-test-junit5:samples", + ":dispatch-test:samples", + ":dispatch-test:samples" ) val allInternalPaths = allPaths.filter { it.matches(internalRegex) } val allProductionPaths = allPaths.filter { !it.matches(internalRegex, sampleRegex) } diff --git a/dispatch-android-lifecycle-extensions/samples/build.gradle.kts b/dispatch-android-lifecycle-extensions/samples/build.gradle.kts index 06ca1fb38..35a2cbdaf 100644 --- a/dispatch-android-lifecycle-extensions/samples/build.gradle.kts +++ b/dispatch-android-lifecycle-extensions/samples/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { implementation(project(":dispatch-android-lifecycle")) implementation(project(":dispatch-android-lifecycle-extensions")) implementation(project(":dispatch-core")) + implementation(project(":dispatch-internal-test-android")) implementation(project(":dispatch-test")) implementation(project(":dispatch-test-junit5")) testImplementation(Libs.JUnit.jUnit5) diff --git a/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/Fragment.kt b/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/Fragment.kt index d971bd474..3f73d824a 100644 --- a/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/Fragment.kt +++ b/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/Fragment.kt @@ -17,6 +17,7 @@ package samples import androidx.lifecycle.* +import dispatch.internal.test.android.* abstract class Fragment( initialState: Lifecycle.State = Lifecycle.State.INITIALIZED diff --git a/dispatch-android-lifecycle/samples/build.gradle.kts b/dispatch-android-lifecycle/samples/build.gradle.kts index 0f8cf4244..837179a8d 100644 --- a/dispatch-android-lifecycle/samples/build.gradle.kts +++ b/dispatch-android-lifecycle/samples/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { implementation(project(":dispatch-android-lifecycle")) implementation(project(":dispatch-android-lifecycle-extensions")) implementation(project(":dispatch-core")) + implementation(project(":dispatch-internal-test-android")) implementation(project(":dispatch-test")) implementation(project(":dispatch-test-junit5")) testImplementation(Libs.JUnit.jUnit5) diff --git a/dispatch-android-lifecycle/samples/src/test/java/samples/FakeLifecycleOwner.kt b/dispatch-android-lifecycle/samples/src/test/java/samples/FakeLifecycleOwner.kt deleted file mode 100644 index f9cceec29..000000000 --- a/dispatch-android-lifecycle/samples/src/test/java/samples/FakeLifecycleOwner.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2020 Rick Busarow - * 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 samples - -import androidx.lifecycle.* -import kotlinx.coroutines.* - -@Suppress("EXPERIMENTAL_API_USAGE") -open class FakeLifecycleOwner( - private val mainDispatcher: CoroutineDispatcher = fakeMainDispatcher(), - initialState: Lifecycle.State = Lifecycle.State.INITIALIZED -) : LifecycleOwner { - - private val registry: LifecycleRegistry by lazy { LifecycleRegistry(this) } - - init { - when (initialState) { - Lifecycle.State.DESTROYED -> destroy() - Lifecycle.State.CREATED -> create() - Lifecycle.State.STARTED -> start() - Lifecycle.State.RESUMED -> resume() - else -> Unit - } - } - - override fun getLifecycle(): LifecycleRegistry = registry - - fun create() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) - } - - fun start() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START) - } - - fun resume() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) - } - - fun pause() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) - } - - fun stop() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP) - } - - fun initialize() = runBlocking(mainDispatcher) { - lifecycle.currentState = Lifecycle.State.INITIALIZED - } - - fun destroy() = runBlocking(mainDispatcher) { - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY) - } - - fun getObserverCount(): Int = runBlocking(mainDispatcher) { registry.observerCount } -} - -@Suppress("EXPERIMENTAL_API_USAGE") -private fun fakeMainDispatcher() = newSingleThreadContext("FakeLifecycleOwner main") diff --git a/dispatch-android-lifecycle/samples/src/test/java/samples/Fragment.kt b/dispatch-android-lifecycle/samples/src/test/java/samples/Fragment.kt index d971bd474..3f73d824a 100644 --- a/dispatch-android-lifecycle/samples/src/test/java/samples/Fragment.kt +++ b/dispatch-android-lifecycle/samples/src/test/java/samples/Fragment.kt @@ -17,6 +17,7 @@ package samples import androidx.lifecycle.* +import dispatch.internal.test.android.* abstract class Fragment( initialState: Lifecycle.State = Lifecycle.State.INITIALIZED diff --git a/dispatch-internal-test-android/build.gradle.kts b/dispatch-internal-test-android/build.gradle.kts new file mode 100644 index 000000000..a1efd7642 --- /dev/null +++ b/dispatch-internal-test-android/build.gradle.kts @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 Rick Busarow + * 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. + */ + +plugins { + id(Plugins.androidLibrary) + id(Plugins.kotlinAndroid) + id(Plugins.kotlinAndroidExtensions) +} + +android { + compileSdkVersion(Versions.compileSdk) + + defaultConfig { + minSdkVersion(Versions.minSdk) + targetSdkVersion(Versions.targetSdk) + versionName = Versions.versionName + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } +} +dependencies { + implementation(Libs.AndroidX.Fragment.core) + implementation(Libs.AndroidX.Lifecycle.common) + implementation(Libs.AndroidX.Lifecycle.runtime) + implementation(Libs.Kotlin.reflect) + implementation(Libs.Kotlin.stdlib) + implementation(Libs.Kotlinx.Coroutines.android) + implementation(Libs.Kotlinx.Coroutines.core) +} diff --git a/dispatch-internal-test-android/src/main/AndroidManifest.xml b/dispatch-internal-test-android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..ef707610b --- /dev/null +++ b/dispatch-internal-test-android/src/main/AndroidManifest.xml @@ -0,0 +1,16 @@ +<!-- + ~ Copyright (C) 2020 Rick Busarow + ~ 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. + --> + +<manifest package="dispatch.internal.test.android" /> diff --git a/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeFragment.java b/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeFragment.java new file mode 100644 index 000000000..28847084c --- /dev/null +++ b/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeFragment.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 Rick Busarow + * 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 dispatch.internal.test.android; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import org.jetbrains.annotations.Nullable; + +public class FakeFragment extends Fragment { + + LifecycleOwner fragmentLifecycleOwner; + MutableLiveData<LifecycleOwner> fakeViewLifecycleOwnerLiveData = new MutableLiveData<>(null); + private LifecycleOwner fakeViewLifecycleOwner = null; + + public FakeFragment(LifecycleOwner fragmentLifecycleOwner) { + this.fragmentLifecycleOwner = fragmentLifecycleOwner; + } + + public void setFakeViewLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) { + fakeViewLifecycleOwner = lifecycleOwner; + fakeViewLifecycleOwnerLiveData.postValue(lifecycleOwner); + } + + @NonNull + @Override + public LifecycleOwner getViewLifecycleOwner() { + return fakeViewLifecycleOwner; + } + + @NonNull + @Override + public LiveData<LifecycleOwner> getViewLifecycleOwnerLiveData() { + return fakeViewLifecycleOwnerLiveData; + } + + @NonNull + @Override + public Lifecycle getLifecycle() { + return fragmentLifecycleOwner.getLifecycle(); + } + +} diff --git a/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/FakeLifecycleOwner.kt b/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeLifecycleOwner.kt similarity index 71% rename from dispatch-android-lifecycle-extensions/samples/src/test/java/samples/FakeLifecycleOwner.kt rename to dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeLifecycleOwner.kt index f9cceec29..4d6d1003d 100644 --- a/dispatch-android-lifecycle-extensions/samples/src/test/java/samples/FakeLifecycleOwner.kt +++ b/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeLifecycleOwner.kt @@ -13,15 +13,15 @@ * limitations under the License. */ -package samples +package dispatch.internal.test.android import androidx.lifecycle.* import kotlinx.coroutines.* @Suppress("EXPERIMENTAL_API_USAGE") open class FakeLifecycleOwner( - private val mainDispatcher: CoroutineDispatcher = fakeMainDispatcher(), - initialState: Lifecycle.State = Lifecycle.State.INITIALIZED + initialState: Lifecycle.State = Lifecycle.State.INITIALIZED, + private val mainDispatcher: CoroutineDispatcher = fakeMainDispatcher() ) : LifecycleOwner { private val registry: LifecycleRegistry by lazy { LifecycleRegistry(this) } @@ -38,6 +38,24 @@ open class FakeLifecycleOwner( override fun getLifecycle(): LifecycleRegistry = registry + fun stepDown() = when (lifecycle.currentState) { + Lifecycle.State.DESTROYED -> throw IllegalArgumentException("already destroyed") + Lifecycle.State.INITIALIZED -> throw IllegalArgumentException( + "cannot transition straight from initialized to destroyed" + ) + Lifecycle.State.CREATED -> destroy() + Lifecycle.State.STARTED -> stop() + Lifecycle.State.RESUMED -> pause() + } + + fun stepUp() = when (lifecycle.currentState) { + Lifecycle.State.DESTROYED -> throw IllegalArgumentException("already destroyed") + Lifecycle.State.INITIALIZED -> create() + Lifecycle.State.CREATED -> start() + Lifecycle.State.STARTED -> resume() + Lifecycle.State.RESUMED -> throw IllegalArgumentException("already resumed") + } + fun create() = runBlocking(mainDispatcher) { lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) } diff --git a/dispatch-internal-test-android/src/test/resources/junit-platform.properties b/dispatch-internal-test-android/src/test/resources/junit-platform.properties new file mode 100644 index 000000000..0e863bea1 --- /dev/null +++ b/dispatch-internal-test-android/src/test/resources/junit-platform.properties @@ -0,0 +1,15 @@ +# +# Copyright (C) 2020 Rick Busarow +# 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. +# +junit.jupiter.testinstance.lifecycle.default=per_class diff --git a/settings.gradle.kts b/settings.gradle.kts index df110ef43..9a88ccbd4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,4 +32,5 @@ include(":dispatch-core:samples") include(":dispatch-detekt") include(":dispatch-detekt:samples") include(":dispatch-internal-test") +include(":dispatch-internal-test-android") include(":dispatch-sample")