10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.kodiak.toml:
--------------------------------------------------------------------------------
1 | # Configuration for Kodiak's auto-merge tool
2 | # see full options: https://kodiakhq.com/docs/config-reference
3 |
4 | version = 1 # this is required but 1 is currently the only option
5 |
6 | [update]
7 | always = false # default: false
8 | require_automerge_label = true # default: true
9 | automerge_label = "automerge" # default: automerge
10 | # if using `update.always`, add dependabot to `update.ignore_usernames` to allow
11 | # dependabot to update and close stale dependency upgrades.
12 | # ignored_usernames = ["dependabot"]
13 |
14 | [merge]
15 | # if a PR is ready, merge it, don't place it in the merge queue.
16 | prioritize_ready_to_merge = true # default: false
17 | # will not do anything if a matching label is applied
18 | blocking_labels = ["DO NOT MERGE"]
19 | method = "squash"
20 |
21 | [merge.automerge_dependencies]
22 | # auto merge all PRs opened by "dependabot" that are "minor" or "patch" version upgrades. "major" version upgrades will be ignored.
23 | #versions = ["minor", "patch"]
24 | #usernames = ["dependabot"]
25 |
26 | [approve]
27 | # note: remove the "[bot]" suffix from GitHub Bot usernames.
28 | # Instead of "dependabot[bot]" use "dependabot".
29 |
30 | # auto_approve_usernames = ["dependabot"]
31 | auto_approve_usernames = ["RBusarow"]
32 |
33 | [merge.message]
34 | # use title of PR for merge commit.
35 | title = "pull_request_title" # default: "github_default"
36 |
37 | # use body of PR for merge commit.
38 | body = "pull_request_body" # default: "github_default"
39 |
40 | # add the PR number to the merge commit title, like GitHub.
41 | include_pr_number = true # default: true
42 |
43 | # use the default markdown content of the PR for the merge commit.
44 | body_type = "markdown" # default: "markdown"
45 |
46 | # remove html comments to auto remove PR templates.
47 | strip_html_comments = true # default: false
48 |
49 | include_pull_request_url = true # default: false
50 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-tactile
--------------------------------------------------------------------------------
/api/Dispatch.api:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/api/Dispatch.api
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | `kotlin-dsl`
18 | }
19 |
20 | repositories {
21 | mavenCentral()
22 | google()
23 | maven("https://plugins.gradle.org/m2/")
24 | }
25 |
26 | val kotlinVersion = libs.versions.kotlin.get()
27 |
28 | dependencies {
29 |
30 | compileOnly(gradleApi())
31 |
32 | implementation(kotlin("gradle-plugin", version = kotlinVersion))
33 | implementation(kotlin("reflect", version = kotlinVersion))
34 | implementation(libs.android.gradle)
35 | implementation(libs.detekt.gradle)
36 | implementation(libs.dokka.gradle)
37 | implementation(libs.dropbox.dependencyGuard)
38 | implementation(libs.kotlin.annotation.processing)
39 | implementation(libs.kotlin.compiler)
40 | implementation(libs.kotlin.gradle.pluginApi)
41 | implementation(libs.kotlin.reflect)
42 | implementation(libs.kotlin.stdlib.jdk8)
43 | implementation(libs.kotlinx.atomicfu)
44 | implementation(libs.kotlinx.knit.gradle)
45 | implementation(libs.kotlinx.metadata.jvm)
46 | implementation(libs.ktlint.gradle)
47 | implementation(libs.vanniktech.publish)
48 | }
49 |
--------------------------------------------------------------------------------
/buildSrc/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | pluginManagement {
17 | repositories {
18 | gradlePluginPortal()
19 | mavenCentral()
20 | google()
21 | }
22 | }
23 |
24 | dependencyResolutionManagement {
25 | @Suppress("UnstableApiUsage")
26 | repositories {
27 | google()
28 | mavenCentral()
29 | }
30 | }
31 |
32 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
33 |
34 | @Suppress("UnstableApiUsage")
35 | dependencyResolutionManagement {
36 | versionCatalogs {
37 | create("libs") {
38 | from(files("../gradle/libs.versions.toml"))
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/Common.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import org.gradle.api.Project
17 | import org.gradle.api.tasks.testing.Test
18 | import org.gradle.kotlin.dsl.systemProperties
19 | import org.gradle.kotlin.dsl.withType
20 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
21 |
22 | fun Project.common() {
23 |
24 | tasks.withType {
25 |
26 | useJUnitPlatform {
27 | includeEngines("junit-vintage", "junit-jupiter")
28 | }
29 |
30 | systemProperties(
31 | // auto-discover and apply any Junit5 extensions in the classpath
32 | // "junit.jupiter.extensions.autodetection.enabled" to true,
33 |
34 | // remove parentheses from test display names
35 | "junit.jupiter.displayname.generator.default" to "org.junit.jupiter.api.DisplayNameGenerator\$Simple",
36 |
37 | // single class instance for all tests
38 | "junit.jupiter.testinstance.lifecycle.default" to "per_class",
39 |
40 | // https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-parallel-execution-config-properties
41 | // run all tests concurrently
42 | // this might wind up creating flakes thanks to Dispatchers.setMain
43 | "junit.jupiter.execution.parallel.enabled" to true,
44 | "junit.jupiter.execution.parallel.mode.default" to "concurrent",
45 | "junit.jupiter.execution.parallel.mode.classes.default" to "concurrent",
46 |
47 | "junit.jupiter.execution.parallel.config.strategy" to "dynamic",
48 | "junit.jupiter.execution.parallel.config.dynamic.factor" to 1.0
49 | )
50 |
51 | // Allow Junit 4 tests to run in parallel
52 | maxParallelForks = Runtime.getRuntime().availableProcessors()
53 | }
54 |
55 | tasks.withType()
56 | .configureEach {
57 |
58 | kotlinOptions {
59 |
60 | allWarningsAsErrors = true
61 |
62 | jvmTarget = "1.8"
63 |
64 | freeCompilerArgs = freeCompilerArgs + listOf(
65 | "-opt-in=kotlin.RequiresOptIn"
66 | )
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/androidLibrary.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("com.android.library")
18 | kotlin("android")
19 | id("detekt")
20 | id("dokka")
21 | }
22 |
23 | android {
24 |
25 | commonAndroid(project)
26 | common()
27 |
28 | // don't generate BuildConfig
29 | @Suppress("UnstableApiUsage")
30 | buildFeatures.buildConfig = false
31 | }
32 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/catalogs.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import org.gradle.api.Project
17 | import org.gradle.api.artifacts.MinimalExternalModuleDependency
18 | import org.gradle.api.artifacts.VersionCatalog
19 | import org.gradle.api.artifacts.VersionCatalogsExtension
20 | import org.gradle.api.artifacts.VersionConstraint
21 | import org.gradle.api.provider.Provider
22 | import org.gradle.kotlin.dsl.getByType
23 |
24 | val Project.catalogs: VersionCatalogsExtension
25 | get() = extensions.getByType(VersionCatalogsExtension::class)
26 |
27 | val Project.libsCatalog: VersionCatalog
28 | get() = catalogs.named("libs")
29 |
30 | fun VersionCatalog.dependency(alias: String): Provider {
31 | return findLibrary(alias).get()
32 | }
33 |
34 | fun VersionCatalog.version(alias: String): VersionConstraint {
35 | return findVersion(alias).get()
36 | }
37 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/dependency-guard.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
17 |
18 | apply(plugin = "com.dropbox.dependency-guard")
19 |
20 | // If we got here, we're either in an empty "parent" module without a build plugin
21 | // (and no configurations), or we're in a vanilla Kotlin module. In this case, we can just look
22 | // at configuration names.
23 | configurations
24 | .matching {
25 | it.name.endsWith("runtimeClasspath", ignoreCase = true) &&
26 | !it.name.endsWith("testRuntimeClasspath", ignoreCase = true)
27 | }
28 | .all { configureClasspath(name) }
29 | }
30 |
31 | pluginManager.withPlugin("com.android.library") {
32 |
33 | apply(plugin = "com.dropbox.dependency-guard")
34 |
35 | // For Android modules, just hard-code `releaseRuntimeClasspath` for the release variant.
36 | // This is actually pretty robust, since if this configuration ever changes, dependency-guard
37 | // will fail when trying to look it up.
38 | extensions.configure {
39 | configureClasspath("releaseRuntimeClasspath")
40 | }
41 | }
42 |
43 | fun configureClasspath(classpathName: String) {
44 | configure {
45 | // Tell dependency-guard to check the `$classpathName` configuration's dependencies.
46 | configuration(classpathName)
47 | }
48 | }
49 |
50 | // Delete any existing dependency files/directories before recreating with a new baseline task.
51 | val dependencyGuardDeleteBaselines by tasks.registering(Delete::class) {
52 | delete("dependencies")
53 | }
54 | tasks.matching { it.name == "dependencyGuardBaseline" }
55 | .configureEach { dependsOn(dependencyGuardDeleteBaselines) }
56 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/detekt.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import io.gitlab.arturbosch.detekt.Detekt
17 | import io.gitlab.arturbosch.detekt.report.ReportMergeTask
18 | import org.gradle.internal.impldep.org.junit.experimental.categories.Categories.CategoryFilter.exclude
19 |
20 | plugins {
21 | id("io.gitlab.arturbosch.detekt")
22 | }
23 |
24 | val reportMerge by tasks.registering(ReportMergeTask::class) {
25 | output.set(rootProject.buildDir.resolve("reports/detekt/merged.sarif"))
26 | }
27 |
28 | val detektExcludes = listOf(
29 | "**/resources/**",
30 | "**/buildSrc/**",
31 | "**/build/**"
32 | )
33 |
34 | tasks.withType {
35 |
36 | parallel = true
37 | config.from(files("$rootDir/detekt/detekt-config.yml"))
38 | buildUponDefaultConfig = true
39 |
40 | // If in CI, merge sarif reports. Skip this locally because it's not worth looking at
41 | // and the task is unnecessarily chatty.
42 | if (!System.getenv("CI").isNullOrBlank()) {
43 | finalizedBy(reportMerge)
44 | reportMerge.configure {
45 | input.from(sarifReportFile)
46 | }
47 | }
48 |
49 | reports {
50 | xml.required.set(true)
51 | html.required.set(true)
52 | txt.required.set(false)
53 | sarif.required.set(true)
54 | }
55 |
56 | setSource(files(projectDir))
57 |
58 | include("**/*.kt", "**/*.kts")
59 | exclude(detektExcludes)
60 | subprojects.forEach { sub ->
61 | exclude("**/${sub.projectDir.relativeTo(rootDir)}/**")
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/javaLibrary.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import org.jetbrains.kotlin.gradle.dsl.*
17 |
18 | plugins {
19 | kotlin("jvm")
20 | id("com.android.lint")
21 | id("detekt")
22 | id("dokka")
23 | }
24 |
25 | common()
26 |
27 | kotlin {
28 | if (!path.endsWith("samples")) {
29 | explicitApi = ExplicitApiMode.Strict
30 | }
31 | }
32 |
33 | java {
34 | // force Java 8 source when building java-only artifacts.
35 | // This is different than the Kotlin jvm target.
36 | sourceCompatibility = JavaVersion.VERSION_1_8
37 | targetCompatibility = JavaVersion.VERSION_1_8
38 | }
39 |
40 | val testJvm by tasks.registering {
41 | dependsOn("test")
42 | }
43 |
44 | val buildTests by tasks.registering {
45 | dependsOn("testClasses")
46 | }
47 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/knit.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | apply(plugin = "kotlinx-knit")
17 |
18 | extensions.configure {
19 |
20 | rootDir = rootProject.rootDir
21 |
22 | files = fileTree(project.rootDir) {
23 | include(
24 | "**/*.md",
25 | "**/*.kt",
26 | "**/*.kts"
27 | )
28 | exclude(
29 | "**/node_modules/**",
30 | "**/build/**",
31 | "**/sample/**",
32 | "**/.gradle/**"
33 | )
34 | }
35 |
36 | moduleRoots = listOf(".")
37 |
38 | moduleDocs = "build/dokka"
39 | moduleMarkers = listOf("build.gradle", "build.gradle.kts")
40 | siteRoot = "https://rbusarow.github.io/Dispatch/api/"
41 | }
42 |
43 | // Build API docs for all modules with dokka before running Knit
44 | tasks.withType()
45 | .configureEach {
46 | dependsOn("dokkaHtmlMultiModule")
47 | }
48 |
--------------------------------------------------------------------------------
/detekt/license.template:
--------------------------------------------------------------------------------
1 | \/\*\n \* Copyright \(C\) 20[0-9]{2}(-20[0-9]{2})?.*\n \* Licensed under the Apache License\, Version 2\.0 \(the \"License\"\)\;\n \* you may not use this file except in compliance with the License\.\n \* You may obtain a copy of the License at\n \*\n \* http\:\/\/www\.apache\.org\/licenses\/LICENSE\-2\.0\n \*\n \* Unless required by applicable law or agreed to in writing\, software\n \* distributed under the License is distributed on an \"AS IS\" BASIS\,\n \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND\, either express or implied\.\n \* See the License for the specific language governing permissions and\n \* limitations under the License\.\n \*\/
2 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | androidLibrary
18 | published
19 | }
20 |
21 | android {
22 | namespace = "dispatch.android.espresso"
23 | }
24 |
25 | dependencies {
26 |
27 | api(libs.androidx.test.espresso.idlingResource)
28 | api(libs.junit.junit4)
29 | api(libs.kotlinx.coroutines.core)
30 | api(libs.kotlinx.coroutines.jvm)
31 |
32 | api(projects.dispatchCore)
33 |
34 | implementation(libs.kotlinx.coroutines.android)
35 |
36 | testImplementation(libs.kotest.assertions)
37 | testImplementation(libs.kotest.runner)
38 | testImplementation(libs.mockk)
39 | testImplementation(libs.robolectric)
40 |
41 | testImplementation(projects.dispatchAndroidLifecycleExtensions)
42 | testImplementation(projects.dispatchAndroidViewmodel)
43 | testImplementation(projects.dispatchInternalTest)
44 | }
45 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/dependencies/releaseRuntimeClasspath.txt:
--------------------------------------------------------------------------------
1 | androidx.test.espresso:espresso-idling-resource:3.4.0
2 | junit:junit:4.13.2
3 | org.hamcrest:hamcrest-core:1.3
4 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
5 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
6 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
7 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
8 | org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2
9 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
10 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
11 | org.jetbrains:annotations:13.0
12 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-android-espresso
16 | POM_NAME=dispatch-android-espresso
17 | POM_PACKAGING=aar
18 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/main/java/dispatch/android/espresso/IdlingDispatcher.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso
17 |
18 | import androidx.test.espresso.IdlingResource
19 | import androidx.test.espresso.idling.CountingIdlingResource
20 | import kotlinx.coroutines.CoroutineDispatcher
21 | import kotlinx.coroutines.Runnable
22 | import kotlin.coroutines.CoroutineContext
23 |
24 | /**
25 | * [IdlingResource] helper for coroutines. This class simply wraps a delegate [CoroutineDispatcher]
26 | * and keeps a running count of all coroutines it creates, decrementing the count when they
27 | * complete.
28 | *
29 | * @property delegate The [CoroutineDispatcher] which will be used for actual dispatch.
30 | * @see IdlingResource
31 | * @see CoroutineDispatcher
32 | */
33 | public class IdlingDispatcher(
34 | private val delegate: CoroutineDispatcher
35 | ) : CoroutineDispatcher() {
36 |
37 | /** The [CountingIdlingResource] which is responsible for Espresso functionality. */
38 | public val counter: CountingIdlingResource = CountingIdlingResource("IdlingResource for $this")
39 |
40 | /**
41 | * * true if the [counter]'s count is zero
42 | * * false if the [counter]'s count is non-zero
43 | *
44 | * @return
45 | */
46 | @Suppress("UNUSED")
47 | public fun isIdle(): Boolean = counter.isIdleNow
48 |
49 | /**
50 | * Counting implementation of the [dispatch][CoroutineDispatcher.dispatch] function.
51 | *
52 | * The count is incremented for every dispatch, and decremented for every completion, including
53 | * suspension.
54 | */
55 | override fun dispatch(context: CoroutineContext, block: Runnable) {
56 |
57 | val runnable = Runnable {
58 | counter.increment()
59 | try {
60 | block.run()
61 | } finally {
62 | counter.decrement()
63 | }
64 | }
65 | delegate.dispatch(context, runnable)
66 | }
67 |
68 | /** @suppress */
69 | override fun toString(): String = "CountingDispatcher delegating to $delegate"
70 | }
71 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/DefaultIdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso.samples
17 |
18 | import dispatch.android.espresso.DefaultIdlingCoroutineScope
19 | import dispatch.android.espresso.registerAllIdlingResources
20 | import dispatch.internal.test.Sample4
21 | import kotlinx.coroutines.Job
22 | import org.junit.runner.RunWith
23 | import org.robolectric.RobolectricTestRunner
24 |
25 | @RunWith(RobolectricTestRunner::class)
26 | class DefaultIdlingCoroutineScope {
27 |
28 | @Sample4
29 | fun createNoArgDefault() {
30 |
31 | val scope = DefaultIdlingCoroutineScope()
32 |
33 | scope.idlingDispatcherProvider.registerAllIdlingResources()
34 | }
35 |
36 | @Sample4
37 | fun createCustomDefault() {
38 |
39 | val scope = DefaultIdlingCoroutineScope(
40 | job = Job(),
41 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
42 | )
43 |
44 | scope.idlingDispatcherProvider.registerAllIdlingResources()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/IOIdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package dispatch.android.espresso.samples
16 |
17 | import dispatch.android.espresso.IOIdlingCoroutineScope
18 | import dispatch.android.espresso.registerAllIdlingResources
19 | import dispatch.internal.test.Sample4
20 | import kotlinx.coroutines.Job
21 | import org.junit.runner.RunWith
22 | import org.robolectric.RobolectricTestRunner
23 |
24 | @RunWith(RobolectricTestRunner::class)
25 | class IOIdlingCoroutineScope {
26 |
27 | @Sample4
28 | fun createNoArgIO() {
29 |
30 | val scope = IOIdlingCoroutineScope()
31 |
32 | scope.idlingDispatcherProvider.registerAllIdlingResources()
33 | }
34 |
35 | @Sample4
36 | fun createCustomIO() {
37 |
38 | val scope = IOIdlingCoroutineScope(
39 | job = Job(),
40 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
41 | )
42 |
43 | scope.idlingDispatcherProvider.registerAllIdlingResources()
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/IdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso.samples
17 |
18 | import dispatch.android.espresso.IdlingCoroutineScope
19 | import dispatch.android.espresso.IdlingDispatcherProvider
20 | import dispatch.android.espresso.registerAllIdlingResources
21 | import dispatch.internal.test.Sample4
22 | import kotlinx.coroutines.Job
23 | import org.junit.runner.RunWith
24 | import org.robolectric.RobolectricTestRunner
25 |
26 | @RunWith(RobolectricTestRunner::class)
27 | class IdlingCoroutineScope {
28 |
29 | @Sample4
30 | fun createNoArg() {
31 |
32 | val scope = IdlingCoroutineScope()
33 |
34 | scope.idlingDispatcherProvider.registerAllIdlingResources()
35 | }
36 |
37 | @Sample4
38 | fun createCustom() {
39 |
40 | val scope = IdlingCoroutineScope(
41 | job = Job(),
42 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
43 | )
44 |
45 | scope.idlingDispatcherProvider.registerAllIdlingResources()
46 | }
47 | }
48 |
49 | fun SomeCustomIdlingDispatcherProvider() = IdlingDispatcherProvider()
50 |
51 | class TestAppComponent {
52 | val customDispatcherProvider = IdlingDispatcherProvider()
53 | }
54 |
55 | val testAppComponent get() = TestAppComponent()
56 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/IdlingCoroutineScopeRuleSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso.samples
17 |
18 | import dispatch.android.espresso.IdlingDispatcherProvider
19 | import dispatch.android.espresso.IdlingDispatcherProviderRule
20 | import kotlinx.coroutines.runBlocking
21 | import org.junit.Rule
22 | import org.junit.Test
23 | import org.junit.runner.RunWith
24 | import org.robolectric.RobolectricTestRunner
25 |
26 | @RunWith(RobolectricTestRunner::class)
27 | class IdlingCoroutineScopeRuleSample {
28 |
29 | // Retrieve the DispatcherProvider from a dependency graph,
30 | // so that the same one is used throughout the codebase.
31 | val customDispatcherProvider = testAppComponent.customDispatcherProvider
32 |
33 | @JvmField
34 | @Rule
35 | val idlingRule = IdlingDispatcherProviderRule {
36 | IdlingDispatcherProvider(customDispatcherProvider)
37 | }
38 |
39 | @Test
40 | fun testThings() = runBlocking {
41 |
42 | // Now any CoroutineScope which uses the DispatcherProvider
43 | // in TestAppComponent will sync its "idle" state with Espresso
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/IdlingCoroutineScopeRuleWithLifecycleSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package dispatch.android.espresso.samples
16 |
17 | import dispatch.android.espresso.IdlingDispatcherProvider
18 | import dispatch.android.espresso.IdlingDispatcherProviderRule
19 | import dispatch.android.lifecycle.LifecycleScopeFactory
20 | import dispatch.android.viewmodel.ViewModelScopeFactory
21 | import dispatch.core.MainImmediateCoroutineScope
22 | import kotlinx.coroutines.runBlocking
23 | import org.junit.Before
24 | import org.junit.Rule
25 | import org.junit.Test
26 | import org.junit.runner.RunWith
27 | import org.robolectric.RobolectricTestRunner
28 |
29 | @RunWith(RobolectricTestRunner::class)
30 | class IdlingCoroutineScopeRuleWithLifecycleSample {
31 |
32 | // Retrieve the DispatcherProvider from a dependency graph,
33 | // so that the same one is used throughout the codebase.
34 | val customDispatcherProvider = testAppComponent.customDispatcherProvider
35 |
36 | @JvmField
37 | @Rule
38 | val idlingRule = IdlingDispatcherProviderRule {
39 | IdlingDispatcherProvider(customDispatcherProvider)
40 | }
41 |
42 | @Before
43 | fun setUp() {
44 | LifecycleScopeFactory.set { customDispatcherProvider }
45 | ViewModelScopeFactory.set {
46 | MainImmediateCoroutineScope(customDispatcherProvider)
47 | }
48 | // now all scopes use the same IdlingDispatcherProvider
49 | }
50 |
51 | @Test
52 | fun testThings() = runBlocking {
53 |
54 | // Now any CoroutineScope which uses the DispatcherProvider
55 | // in TestAppComponent will sync its "idle" state with Espresso
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/MainIdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package dispatch.android.espresso.samples
16 |
17 | import dispatch.android.espresso.MainIdlingCoroutineScope
18 | import dispatch.android.espresso.registerAllIdlingResources
19 | import dispatch.internal.test.Sample4
20 | import kotlinx.coroutines.Job
21 | import org.junit.runner.RunWith
22 | import org.robolectric.RobolectricTestRunner
23 |
24 | @RunWith(RobolectricTestRunner::class)
25 | class MainIdlingCoroutineScope {
26 |
27 | @Sample4
28 | fun createNoArgMain() {
29 |
30 | val scope = MainIdlingCoroutineScope()
31 |
32 | scope.idlingDispatcherProvider.registerAllIdlingResources()
33 | }
34 |
35 | @Sample4
36 | fun createCustomMain() {
37 |
38 | val scope = MainIdlingCoroutineScope(
39 | job = Job(),
40 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
41 | )
42 |
43 | scope.idlingDispatcherProvider.registerAllIdlingResources()
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/MainImmediateIdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso.samples
17 |
18 | import dispatch.android.espresso.MainImmediateIdlingCoroutineScope
19 | import dispatch.android.espresso.registerAllIdlingResources
20 | import dispatch.internal.test.Sample4
21 | import kotlinx.coroutines.Job
22 | import org.junit.runner.RunWith
23 | import org.robolectric.RobolectricTestRunner
24 |
25 | @RunWith(RobolectricTestRunner::class)
26 | class MainImmediateIdlingCoroutineScope {
27 |
28 | @Sample4
29 | fun createNoArg() {
30 |
31 | val scope = MainImmediateIdlingCoroutineScope()
32 |
33 | scope.idlingDispatcherProvider.registerAllIdlingResources()
34 | }
35 |
36 | @Sample4
37 | fun createCustom() {
38 |
39 | val scope = MainImmediateIdlingCoroutineScope(
40 | job = Job(),
41 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
42 | )
43 |
44 | scope.idlingDispatcherProvider.registerAllIdlingResources()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dispatch-android-espresso/src/test/java/dispatch/android/espresso/samples/UnconfinedIdlingCoroutineScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.espresso.samples
17 |
18 | import dispatch.android.espresso.UnconfinedIdlingCoroutineScope
19 | import dispatch.android.espresso.registerAllIdlingResources
20 | import dispatch.internal.test.Sample4
21 | import kotlinx.coroutines.Job
22 | import org.junit.runner.RunWith
23 | import org.robolectric.RobolectricTestRunner
24 |
25 | @RunWith(RobolectricTestRunner::class)
26 | class UnconfinedIdlingCoroutineScope {
27 |
28 | @Sample4
29 | fun createNoArgUnconfined() {
30 |
31 | val scope = UnconfinedIdlingCoroutineScope()
32 |
33 | scope.idlingDispatcherProvider.registerAllIdlingResources()
34 | }
35 |
36 | @Sample4
37 | fun createCustomUnconfined() {
38 |
39 | val scope = UnconfinedIdlingCoroutineScope(
40 | job = Job(),
41 | dispatcherProvider = SomeCustomIdlingDispatcherProvider()
42 | )
43 |
44 | scope.idlingDispatcherProvider.registerAllIdlingResources()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/api/dispatch-android-lifecycle-extensions.api:
--------------------------------------------------------------------------------
1 | public final class dispatch/android/lifecycle/LifecycleOwnerKt {
2 | public static final fun getDispatchLifecycleScope (Landroidx/lifecycle/LifecycleOwner;)Ldispatch/android/lifecycle/DispatchLifecycleScope;
3 | public static final fun getLifecycleScope (Landroidx/lifecycle/LifecycleOwner;)Ldispatch/android/lifecycle/DispatchLifecycleScope;
4 | }
5 |
6 | public final class dispatch/android/lifecycle/LifecycleScopeFactory {
7 | public static final field INSTANCE Ldispatch/android/lifecycle/LifecycleScopeFactory;
8 | public final fun reset ()V
9 | public final fun set (Ldispatch/android/lifecycle/DispatchLifecycleScopeFactory;)V
10 | public final fun set (Lkotlin/jvm/functions/Function0;)V
11 | }
12 |
13 | public final class dispatch/android/lifecycle/WithViewLifecycleScopeKt {
14 | public static final fun withViewLifecycleScope (Landroidx/fragment/app/Fragment;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/Job;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | androidLibrary
18 | published
19 | }
20 |
21 | android {
22 | namespace = "dispatch.android.lifecycle.extensions"
23 | }
24 |
25 | dependencies {
26 |
27 | api(libs.androidx.fragment.core)
28 | api(libs.androidx.lifecycle.common)
29 | api(libs.kotlinx.coroutines.core)
30 | api(libs.kotlinx.coroutines.jvm)
31 |
32 | api(projects.dispatchAndroidLifecycle)
33 |
34 | implementation(libs.kotlinx.coroutines.android)
35 |
36 | implementation(projects.dispatchCore)
37 |
38 | testImplementation(libs.androidx.arch.test.core)
39 | testImplementation(libs.androidx.lifecycle.runtime)
40 | testImplementation(libs.androidx.test.espresso.core)
41 | testImplementation(libs.androidx.test.runner)
42 | testImplementation(libs.hermit.jUnit5)
43 | testImplementation(libs.junit.jupiter)
44 | testImplementation(libs.kotest.assertions)
45 | testImplementation(libs.kotest.properties)
46 | testImplementation(libs.kotest.runner)
47 | testImplementation(libs.kotlinx.coroutines.test)
48 | testImplementation(libs.robolectric)
49 |
50 | testImplementation(projects.dispatchAndroidEspresso)
51 | testImplementation(projects.dispatchInternalTest)
52 | testImplementation(projects.dispatchInternalTestAndroid)
53 | testImplementation(projects.dispatchTest)
54 | testImplementation(projects.dispatchTestJunit4)
55 | }
56 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/dependencies/releaseRuntimeClasspath.txt:
--------------------------------------------------------------------------------
1 | androidx.activity:activity:1.5.1
2 | androidx.annotation:annotation-experimental:1.1.0
3 | androidx.annotation:annotation:1.2.0
4 | androidx.arch.core:core-common:2.1.0
5 | androidx.arch.core:core-runtime:2.1.0
6 | androidx.collection:collection:1.1.0
7 | androidx.concurrent:concurrent-futures:1.0.0
8 | androidx.core:core-ktx:1.2.0
9 | androidx.core:core:1.8.0
10 | androidx.customview:customview:1.0.0
11 | androidx.fragment:fragment:1.5.2
12 | androidx.lifecycle:lifecycle-common:2.5.1
13 | androidx.lifecycle:lifecycle-livedata-core-ktx:2.5.1
14 | androidx.lifecycle:lifecycle-livedata-core:2.5.1
15 | androidx.lifecycle:lifecycle-livedata-ktx:2.5.1
16 | androidx.lifecycle:lifecycle-livedata:2.5.1
17 | androidx.lifecycle:lifecycle-runtime:2.5.1
18 | androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1
19 | androidx.lifecycle:lifecycle-viewmodel:2.5.1
20 | androidx.loader:loader:1.0.0
21 | androidx.savedstate:savedstate:1.2.0
22 | androidx.tracing:tracing:1.0.0
23 | androidx.versionedparcelable:versionedparcelable:1.1.1
24 | androidx.viewpager:viewpager:1.0.0
25 | com.google.guava:listenablefuture:1.0
26 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
27 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
28 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
29 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
30 | org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2
31 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
32 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
33 | org.jetbrains:annotations:13.0
34 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-android-lifecycle-extensions
16 | POM_NAME=dispatch-android-lifecycle-extensions
17 | POM_PACKAGING=aar
18 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/main/java/dispatch/android/lifecycle/internal/atomic.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle.internal
17 |
18 | import androidx.lifecycle.Lifecycle
19 | import dispatch.android.lifecycle.DispatchLifecycleScope
20 | import dispatch.core.launchMainImmediate
21 | import kotlinx.coroutines.Job
22 | import java.util.concurrent.ConcurrentMap
23 |
24 | /**
25 | * Normal [getOrPut] is guaranteed to only return a single instance for a given key, but the
26 | * [defaultValue] lambda may be invoked unnecessarily. This would create a new instance of
27 | * [DispatchLifecycleScope] without actually returning it.
28 | *
29 | * This extra [DispatchLifecycleScope] would still be active and observing the [lifecycle][key].
30 | *
31 | * This function compares the result of the lambda to the result of [getOrPut], and cancels the
32 | * lambda's result if it's different.
33 | *
34 | * @see getOrPut
35 | */
36 | internal inline fun ConcurrentMap.atomicGetOrPut(
37 | key: Lifecycle,
38 | defaultValue: () -> DispatchLifecycleScope
39 | ): DispatchLifecycleScope {
40 |
41 | var newInstance: DispatchLifecycleScope? = null
42 |
43 | val existingOrNew = getOrPut(key) {
44 | newInstance = defaultValue.invoke()
45 | newInstance!!
46 | }
47 |
48 | // If the second value is different, that means the first was never inserted into the map.
49 | // Cancel the observer for `newInstance` and cancel the coroutineContext.
50 | newInstance?.let { new ->
51 | if (new != existingOrNew) {
52 | existingOrNew.launchMainImmediate {
53 |
54 | new.coroutineContext[Job]?.cancel()
55 | }
56 | }
57 | }
58 |
59 | return existingOrNew
60 | }
61 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/main/java/dispatch/android/lifecycle/withViewLifecycleScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle
17 |
18 | import androidx.fragment.app.Fragment
19 | import kotlinx.coroutines.CoroutineScope
20 | import kotlinx.coroutines.ExperimentalCoroutinesApi
21 | import kotlinx.coroutines.Job
22 |
23 | /**
24 | * [CoroutineScope] helper for a [Fragment]'s
25 | * [ViewLifecycleOwner][androidx.fragment.app.FragmentViewLifecycleOwner].
26 | *
27 | * This function observes a `Fragment`'s
28 | * [viewLifecycleOwnerLiveData][androidx.fragment.app.Fragment.getViewLifecycleOwnerLiveData],
29 | * and invokes [block].
30 | *
31 | * @sample dispatch.android.lifecycle.samples.WithViewLifecycleScopeExtensionSample.sample
32 | */
33 | @ExperimentalCoroutinesApi
34 | public fun Fragment.withViewLifecycleScope(
35 | block: ViewLifecycleCoroutineScope.() -> Unit
36 | ): Job = dispatchLifecycleScope.withViewLifecycle(this, block)
37 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/test/java/dispatch/android/lifecycle/samples/Fragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle.samples
17 |
18 | import androidx.lifecycle.Lifecycle
19 | import dispatch.internal.test.android.FakeLifecycleOwner
20 |
21 | @Suppress("UnnecessaryAbstractClass")
22 | abstract class Fragment(
23 | initialState: Lifecycle.State = Lifecycle.State.INITIALIZED
24 | ) : FakeLifecycleOwner(initialState = initialState)
25 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/test/java/dispatch/android/lifecycle/samples/LifecycleScopeExtensionSamples.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle.samples
17 |
18 | import dispatch.android.lifecycle.dispatchLifecycleScope
19 | import dispatch.core.launchMain
20 | import dispatch.internal.test.Sample5
21 |
22 | class LifecycleScopeExtensionSamples {
23 |
24 | @Sample5
25 | fun sample() {
26 |
27 | // This could be any LifecycleOwner -- Fragments, Activities, Services...
28 | class SomeFragment : Fragment() {
29 |
30 | init {
31 |
32 | // auto-created MainImmediateCoroutineScope which is lifecycle-aware
33 | dispatchLifecycleScope // ...
34 |
35 | // active only when "resumed". starts a fresh coroutine each time
36 | // this is a rough proxy for LiveData behavior
37 | dispatchLifecycleScope.launchOnResume { }
38 |
39 | // active only when "started". starts a fresh coroutine each time
40 | dispatchLifecycleScope.launchOnStart { }
41 |
42 | // launch when created, automatically stop on destroy
43 | dispatchLifecycleScope.launchOnCreate { }
44 |
45 | // it works as a normal CoroutineScope as well (because it is)
46 | dispatchLifecycleScope.launchMain { }
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/test/java/dispatch/android/lifecycle/samples/LifecycleScopeFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:Suppress("EXPERIMENTAL_API_USAGE")
17 |
18 | package dispatch.android.lifecycle.samples
19 |
20 | import dispatch.android.espresso.IdlingDispatcherProvider
21 | import dispatch.android.lifecycle.LifecycleScopeFactory
22 | import dispatch.android.lifecycle.MainImmediateContext
23 | import dispatch.core.DispatcherProvider
24 | import dispatch.internal.test.Application
25 | import dispatch.internal.test.MyCustomElement
26 | import dispatch.internal.test.Sample5
27 | import kotlinx.coroutines.SupervisorJob
28 |
29 | class LifecycleScopeFactorySample {
30 |
31 | @Sample5
32 | fun productionSample() {
33 |
34 | class MyApplication : Application {
35 |
36 | override fun onCreate() {
37 |
38 | LifecycleScopeFactory.set { MyCustomElement() + MainImmediateContext() }
39 | }
40 | }
41 | }
42 |
43 | @Sample5
44 | fun espressoSample() {
45 |
46 | class MyEspressoTest {
47 |
48 | @Before
49 | fun setUp() {
50 |
51 | val dispatcherProvider = IdlingDispatcherProvider()
52 |
53 | LifecycleScopeFactory.set {
54 | SupervisorJob() + dispatcherProvider + dispatcherProvider.mainImmediate
55 | }
56 | }
57 | }
58 | }
59 |
60 | @Sample5
61 | fun resetSample() {
62 |
63 | class MyEspressoTest {
64 |
65 | @Before
66 | fun setUp() {
67 |
68 | val dispatcherProvider = DispatcherProvider()
69 |
70 | LifecycleScopeFactory.set {
71 | SupervisorJob() + dispatcherProvider + dispatcherProvider.mainImmediate
72 | }
73 | }
74 |
75 | @After
76 | fun tearDown() {
77 | LifecycleScopeFactory.reset()
78 | }
79 | }
80 | }
81 |
82 | private annotation class Before
83 | private annotation class After
84 | }
85 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle-extensions/src/test/java/dispatch/android/lifecycle/samples/WithViewLifecycleScopeExtensionSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 | @file:Suppress("UNUSED_ANONYMOUS_PARAMETER")
18 |
19 | package dispatch.android.lifecycle.samples
20 |
21 | import androidx.fragment.app.Fragment
22 | import dispatch.android.lifecycle.withViewLifecycleScope
23 | import dispatch.internal.test.Sample4
24 | import kotlinx.coroutines.ExperimentalCoroutinesApi
25 | import kotlinx.coroutines.flow.flow
26 | import kotlinx.coroutines.flow.onEach
27 | import org.junit.runner.RunWith
28 | import org.robolectric.RobolectricTestRunner
29 | import org.robolectric.annotation.Config
30 |
31 | @RunWith(RobolectricTestRunner::class)
32 | @Config(manifest = Config.NONE)
33 | class WithViewLifecycleScopeExtensionSample {
34 |
35 | @Sample4
36 | fun sample() {
37 |
38 | class MyViewModel {
39 |
40 | val dataFlow = flow {
41 | // ...
42 | }
43 | }
44 |
45 | class MyFragment : Fragment() {
46 |
47 | val myViewModel = MyViewModel()
48 |
49 | val observerJob = withViewLifecycleScope {
50 | myViewModel.dataFlow.onEach { data ->
51 | // ...
52 | }.launchOnCreate()
53 | }
54 | }
55 | }
56 | }
57 |
58 | interface Data
59 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | androidLibrary
18 | published
19 | }
20 |
21 | android {
22 | namespace = "dispatch.android.lifecycle"
23 | }
24 |
25 | dependencies {
26 |
27 | api(libs.androidx.lifecycle.common)
28 | api(libs.kotlinx.coroutines.core)
29 | api(libs.kotlinx.coroutines.jvm)
30 |
31 | api(projects.dispatchCore)
32 |
33 | implementation(libs.androidx.fragment.core)
34 | implementation(libs.androidx.lifecycle.liveData)
35 | implementation(libs.androidx.lifecycle.liveDataKtx)
36 | implementation(libs.androidx.lifecycle.runtime)
37 | implementation(libs.kotlinx.coroutines.android)
38 |
39 | testImplementation(libs.androidx.arch.test.core)
40 | testImplementation(libs.androidx.fragment.ktx)
41 | testImplementation(libs.androidx.lifecycle.runtime)
42 | testImplementation(libs.androidx.lifecycle.viewModel.ktx)
43 | testImplementation(libs.androidx.test.espresso.core)
44 | testImplementation(libs.androidx.test.runner)
45 | testImplementation(libs.hermit.coroutines)
46 | testImplementation(libs.hermit.jUnit5)
47 | testImplementation(libs.junit.jupiter)
48 | testImplementation(libs.kotest.assertions)
49 | testImplementation(libs.kotest.properties)
50 | testImplementation(libs.kotest.runner)
51 | testImplementation(libs.kotlinx.coroutines.test)
52 | testImplementation(libs.robolectric)
53 |
54 | testImplementation(projects.dispatchAndroidLifecycleExtensions)
55 | testImplementation(projects.dispatchInternalTest)
56 | testImplementation(projects.dispatchInternalTestAndroid)
57 | testImplementation(projects.dispatchTest)
58 | testImplementation(projects.dispatchTestJunit4)
59 | testImplementation(projects.dispatchTestJunit5)
60 | }
61 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/dependencies/releaseRuntimeClasspath.txt:
--------------------------------------------------------------------------------
1 | androidx.activity:activity:1.5.1
2 | androidx.annotation:annotation-experimental:1.1.0
3 | androidx.annotation:annotation:1.2.0
4 | androidx.arch.core:core-common:2.1.0
5 | androidx.arch.core:core-runtime:2.1.0
6 | androidx.collection:collection:1.1.0
7 | androidx.concurrent:concurrent-futures:1.0.0
8 | androidx.core:core-ktx:1.2.0
9 | androidx.core:core:1.8.0
10 | androidx.customview:customview:1.0.0
11 | androidx.fragment:fragment:1.5.2
12 | androidx.lifecycle:lifecycle-common:2.5.1
13 | androidx.lifecycle:lifecycle-livedata-core-ktx:2.5.1
14 | androidx.lifecycle:lifecycle-livedata-core:2.5.1
15 | androidx.lifecycle:lifecycle-livedata-ktx:2.5.1
16 | androidx.lifecycle:lifecycle-livedata:2.5.1
17 | androidx.lifecycle:lifecycle-runtime:2.5.1
18 | androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1
19 | androidx.lifecycle:lifecycle-viewmodel:2.5.1
20 | androidx.loader:loader:1.0.0
21 | androidx.savedstate:savedstate:1.2.0
22 | androidx.tracing:tracing:1.0.0
23 | androidx.versionedparcelable:versionedparcelable:1.1.1
24 | androidx.viewpager:viewpager:1.0.0
25 | com.google.guava:listenablefuture:1.0
26 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
27 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
28 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
29 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
30 | org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2
31 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
32 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
33 | org.jetbrains:annotations:13.0
34 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-android-lifecycle
16 | POM_NAME=dispatch-android-lifecycle
17 | POM_PACKAGING=aar
18 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/src/main/java/dispatch/android/lifecycle/DispatchLifecycleScopeFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle
17 |
18 | import androidx.lifecycle.Lifecycle
19 | import kotlin.coroutines.CoroutineContext
20 |
21 | /**
22 | * Factory for [DispatchLifecycleScope]s. This may be injected into a lifecycle-aware class to
23 | * provide custom [CoroutineContexts][CoroutineContext].
24 | *
25 | * @property coroutineContextFactory the lambda defining the creating of a [CoroutineContext]
26 | * @sample dispatch.android.lifecycle.samples.DispatchLifecycleScopeFactorySample.factorySample
27 | */
28 | public class DispatchLifecycleScopeFactory(
29 | private val coroutineContextFactory: () -> CoroutineContext
30 | ) {
31 |
32 | /**
33 | * Creates a new [DispatchLifecycleScope] using `coroutineContextFactory`
34 | *
35 | * @param lifecycle the lifecycle which will be bound to the [DispatchLifecycleScope]
36 | */
37 | public fun create(
38 | lifecycle: Lifecycle
39 | ): DispatchLifecycleScope = DispatchLifecycleScope(lifecycle, coroutineContextFactory.invoke())
40 | }
41 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/src/test/java/dispatch/android/lifecycle/samples/DispatchLifecycleCoroutineScopeFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle.samples
17 |
18 | import dispatch.android.lifecycle.DispatchLifecycleScopeFactory
19 | import dispatch.internal.test.MyCustomElement
20 | import dispatch.internal.test.Sample5
21 | import dispatch.internal.test.android.LiveDataTest
22 |
23 | class DispatchLifecycleScopeFactorySample : LiveDataTest {
24 |
25 | @Sample5
26 | fun factorySample() {
27 |
28 | @Provides
29 | fun provideFactory(): DispatchLifecycleScopeFactory = DispatchLifecycleScopeFactory {
30 | // other elements are added automatically
31 | MyCustomElement()
32 | }
33 |
34 | class MyFragment @Inject constructor(
35 | factory: DispatchLifecycleScopeFactory
36 | ) : Fragment() {
37 |
38 | val lifecycleScope = factory.create(lifecycle)
39 |
40 | init {
41 | lifecycleScope.launchOnStart {
42 | // ...
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | internal annotation class Before
50 | internal annotation class After
51 | internal annotation class Module
52 | internal annotation class Provides
53 | internal annotation class Inject
54 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/src/test/java/dispatch/android/lifecycle/samples/Fragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.lifecycle.samples
17 |
18 | import androidx.lifecycle.Lifecycle
19 | import dispatch.internal.test.android.FakeLifecycleOwner
20 |
21 | @Suppress("UnnecessaryAbstractClass")
22 | abstract class Fragment(
23 | initialState: Lifecycle.State = Lifecycle.State.INITIALIZED
24 | ) : FakeLifecycleOwner(initialState = initialState)
25 |
--------------------------------------------------------------------------------
/dispatch-android-lifecycle/src/test/java/dispatch/android/lifecycle/samples/WithLifecycleScopeSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 | @file:Suppress("UNUSED_ANONYMOUS_PARAMETER")
18 |
19 | package dispatch.android.lifecycle.samples
20 |
21 | import androidx.fragment.app.Fragment
22 | import androidx.fragment.app.viewModels
23 | import androidx.lifecycle.ViewModel
24 | import dispatch.android.lifecycle.withViewLifecycle
25 | import dispatch.core.MainImmediateCoroutineScope
26 | import dispatch.internal.test.android.LiveDataTest
27 | import kotlinx.coroutines.ExperimentalCoroutinesApi
28 | import kotlinx.coroutines.flow.flow
29 | import kotlinx.coroutines.flow.onEach
30 | import org.junit.Test
31 | import org.junit.runner.RunWith
32 | import org.robolectric.RobolectricTestRunner
33 | import org.robolectric.annotation.Config
34 |
35 | @Suppress("MemberNameEqualsClassName")
36 | @RunWith(RobolectricTestRunner::class)
37 | @ExperimentalCoroutinesApi
38 | @Config(manifest = Config.NONE)
39 | class WithViewLifecycleScopeSample : LiveDataTest {
40 |
41 | @Test
42 | fun sample() {
43 |
44 | class MyFragment @Inject constructor(
45 | scope: MainImmediateCoroutineScope
46 | ) : Fragment() {
47 |
48 | val myViewModel by viewModels()
49 |
50 | val observerJob = scope.withViewLifecycle(this) {
51 | // this lambda is invoked every time the View lifecycle is set
52 | myViewModel.dataFlow.onEach { data ->
53 | // ...
54 | }.launchOnCreate()
55 | }
56 | }
57 | }
58 | }
59 |
60 | interface Data
61 |
62 | class MyViewModel : ViewModel() {
63 |
64 | val dataFlow = flow {
65 | // ...
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/api/dispatch-android-viewmodel.api:
--------------------------------------------------------------------------------
1 | public abstract class dispatch/android/viewmodel/DispatchViewModel : androidx/lifecycle/ViewModel {
2 | public fun ()V
3 | public final fun getViewModelScope ()Lkotlinx/coroutines/CoroutineScope;
4 | protected fun onClear ()V
5 | protected final fun onCleared ()V
6 | }
7 |
8 | public final class dispatch/android/viewmodel/ViewModelScopeFactory {
9 | public static final field INSTANCE Ldispatch/android/viewmodel/ViewModelScopeFactory;
10 | public final fun reset ()V
11 | public final fun set (Lkotlin/jvm/functions/Function0;)V
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | androidLibrary
18 | published
19 | }
20 |
21 | android {
22 | namespace = "dispatch.android.viewmodel"
23 | }
24 |
25 | dependencies {
26 | api(libs.androidx.lifecycle.viewModel.core)
27 | api(libs.kotlinx.coroutines.core)
28 | api(libs.kotlinx.coroutines.jvm)
29 |
30 | api(projects.dispatchCore)
31 |
32 | implementation(libs.androidx.lifecycle.viewModel.ktx)
33 | implementation(libs.kotlinx.coroutines.android)
34 |
35 | testImplementation(libs.androidx.test.espresso.core)
36 | testImplementation(libs.androidx.test.runner)
37 | testImplementation(libs.junit.jupiter)
38 | testImplementation(libs.kotest.assertions)
39 | testImplementation(libs.kotest.properties)
40 | testImplementation(libs.kotest.runner)
41 | testImplementation(libs.kotlinx.coroutines.test)
42 |
43 | testImplementation(projects.dispatchAndroidEspresso)
44 | testImplementation(projects.dispatchAndroidViewmodel)
45 | testImplementation(projects.dispatchInternalTest)
46 | testImplementation(projects.dispatchTest)
47 | }
48 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/dependencies/releaseRuntimeClasspath.txt:
--------------------------------------------------------------------------------
1 | androidx.annotation:annotation:1.1.0
2 | androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1
3 | androidx.lifecycle:lifecycle-viewmodel:2.5.1
4 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
5 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
6 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
7 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
8 | org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2
9 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
10 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
11 | org.jetbrains:annotations:13.0
12 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-android-viewmodel
16 | POM_NAME=dispatch-android-viewmodel
17 | POM_PACKAGING=aar
18 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/src/test/java/dispatch/android/viewmodel/samples/Application.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.viewmodel.samples
17 |
18 | interface Application {
19 | fun onCreate()
20 | }
21 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/src/test/java/dispatch/android/viewmodel/samples/ViewModelScopeFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.viewmodel.samples
17 |
18 | import dispatch.android.espresso.MainImmediateIdlingCoroutineScope
19 | import dispatch.android.viewmodel.ViewModelScopeFactory
20 | import dispatch.core.MainImmediateCoroutineScope
21 | import dispatch.internal.test.Sample5
22 | import dispatch.test.TestProvidedCoroutineScope
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 |
25 | @ExperimentalCoroutinesApi
26 | class ViewModelScopeFactorySample {
27 |
28 | @Sample5
29 | fun productionSample() {
30 |
31 | class MyApplication : Application {
32 |
33 | override fun onCreate() {
34 | ViewModelScopeFactory.set { MainImmediateCoroutineScope() }
35 | }
36 | }
37 | }
38 |
39 | @Sample5
40 | fun espressoSample() {
41 |
42 | class MyEspressoTest {
43 |
44 | @Before
45 | fun setUp() {
46 | ViewModelScopeFactory.set { MainImmediateIdlingCoroutineScope() }
47 | }
48 | }
49 | }
50 |
51 | @Sample5
52 | fun resetSample() {
53 |
54 | class MyEspressoTest {
55 |
56 | @Before
57 | fun setUp() {
58 | ViewModelScopeFactory.set { MainImmediateIdlingCoroutineScope() }
59 | }
60 |
61 | @After
62 | fun tearDown() {
63 | ViewModelScopeFactory.reset()
64 | }
65 | }
66 | }
67 |
68 | @Sample5
69 | fun jvmSample() {
70 |
71 | class MyJvmTest {
72 |
73 | @Before
74 | fun setUp() {
75 | ViewModelScopeFactory.set { TestProvidedCoroutineScope() }
76 | }
77 | }
78 | }
79 |
80 | private annotation class Before
81 | private annotation class After
82 | }
83 |
--------------------------------------------------------------------------------
/dispatch-android-viewmodel/src/test/java/dispatch/android/viewmodel/samples/ViewModelScopeSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.android.viewmodel.samples
17 |
18 | import dispatch.android.viewmodel.DispatchViewModel
19 | import dispatch.core.launchMain
20 | import dispatch.internal.test.Sample5
21 | import io.kotest.matchers.shouldBe
22 | import kotlinx.coroutines.ExperimentalCoroutinesApi
23 | import kotlinx.coroutines.isActive
24 |
25 | @Suppress("MemberNameEqualsClassName")
26 | @ExperimentalCoroutinesApi
27 | class ViewModelScopeSample {
28 |
29 | @Sample5
30 | fun viewModelScopeSample() {
31 |
32 | class SomeViewModel : DispatchViewModel() {
33 |
34 | init {
35 |
36 | // auto-created MainImmediateCoroutineScope which is auto-cancelled in onClear()
37 | viewModelScope // ...
38 |
39 | // it works as a normal CoroutineScope (because it is)
40 | viewModelScope.launchMain { }
41 |
42 | // this is the same CoroutineScope instance each time
43 | viewModelScope.launchMain { }
44 | }
45 |
46 | override fun onClear() {
47 | viewModelScope.isActive shouldBe false
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/dispatch-bom/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | `java-platform`
18 | published
19 | }
20 |
21 | version = project.extra.properties["VERSION_NAME"] as String
22 |
23 | val bomProject = project
24 |
25 | rootProject
26 | .subprojects
27 | .filter { it.includeInBom() }
28 | .forEach { bomProject.evaluationDependsOn(it.path) }
29 |
30 | dependencies {
31 | constraints {
32 | rootProject
33 | .subprojects
34 | .filter { it.includeInBom() }
35 | .forEach { api(project(it.path)) }
36 | }
37 | }
38 |
39 | publishing {
40 | publications {
41 | create("DispatchBom") {
42 | from(components["javaPlatform"])
43 | }
44 | }
45 | }
46 |
47 | fun Project.includeInBom() = !path.contains("sample") &&
48 | !path.contains("internal") &&
49 | this != bomProject
50 |
--------------------------------------------------------------------------------
/dispatch-bom/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-bom
16 | POM_NAME=dispatch-bom
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-core/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | javaLibrary
18 | published
19 | id("kotlinx-atomicfu")
20 | }
21 |
22 | dependencies {
23 |
24 | api(libs.kotlinx.coroutines.core)
25 | api(libs.kotlinx.coroutines.jvm)
26 |
27 | testImplementation(libs.hermit.jUnit5)
28 | testImplementation(libs.junit.jupiter)
29 | testImplementation(libs.kotest.assertions)
30 | testImplementation(libs.kotest.properties)
31 | testImplementation(libs.kotlin.test.common)
32 | testImplementation(libs.kotlin.test.core)
33 | testImplementation(libs.kotlinx.coroutines.test)
34 | testImplementation(libs.mockk)
35 |
36 | testImplementation(projects.dispatchInternalTest)
37 | }
38 |
--------------------------------------------------------------------------------
/dispatch-core/dependencies/runtimeClasspath.txt:
--------------------------------------------------------------------------------
1 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
2 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
3 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
4 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
5 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
6 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
7 | org.jetbrains:annotations:13.0
8 |
--------------------------------------------------------------------------------
/dispatch-core/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-core
16 | POM_NAME=dispatch-core
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-core/src/test/java/dispatch/core/samples/AsyncSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.samples
17 |
18 | import dispatch.core.asyncDefault
19 | import dispatch.core.asyncIO
20 | import dispatch.core.asyncMain
21 | import dispatch.core.asyncMainImmediate
22 | import dispatch.core.asyncUnconfined
23 | import dispatch.internal.test.Sample5
24 | import dispatch.internal.test.dispatcherName
25 | import dispatch.internal.test.someDispatcherProvider
26 | import io.kotest.matchers.shouldBe
27 | import kotlinx.coroutines.runBlocking
28 |
29 | class AsyncSample {
30 |
31 | @Sample5
32 | fun asyncDefaultSample() = runBlocking(someDispatcherProvider) {
33 |
34 | dispatcherName() shouldBe "runBlocking thread"
35 |
36 | asyncDefault {
37 |
38 | dispatcherName() shouldBe "default"
39 | }.join()
40 | }
41 |
42 | @Sample5
43 | fun asyncIOSample() = runBlocking(someDispatcherProvider) {
44 |
45 | dispatcherName() shouldBe "runBlocking thread"
46 |
47 | asyncIO {
48 |
49 | dispatcherName() shouldBe "io"
50 | }.join()
51 | }
52 |
53 | @Sample5
54 | fun asyncMainSample() = runBlocking(someDispatcherProvider) {
55 |
56 | dispatcherName() shouldBe "runBlocking thread"
57 |
58 | asyncMain {
59 |
60 | dispatcherName() shouldBe "main"
61 | }.join()
62 | }
63 |
64 | @Sample5
65 | fun asyncMainImmediateSample() = runBlocking(someDispatcherProvider) {
66 |
67 | dispatcherName() shouldBe "runBlocking thread"
68 |
69 | asyncMainImmediate {
70 |
71 | dispatcherName() shouldBe "main immediate"
72 | }.join()
73 | }
74 |
75 | @Sample5
76 | fun asyncUnconfinedSample() = runBlocking(someDispatcherProvider) {
77 |
78 | dispatcherName() shouldBe "runBlocking thread"
79 |
80 | asyncUnconfined {
81 |
82 | dispatcherName() shouldBe "unconfined"
83 | }.join()
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/dispatch-core/src/test/java/dispatch/core/samples/DispatcherProviderCopySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.samples
17 |
18 | import dispatch.core.dispatcherProvider
19 | import dispatch.internal.test.Sample5
20 | import io.kotest.matchers.shouldBe
21 | import kotlinx.coroutines.CoroutineDispatcher
22 | import kotlinx.coroutines.Dispatchers
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import kotlinx.coroutines.Runnable
25 | import kotlinx.coroutines.currentCoroutineContext
26 | import kotlinx.coroutines.runBlocking
27 | import kotlinx.coroutines.test.resetMain
28 | import kotlinx.coroutines.test.setMain
29 | import kotlinx.coroutines.withContext
30 | import kotlin.coroutines.CoroutineContext
31 |
32 | @Suppress("HardCodedDispatcher")
33 | @OptIn(
34 | ExperimentalStdlibApi::class,
35 | ExperimentalCoroutinesApi::class
36 | )
37 | class DispatcherProviderCopySample {
38 |
39 | @Sample5
40 | fun testCopySample() = runBlocking {
41 |
42 | Dispatchers.setMain(coroutineContext[CoroutineDispatcher.Key]!!)
43 |
44 | copySample()
45 |
46 | Dispatchers.resetMain()
47 | }
48 |
49 | suspend fun copySample() {
50 | val originalDispatcherProvider = currentCoroutineContext().dispatcherProvider
51 | originalDispatcherProvider.main shouldBe Dispatchers.Main
52 |
53 | val newMain = MyCustomBlockingQueueDispatcher()
54 | // create a copy of the existing DispatcherProvider, except the new main dispatcher
55 | val bleDispatchers = originalDispatcherProvider.copy(main = newMain)
56 |
57 | withContext(bleDispatchers) {
58 | // any coroutine downstream of this `withContext { }` will use the redefined main dispatcher
59 | dispatcherProvider.main shouldBe newMain
60 | }
61 | }
62 |
63 | private class MyCustomBlockingQueueDispatcher : CoroutineDispatcher() {
64 | override fun dispatch(context: CoroutineContext, block: Runnable) {
65 | block.run()
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/dispatch-core/src/test/java/dispatch/core/samples/LaunchSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.samples
17 |
18 | import dispatch.core.launchDefault
19 | import dispatch.core.launchIO
20 | import dispatch.core.launchMain
21 | import dispatch.core.launchMainImmediate
22 | import dispatch.core.launchUnconfined
23 | import dispatch.internal.test.Sample5
24 | import dispatch.internal.test.dispatcherName
25 | import dispatch.internal.test.someDispatcherProvider
26 | import io.kotest.matchers.shouldBe
27 | import kotlinx.coroutines.runBlocking
28 |
29 | class LaunchSample {
30 |
31 | @Sample5
32 | fun launchDefaultSample() = runBlocking(someDispatcherProvider) {
33 |
34 | dispatcherName() shouldBe "runBlocking thread"
35 |
36 | launchDefault {
37 |
38 | dispatcherName() shouldBe "default"
39 | }.join()
40 | }
41 |
42 | @Sample5
43 | fun launchIOSample() = runBlocking(someDispatcherProvider) {
44 |
45 | dispatcherName() shouldBe "runBlocking thread"
46 |
47 | launchIO {
48 |
49 | dispatcherName() shouldBe "io"
50 | }.join()
51 | }
52 |
53 | @Sample5
54 | fun launchMainSample() = runBlocking(someDispatcherProvider) {
55 |
56 | dispatcherName() shouldBe "runBlocking thread"
57 |
58 | launchMain {
59 |
60 | dispatcherName() shouldBe "main"
61 | }.join()
62 | }
63 |
64 | @Sample5
65 | fun launchMainImmediateSample() = runBlocking(someDispatcherProvider) {
66 |
67 | dispatcherName() shouldBe "runBlocking thread"
68 |
69 | launchMainImmediate {
70 |
71 | dispatcherName() shouldBe "main immediate"
72 | }.join()
73 | }
74 |
75 | @Sample5
76 | fun launchUnconfinedSample() = runBlocking(someDispatcherProvider) {
77 |
78 | dispatcherName() shouldBe "runBlocking thread"
79 |
80 | launchUnconfined {
81 |
82 | dispatcherName() shouldBe "unconfined"
83 | }.join()
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/dispatch-core/src/test/java/dispatch/core/samples/WithContextSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.samples
17 |
18 | import dispatch.core.withDefault
19 | import dispatch.core.withIO
20 | import dispatch.core.withMain
21 | import dispatch.core.withMainImmediate
22 | import dispatch.core.withUnconfined
23 | import dispatch.internal.test.Sample5
24 | import dispatch.internal.test.dispatcherName
25 | import dispatch.internal.test.someDispatcherProvider
26 | import io.kotest.matchers.shouldBe
27 | import kotlinx.coroutines.runBlocking
28 |
29 | class WithContextSample {
30 |
31 | @Sample5
32 | fun withDefaultSample() = runBlocking(someDispatcherProvider) {
33 |
34 | dispatcherName() shouldBe "runBlocking thread"
35 |
36 | withDefault {
37 |
38 | dispatcherName() shouldBe "default"
39 | }
40 | }
41 |
42 | @Sample5
43 | fun withIOSample() = runBlocking(someDispatcherProvider) {
44 |
45 | dispatcherName() shouldBe "runBlocking thread"
46 |
47 | withIO {
48 |
49 | dispatcherName() shouldBe "io"
50 | }
51 | }
52 |
53 | @Sample5
54 | fun withMainSample() = runBlocking(someDispatcherProvider) {
55 |
56 | dispatcherName() shouldBe "runBlocking thread"
57 |
58 | withMain {
59 |
60 | dispatcherName() shouldBe "main"
61 | }
62 | }
63 |
64 | @Sample5
65 | fun withMainImmediateSample() = runBlocking(someDispatcherProvider) {
66 |
67 | dispatcherName() shouldBe "runBlocking thread"
68 |
69 | withMainImmediate {
70 |
71 | dispatcherName() shouldBe "main immediate"
72 | }
73 | }
74 |
75 | @Sample5
76 | fun withUnconfinedSample() = runBlocking(someDispatcherProvider) {
77 |
78 | dispatcherName() shouldBe "runBlocking thread"
79 |
80 | withUnconfined {
81 |
82 | dispatcherName() shouldBe "unconfined"
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/dispatch-detekt/api/dispatch-detekt.api:
--------------------------------------------------------------------------------
1 | public final class dispatch/detekt/ConfigError : io/gitlab/arturbosch/detekt/api/Notification {
2 | public fun (Ljava/lang/String;Lio/gitlab/arturbosch/detekt/api/Notification$Level;)V
3 | public synthetic fun (Ljava/lang/String;Lio/gitlab/arturbosch/detekt/api/Notification$Level;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
4 | public fun getLevel ()Lio/gitlab/arturbosch/detekt/api/Notification$Level;
5 | public fun getMessage ()Ljava/lang/String;
6 | public fun isError ()Z
7 | }
8 |
9 | public final class dispatch/detekt/DispatchConfigValidator : io/gitlab/arturbosch/detekt/api/ConfigValidator {
10 | public fun ()V
11 | public fun getId ()Ljava/lang/String;
12 | public fun getPriority ()I
13 | public fun init (Lio/gitlab/arturbosch/detekt/api/Config;)V
14 | public fun init (Lio/gitlab/arturbosch/detekt/api/SetupContext;)V
15 | public fun validate (Lio/gitlab/arturbosch/detekt/api/Config;)Ljava/util/Collection;
16 | }
17 |
18 | public final class dispatch/detekt/DispatchRuleSetProvider : io/gitlab/arturbosch/detekt/api/RuleSetProvider {
19 | public fun ()V
20 | public fun getRuleSetId ()Ljava/lang/String;
21 | public fun instance (Lio/gitlab/arturbosch/detekt/api/Config;)Lio/gitlab/arturbosch/detekt/api/RuleSet;
22 | }
23 |
24 | public final class dispatch/detekt/rules/AndroidXLifecycleScope : io/gitlab/arturbosch/detekt/api/Rule {
25 | public fun ()V
26 | public fun (Lio/gitlab/arturbosch/detekt/api/Config;)V
27 | public synthetic fun (Lio/gitlab/arturbosch/detekt/api/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
28 | public fun getIssue ()Lio/gitlab/arturbosch/detekt/api/Issue;
29 | public fun visitImportDirective (Lorg/jetbrains/kotlin/psi/KtImportDirective;)V
30 | public fun visitReferenceExpression (Lorg/jetbrains/kotlin/psi/KtReferenceExpression;)V
31 | }
32 |
33 | public final class dispatch/detekt/rules/HardCodedDispatcher : io/gitlab/arturbosch/detekt/api/Rule {
34 | public fun ()V
35 | public fun (Lio/gitlab/arturbosch/detekt/api/Config;)V
36 | public synthetic fun (Lio/gitlab/arturbosch/detekt/api/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
37 | public fun getIssue ()Lio/gitlab/arturbosch/detekt/api/Issue;
38 | public fun visitDotQualifiedExpression (Lorg/jetbrains/kotlin/psi/KtDotQualifiedExpression;)V
39 | public fun visitImportDirective (Lorg/jetbrains/kotlin/psi/KtImportDirective;)V
40 | public fun visitReferenceExpression (Lorg/jetbrains/kotlin/psi/KtReferenceExpression;)V
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/dispatch-detekt/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | javaLibrary
18 | published
19 | }
20 |
21 | dependencies {
22 |
23 | api(libs.detekt.api)
24 | api(libs.kotlin.compiler)
25 |
26 | testImplementation(libs.detekt.test)
27 | testImplementation(libs.junit.api)
28 | testImplementation(libs.kotest.assertions)
29 | testImplementation(libs.kotest.properties)
30 | testImplementation(libs.kotest.runner)
31 |
32 | testRuntimeOnly(libs.junit.engine)
33 | testRuntimeOnly(libs.junit.vintage)
34 | }
35 |
--------------------------------------------------------------------------------
/dispatch-detekt/dependencies/runtimeClasspath.txt:
--------------------------------------------------------------------------------
1 | io.gitlab.arturbosch.detekt:detekt-api:1.21.0
2 | io.gitlab.arturbosch.detekt:detekt-psi-utils:1.21.0
3 | io.gitlab.arturbosch.detekt:detekt-utils:1.21.0
4 | net.java.dev.jna:jna:5.6.0
5 | org.jetbrains.intellij.deps:trove4j:1.0.20200330
6 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10
7 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10
8 | org.jetbrains.kotlin:kotlin-reflect:1.7.10
9 | org.jetbrains.kotlin:kotlin-script-runtime:1.7.10
10 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
11 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
12 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
13 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
14 | org.jetbrains:annotations:13.0
15 |
--------------------------------------------------------------------------------
/dispatch-detekt/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-detekt
16 | POM_NAME=dispatch-detekt
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-detekt/src/main/java/dispatch/detekt/DispatchRuleSetProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.detekt
17 |
18 | import dispatch.detekt.rules.AndroidXLifecycleScope
19 | import dispatch.detekt.rules.HardCodedDispatcher
20 | import io.gitlab.arturbosch.detekt.api.Config
21 | import io.gitlab.arturbosch.detekt.api.RuleSet
22 | import io.gitlab.arturbosch.detekt.api.RuleSetProvider
23 |
24 | /** @suppress */
25 | public class DispatchRuleSetProvider : RuleSetProvider {
26 |
27 | override val ruleSetId: String = "dispatch"
28 |
29 | override fun instance(config: Config): RuleSet = RuleSet(
30 | id = ruleSetId,
31 | rules = listOf(
32 | AndroidXLifecycleScope(config),
33 | HardCodedDispatcher(config)
34 | )
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/dispatch-detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.ConfigValidator:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 |
16 | #
17 | # Copyright (C) 2020 Rick Busarow
18 | # Licensed under the Apache License, Version 2.0 (the "License");
19 | # you may not use this file except in compliance with the License.
20 | # You may obtain a copy of the License at
21 | #
22 | # http://www.apache.org/licenses/LICENSE-2.0
23 | #
24 | # Unless required by applicable law or agreed to in writing, software
25 | # distributed under the License is distributed on an "AS IS" BASIS,
26 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 | # See the License for the specific language governing permissions and
28 | # limitations under the License.
29 | #
30 |
31 | #
32 | # Copyright (C) 2020 Rick Busarow
33 | # Licensed under the Apache License, Version 2.0 (the "License");
34 | # you may not use this file except in compliance with the License.
35 | # You may obtain a copy of the License at
36 | #
37 | # http://www.apache.org/licenses/LICENSE-2.0
38 | #
39 | # Unless required by applicable law or agreed to in writing, software
40 | # distributed under the License is distributed on an "AS IS" BASIS,
41 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42 | # See the License for the specific language governing permissions and
43 | # limitations under the License.
44 | #
45 |
46 | dispatch.detekt.DispatchConfigValidator
47 |
--------------------------------------------------------------------------------
/dispatch-detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 |
16 | dispatch.detekt.DispatchRuleSetProvider
17 |
--------------------------------------------------------------------------------
/dispatch-detekt/src/test/java/dispatch/detekt/rules/util.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.detekt.rules
17 |
18 | import io.gitlab.arturbosch.detekt.api.Finding
19 |
20 | val List.messages: List
21 | get() = map { it.message }
22 |
--------------------------------------------------------------------------------
/dispatch-internal-test-android/api/dispatch-internal-test-android.api:
--------------------------------------------------------------------------------
1 | public final class dispatch/internal/test/android/BuildConfig {
2 | public static final field BUILD_TYPE Ljava/lang/String;
3 | public static final field DEBUG Z
4 | public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String;
5 | public static final field VERSION_CODE I
6 | public static final field VERSION_NAME Ljava/lang/String;
7 | public fun ()V
8 | }
9 |
10 | public class dispatch/internal/test/android/FakeFragment : androidx/fragment/app/Fragment {
11 | public fun (Landroidx/lifecycle/LifecycleOwner;)V
12 | public fun getLifecycle ()Landroidx/lifecycle/Lifecycle;
13 | public fun getViewLifecycleOwner ()Landroidx/lifecycle/LifecycleOwner;
14 | public fun getViewLifecycleOwnerLiveData ()Landroidx/lifecycle/LiveData;
15 | public fun setFakeViewLifecycleOwner (Landroidx/lifecycle/LifecycleOwner;)V
16 | }
17 |
18 | public class dispatch/internal/test/android/FakeLifecycleOwner : androidx/lifecycle/LifecycleOwner {
19 | public fun ()V
20 | public fun (Lkotlinx/coroutines/CoroutineDispatcher;Landroidx/lifecycle/Lifecycle$State;)V
21 | public synthetic fun (Lkotlinx/coroutines/CoroutineDispatcher;Landroidx/lifecycle/Lifecycle$State;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
22 | public final fun create ()V
23 | public final fun destroy ()V
24 | public synthetic fun getLifecycle ()Landroidx/lifecycle/Lifecycle;
25 | public fun getLifecycle ()Landroidx/lifecycle/LifecycleRegistry;
26 | public final fun getObserverCount ()I
27 | public final fun initialize ()V
28 | public final fun pause ()V
29 | public final fun resume ()V
30 | public final fun start ()V
31 | public final fun stop ()V
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/dispatch-internal-test-android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | androidLibrary
18 | }
19 |
20 | android {
21 | namespace = "dispatch.internal.test.android"
22 | }
23 |
24 | dependencies {
25 |
26 | api(libs.androidx.fragment.core)
27 | api(libs.androidx.lifecycle.common)
28 | api(libs.androidx.lifecycle.liveData)
29 | api(libs.androidx.lifecycle.runtime)
30 | api(libs.junit.api)
31 | api(libs.kotlinx.coroutines.core)
32 | api(libs.kotlinx.coroutines.jvm)
33 |
34 | implementation(libs.androidx.lifecycle.runtimeKtx)
35 | implementation(libs.kotlin.reflect)
36 | implementation(libs.kotlinx.coroutines.android)
37 | }
38 |
--------------------------------------------------------------------------------
/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test.android;
17 |
18 | import androidx.annotation.NonNull;
19 | import androidx.fragment.app.Fragment;
20 | import androidx.lifecycle.Lifecycle;
21 | import androidx.lifecycle.LifecycleOwner;
22 | import androidx.lifecycle.LiveData;
23 | import androidx.lifecycle.MutableLiveData;
24 |
25 | import org.jetbrains.annotations.Nullable;
26 |
27 | public class FakeFragment extends Fragment {
28 |
29 | LifecycleOwner fragmentLifecycleOwner;
30 | MutableLiveData fakeViewLifecycleOwnerLiveData = new MutableLiveData<>(null);
31 | private LifecycleOwner fakeViewLifecycleOwner = null;
32 |
33 | public FakeFragment(@Nullable LifecycleOwner fragmentLifecycleOwner) {
34 | this.fragmentLifecycleOwner = fragmentLifecycleOwner;
35 | }
36 |
37 | public void setFakeViewLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) {
38 | fakeViewLifecycleOwner = lifecycleOwner;
39 | fakeViewLifecycleOwnerLiveData.postValue(lifecycleOwner);
40 | }
41 |
42 | @NonNull
43 | @Override
44 | public LifecycleOwner getViewLifecycleOwner() {
45 | return fakeViewLifecycleOwner;
46 | }
47 |
48 | @NonNull
49 | @Override
50 | public LiveData getViewLifecycleOwnerLiveData() {
51 | return fakeViewLifecycleOwnerLiveData;
52 | }
53 |
54 | @NonNull
55 | @Override
56 | public Lifecycle getLifecycle() {
57 | return fragmentLifecycleOwner.getLifecycle();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/FakeLifecycle.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test.android
17 |
18 | import androidx.lifecycle.Lifecycle
19 | import androidx.lifecycle.LifecycleObserver
20 | import androidx.lifecycle.LifecycleRegistry
21 | import kotlinx.coroutines.channels.BufferOverflow
22 | import kotlinx.coroutines.flow.MutableSharedFlow
23 |
24 | class FakeLifecycle(lifecycleOwner: FakeLifecycleOwner) : Lifecycle() {
25 |
26 | val delegate = LifecycleRegistry(lifecycleOwner)
27 |
28 | val observerEvents = MutableSharedFlow(
29 | replay = 1,
30 | onBufferOverflow = BufferOverflow.DROP_OLDEST
31 | )
32 |
33 | val observerCount: Int get() = delegate.observerCount
34 |
35 | sealed class ObserverEvent {
36 | abstract val observer: LifecycleObserver
37 |
38 | data class Add(override val observer: LifecycleObserver) : ObserverEvent()
39 | data class Remove(override val observer: LifecycleObserver) : ObserverEvent()
40 | }
41 |
42 | override fun addObserver(observer: LifecycleObserver) {
43 | delegate.addObserver(observer)
44 | observerEvents.tryEmit(ObserverEvent.Add(observer))
45 | }
46 |
47 | override fun removeObserver(observer: LifecycleObserver) {
48 | delegate.removeObserver(observer)
49 | observerEvents.tryEmit(ObserverEvent.Remove(observer))
50 | }
51 |
52 | override fun getCurrentState(): State = delegate.currentState
53 | fun setCurrentState(state: State) {
54 | delegate.currentState = state
55 | }
56 |
57 | fun handleLifecycleEvent(event: Event) {
58 | delegate.handleLifecycleEvent(event)
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/dispatch-internal-test-android/src/main/java/dispatch/internal/test/android/InstantTaskExecutorExtension.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test.android
17 |
18 | import androidx.arch.core.executor.ArchTaskExecutor
19 | import androidx.arch.core.executor.TaskExecutor
20 | import org.junit.jupiter.api.extension.BeforeAllCallback
21 | import org.junit.jupiter.api.extension.ExtendWith
22 | import org.junit.jupiter.api.extension.ExtensionContext
23 |
24 | @ExtendWith(InstantTaskExecutorExtension::class)
25 | interface LiveDataTest
26 |
27 | @Suppress("RestrictedApi")
28 | class InstantTaskExecutorExtension : BeforeAllCallback {
29 |
30 | override fun beforeAll(context: ExtensionContext?) {
31 | ArchTaskExecutor.getInstance()
32 | .setDelegate(object : TaskExecutor() {
33 | override fun executeOnDiskIO(runnable: Runnable) {
34 | runnable.run()
35 | }
36 |
37 | override fun postToMainThread(runnable: Runnable) {
38 | runnable.run()
39 | }
40 |
41 | override fun isMainThread(): Boolean = true
42 | })
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/dispatch-internal-test/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("kotlinx-atomicfu")
18 | javaLibrary
19 | }
20 |
21 | dependencies {
22 |
23 | api(libs.junit.api)
24 | api(libs.junit.junit4)
25 | api(libs.junit.jupiter)
26 | api(libs.junit.vintage)
27 | api(libs.kotest.assertions)
28 | api(libs.kotest.assertionsShared)
29 | api(libs.kotest.common.jvm)
30 | api(libs.kotest.runner)
31 | api(libs.kotlin.reflect)
32 | api(libs.kotlin.test.common)
33 | api(libs.kotlin.test.core)
34 | api(libs.kotlinx.coroutines.core)
35 | api(libs.kotlinx.coroutines.jvm)
36 | api(libs.kotlinx.coroutines.test)
37 | api(libs.kotlinx.knit.test)
38 |
39 | api(projects.dispatchCore)
40 | }
41 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/main/java/dispatch/internal/test/AtomicCounterExtension.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import kotlinx.atomicfu.atomic
19 | import org.junit.jupiter.api.extension.AfterEachCallback
20 | import org.junit.jupiter.api.extension.ExtensionContext
21 |
22 | public class AtomicCounterExtension : AfterEachCallback {
23 |
24 | private val index = atomic(0)
25 | private val finished = atomic(false)
26 |
27 | public fun expect(expectedIndex: Int) {
28 |
29 | val actualIndex = index.incrementAndGet()
30 |
31 | assert(expectedIndex == actualIndex) {
32 | "Expecting action index $expectedIndex but it is actually $actualIndex"
33 | }
34 | }
35 |
36 | public fun finish(expectedIndex: Int) {
37 | expect(expectedIndex)
38 | assert(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" }
39 | }
40 |
41 | override fun afterEach(context: ExtensionContext?) {
42 | resetIndex()
43 | }
44 |
45 | public fun resetIndex() {
46 | assert(index.value == 0) { "Expecting that 'finish(...)' was invoked, but it was not" }
47 | index.value = 0
48 | finished.value = false
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/main/java/dispatch/internal/test/BaseTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import io.kotest.matchers.shouldBe
19 | import kotlinx.atomicfu.atomic
20 | import org.junit.jupiter.api.AfterEach
21 |
22 | @Suppress("UnnecessaryAbstractClass")
23 | public abstract class BaseTest {
24 |
25 | private val index = atomic(0)
26 | private val finished = atomic(false)
27 |
28 | @AfterEach
29 | internal fun _afterEach() {
30 | resetIndex()
31 | }
32 |
33 | public fun expect(expectedIndex: Int) {
34 |
35 | val actualIndex = index.incrementAndGet()
36 |
37 | actualIndex shouldBe expectedIndex
38 | }
39 |
40 | public fun finish(expectedIndex: Int) {
41 | expect(expectedIndex)
42 | require(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" }
43 | }
44 |
45 | public fun resetIndex() {
46 | try {
47 | require(index.value == 0 || finished.value) { "Expecting that 'finish(...)' was invoked, but it was not" }
48 | } finally {
49 | index.value = 0
50 | finished.value = false
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/main/java/dispatch/internal/test/ExpectedFailureRule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import io.kotest.matchers.shouldBe
19 | import org.junit.rules.TestRule
20 | import org.junit.runner.Description
21 | import org.junit.runners.model.Statement
22 |
23 | public class ExpectedFailureRule : TestRule {
24 |
25 | override fun apply(
26 | base: Statement,
27 | description: Description
28 | ): Statement = object : Statement() {
29 |
30 | override fun evaluate() {
31 | try {
32 |
33 | base.evaluate()
34 | } catch (e: Error) {
35 |
36 | val failsAnnotation = description.getAnnotation(Fails::class.java)
37 |
38 | if (failsAnnotation != null) {
39 | failsAnnotation.expected shouldBe e::class
40 | } else {
41 | throw e
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/main/java/dispatch/internal/test/Fails.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import kotlin.reflect.KClass
19 |
20 | /** Indicates that a test **function** is expected to fail with the given exception type. */
21 | @Target(AnnotationTarget.FUNCTION)
22 | public annotation class Fails(
23 | /** The KClass of the expected Throwable. */
24 | val expected: KClass<*>
25 | )
26 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/main/java/dispatch/internal/test/reflect.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import kotlin.reflect.full.memberProperties
19 | import kotlin.reflect.jvm.isAccessible
20 |
21 | public inline fun T.getPrivateObjectFieldByName(
22 | name: String
23 | ): R {
24 |
25 | val kClass = T::class
26 |
27 | val property = kClass.members.find { it.name == name }
28 |
29 | require(property != null) { "Cannot find a property named `$name` in ${kClass::qualifiedName}." }
30 |
31 | property.isAccessible = true
32 |
33 | return property.call() as R
34 | }
35 |
36 | public inline fun T.getPrivateFieldByName(name: String): R {
37 |
38 | val kClass = T::class
39 |
40 | val property = kClass.memberProperties.find { it.name == name }
41 |
42 | require(property != null) { "Cannot find a property named `$name` in ${kClass::qualifiedName}." }
43 |
44 | property.isAccessible = true
45 |
46 | return property.get(this) as R
47 | }
48 |
--------------------------------------------------------------------------------
/dispatch-internal-test/src/test/java/dispatch/internal/test/AssertionsTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.internal.test
17 |
18 | import kotlinx.coroutines.Job
19 | import kotlinx.coroutines.SupervisorJob
20 | import kotlinx.coroutines.launch
21 | import kotlinx.coroutines.runBlocking
22 | import org.junit.jupiter.api.Nested
23 | import org.junit.jupiter.api.Test
24 | import kotlin.test.assertFails
25 |
26 | internal class AssertionsTest {
27 |
28 | @Nested
29 | inner class `should be SupervisorJob` {
30 |
31 | @Test
32 | fun `normal Job should fail`() {
33 |
34 | assertFails { Job().shouldBeSupervisorJob() }
35 | }
36 |
37 | @Test
38 | fun `SupervisorJob should pass`() {
39 |
40 | SupervisorJob().shouldBeSupervisorJob()
41 | }
42 | }
43 |
44 | @Nested
45 | inner class `should be or child of` {
46 |
47 | @Test
48 | fun `referential equality should pass`() {
49 |
50 | val job = Job()
51 |
52 | job shouldBeOrChildOf job
53 | }
54 |
55 | @Test
56 | fun `receiver job as child of parameter should pass`() = runBlocking a@{
57 |
58 | launch b@{
59 | this@b.coroutineContext[Job]!! shouldBeOrChildOf this@a.coroutineContext[Job]!!
60 | }.join()
61 | }
62 |
63 | @Test
64 | fun `parameter job as child of receiver should fail`() = runBlocking a@{
65 |
66 | launch b@{
67 | assertFails {
68 | this@a.coroutineContext[Job]!! shouldBeOrChildOf this@b.coroutineContext[Job]!!
69 | }
70 | }
71 | }
72 |
73 | @Test
74 | fun `unrelated jobs should fail`() {
75 |
76 | val a = Job()
77 | val b = Job()
78 |
79 | assertFails { a shouldBeOrChildOf b }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/dispatch-sample/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("com.android.application")
18 | kotlin("android")
19 | id("kotlin-parcelize")
20 | }
21 |
22 | android {
23 | commonAndroid(project)
24 |
25 | @Suppress("UnstableApiUsage")
26 | buildFeatures.viewBinding = true
27 | }
28 |
29 | dependencies {
30 |
31 | androidTestImplementation(libs.androidx.test.espresso.core)
32 | androidTestImplementation(libs.androidx.test.runner)
33 |
34 | api(projects.dispatchCore)
35 |
36 | implementation(libs.androidx.activity.ktx)
37 | implementation(libs.androidx.appcompat)
38 | implementation(libs.androidx.constraintLayout)
39 | implementation(libs.androidx.coreKtx)
40 | implementation(libs.androidx.fragment.ktx)
41 | implementation(libs.androidx.lifecycle.common)
42 | implementation(libs.kotlinx.coroutines.android)
43 | implementation(libs.kotlinx.coroutines.core)
44 | implementation(libs.timber)
45 |
46 | implementation(projects.dispatchAndroidLifecycle)
47 |
48 | testImplementation(libs.junit.junit4)
49 | testImplementation(libs.junit.jupiter)
50 | testImplementation(libs.kotest.assertions)
51 | testImplementation(libs.kotest.properties)
52 | testImplementation(libs.kotest.runner)
53 | testImplementation(libs.kotlinx.coroutines.test)
54 | }
55 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
18 |
19 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/java/dispatch/sample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.sample
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 | import dispatch.sample.databinding.ActivityMainBinding
21 | import kotlinx.coroutines.ExperimentalCoroutinesApi
22 | import timber.log.Timber
23 |
24 | @ExperimentalCoroutinesApi
25 | class MainActivity : AppCompatActivity() {
26 |
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | setContentView(ActivityMainBinding.inflate(layoutInflater).root)
30 |
31 | Timber.plant(Timber.DebugTree())
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/java/dispatch/sample/MainViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.sample
17 |
18 | import androidx.lifecycle.ViewModel
19 | import dispatch.core.DefaultCoroutineScope
20 | import dispatch.core.defaultDispatcher
21 | import kotlinx.coroutines.CompletableDeferred
22 | import kotlinx.coroutines.Deferred
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import kotlinx.coroutines.cancel
25 | import kotlinx.coroutines.delay
26 | import kotlinx.coroutines.flow.flow
27 | import kotlinx.coroutines.flow.flowOn
28 | import kotlinx.coroutines.launch
29 |
30 | @ExperimentalCoroutinesApi
31 | class MainViewModel(
32 | val coroutineScope: DefaultCoroutineScope,
33 | val repository: SomeRepository
34 | ) : ViewModel() {
35 |
36 | val expensiveDeferred: Deferred = repository.getSomethingExpensiveUnstructured()
37 |
38 | val alsoExpensiveDeferred: Deferred by lazy {
39 | CompletableDeferred().also { completable ->
40 |
41 | // this no-arg launch will use the default CoroutineDispatcher in the CoroutineScope,
42 | // which in this case is dispatcherProvider.default
43 | coroutineScope.launch {
44 | val expensive = repository.getSomethingExpensive()
45 | completable.complete(expensive)
46 | }
47 | }
48 | }
49 |
50 | val message = flow {
51 |
52 | emit("Get ready for some coroutine stuff...")
53 |
54 | emit(expensiveDeferred.await())
55 |
56 | emit(alsoExpensiveDeferred.await())
57 |
58 | @Suppress("MagicNumber")
59 | delay(5000)
60 |
61 | // explicitly specify the default dispatcher (which is redundant here, but it's an example)
62 | }.flowOn(coroutineScope.defaultDispatcher)
63 |
64 | override fun onCleared() {
65 | super.onCleared()
66 |
67 | coroutineScope.cancel()
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/java/dispatch/sample/SomeRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.sample
17 |
18 | import dispatch.core.IOCoroutineScope
19 | import dispatch.core.asyncIO
20 | import dispatch.core.withIO
21 | import kotlinx.coroutines.delay
22 |
23 | /**
24 | * This would normally be a singleton, but we don't have a DI framework here, so we'll just
25 | * _suspend_ disbelief.
26 | */
27 | class SomeRepository(private val coroutineScope: IOCoroutineScope) {
28 |
29 | @Suppress("MagicNumber")
30 | suspend fun getSomethingExpensive() = withIO {
31 | delay(5000)
32 | "suspend function is complete!"
33 | }
34 |
35 | @Suppress("MagicNumber")
36 | fun getSomethingExpensiveUnstructured() = coroutineScope.asyncIO {
37 | delay(5000)
38 | "deferred function is complete!"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
21 |
22 |
32 |
33 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
21 |
22 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/dispatch-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 | #3D92FC
19 | #102572
20 | #0151DB
21 |
22 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 | #38DA00
19 |
20 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | Dispatch Sample
18 |
19 |
--------------------------------------------------------------------------------
/dispatch-sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/api/dispatch-test-junit4.api:
--------------------------------------------------------------------------------
1 | public final class dispatch/test/TestCoroutineRule : org/junit/rules/TestWatcher, dispatch/test/TestProvidedCoroutineScope {
2 | public fun ()V
3 | public fun (Lkotlin/jvm/functions/Function0;)V
4 | public synthetic fun (Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
5 | public fun advanceTimeBy (J)J
6 | public fun advanceUntilIdle ()J
7 | public fun cleanupTestCoroutines ()V
8 | public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
9 | public fun getCurrentTime ()J
10 | public final fun getDispatcher ()Lkotlinx/coroutines/test/TestCoroutineDispatcher;
11 | public fun getDispatcherProvider ()Ldispatch/core/DispatcherProvider;
12 | public fun getUncaughtExceptions ()Ljava/util/List;
13 | public fun pauseDispatcher ()V
14 | public fun pauseDispatcher (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
15 | public fun resumeDispatcher ()V
16 | public fun runCurrent ()V
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("kotlinx-atomicfu")
18 | javaLibrary
19 | published
20 | }
21 |
22 | dependencies {
23 |
24 | api(libs.junit.junit4)
25 | api(libs.kotlinx.coroutines.test)
26 |
27 | api(projects.dispatchTest)
28 |
29 | implementation(libs.kotlinx.coroutines.core)
30 | implementation(libs.kotlinx.coroutines.jvm)
31 |
32 | testImplementation(libs.kotest.assertions)
33 | testImplementation(libs.kotest.properties)
34 | testImplementation(libs.kotest.runner)
35 | testImplementation(libs.kotlin.test.common)
36 | testImplementation(libs.kotlin.test.core)
37 | testImplementation(libs.mockk)
38 |
39 | testImplementation(projects.dispatchCore)
40 | testImplementation(projects.dispatchInternalTest)
41 | }
42 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/dependencies/runtimeClasspath.txt:
--------------------------------------------------------------------------------
1 | junit:junit:4.13.2
2 | net.java.dev.jna:jna-platform:5.5.0
3 | net.java.dev.jna:jna:5.5.0
4 | org.hamcrest:hamcrest-core:1.3
5 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
6 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
7 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
8 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
9 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
10 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
11 | org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.5.2
12 | org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.2
13 | org.jetbrains:annotations:13.0
14 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-test-junit4
16 | POM_NAME=dispatch-test-junit4
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/src/test/kotlin/dispatch/core/test/samples/TestCoroutineRuleSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.test.samples
17 |
18 | import dispatch.test.TestCoroutineRule
19 | import dispatch.test.TestProvidedCoroutineScope
20 | import io.kotest.matchers.types.shouldBeInstanceOf
21 | import kotlinx.coroutines.ExperimentalCoroutinesApi
22 | import kotlinx.coroutines.launch
23 | import kotlinx.coroutines.runBlocking
24 | import org.junit.Rule
25 | import org.junit.Test
26 |
27 | @ExperimentalCoroutinesApi
28 | class TestCoroutineRuleSample {
29 |
30 | @JvmField
31 | @Rule
32 | val rule = TestCoroutineRule()
33 |
34 | @Test
35 | fun `rule should be a TestProvidedCoroutineScope`() = runBlocking {
36 |
37 | rule.shouldBeInstanceOf()
38 |
39 | rule.launch {
40 | // use the rule like any other CoroutineScope
41 | }
42 | .join()
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/dispatch-test-junit4/src/test/kotlin/dispatch/core/test/samples/TestCoroutineRuleWithFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.core.test.samples
17 |
18 | import dispatch.test.TestCoroutineRule
19 | import dispatch.test.TestProvidedCoroutineScope
20 | import io.kotest.matchers.shouldBe
21 | import io.kotest.matchers.types.shouldBeInstanceOf
22 | import kotlinx.coroutines.CoroutineName
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import kotlinx.coroutines.launch
25 | import kotlinx.coroutines.runBlocking
26 | import org.junit.Rule
27 | import org.junit.jupiter.api.Test
28 |
29 | @ExperimentalCoroutinesApi
30 | class TestCoroutineRuleWithFactorySample {
31 |
32 | val customScope = TestProvidedCoroutineScope(
33 | context = CoroutineName("custom name")
34 | )
35 |
36 | @JvmField
37 | @Rule
38 | val rule = TestCoroutineRule { customScope }
39 |
40 | @Test
41 | fun `rule should be a TestProvidedCoroutineScope`() = runBlocking {
42 |
43 | rule.shouldBeInstanceOf()
44 |
45 | rule.launch {
46 | // use the rule like any other CoroutineScope
47 | }
48 | .join()
49 | }
50 |
51 | @Test
52 | fun `rule should be the provided custom scope`() = runBlocking {
53 |
54 | val context = rule.coroutineContext
55 |
56 | context shouldBe customScope.coroutineContext
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/api/dispatch-test-junit5.api:
--------------------------------------------------------------------------------
1 | public abstract interface annotation class dispatch/test/CoroutineTest : java/lang/annotation/Annotation {
2 | public abstract fun scopeFactory ()Ljava/lang/Class;
3 | }
4 |
5 | public final class dispatch/test/CoroutineTestExtension : org/junit/jupiter/api/extension/support/TypeBasedParameterResolver, org/junit/jupiter/api/extension/AfterEachCallback, org/junit/jupiter/api/extension/BeforeEachCallback {
6 | public fun ()V
7 | public fun (Ldispatch/test/CoroutineTestExtension$ScopeFactory;)V
8 | public synthetic fun (Ldispatch/test/CoroutineTestExtension$ScopeFactory;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
9 | public fun afterEach (Lorg/junit/jupiter/api/extension/ExtensionContext;)V
10 | public fun beforeEach (Lorg/junit/jupiter/api/extension/ExtensionContext;)V
11 | public final fun getScope ()Ldispatch/test/TestProvidedCoroutineScope;
12 | public fun resolveParameter (Lorg/junit/jupiter/api/extension/ParameterContext;Lorg/junit/jupiter/api/extension/ExtensionContext;)Ldispatch/test/TestProvidedCoroutineScope;
13 | public synthetic fun resolveParameter (Lorg/junit/jupiter/api/extension/ParameterContext;Lorg/junit/jupiter/api/extension/ExtensionContext;)Ljava/lang/Object;
14 | }
15 |
16 | public class dispatch/test/CoroutineTestExtension$ScopeFactory {
17 | public fun ()V
18 | public fun create ()Ldispatch/test/TestProvidedCoroutineScope;
19 | }
20 |
21 | public final class dispatch/test/CoroutineTestExtensionKt {
22 | public static final fun coroutineTestExtension (Lkotlin/jvm/functions/Function0;)Ldispatch/test/CoroutineTestExtension;
23 | public static synthetic fun coroutineTestExtension$default (Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Ldispatch/test/CoroutineTestExtension;
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("kotlinx-atomicfu")
18 | javaLibrary
19 | published
20 | }
21 |
22 | dependencies {
23 |
24 | api(libs.junit.api)
25 |
26 | api(projects.dispatchTest)
27 |
28 | implementation(libs.junit.jupiter)
29 | implementation(libs.kotlin.reflect)
30 | implementation(libs.kotlinx.coroutines.core)
31 | implementation(libs.kotlinx.coroutines.jvm)
32 | implementation(libs.kotlinx.coroutines.test)
33 |
34 | testImplementation(libs.kotest.assertions)
35 | testImplementation(libs.kotest.properties)
36 | testImplementation(libs.kotest.runner)
37 | testImplementation(libs.kotlin.test.common)
38 | testImplementation(libs.kotlin.test.core)
39 | testImplementation(libs.mockk)
40 |
41 | testImplementation(projects.dispatchCore)
42 | testImplementation(projects.dispatchInternalTest)
43 | }
44 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/dependencies/runtimeClasspath.txt:
--------------------------------------------------------------------------------
1 | net.java.dev.jna:jna-platform:5.5.0
2 | net.java.dev.jna:jna:5.5.0
3 | org.jetbrains.kotlin:kotlin-reflect:1.7.10
4 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
5 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
6 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
7 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
8 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
9 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
10 | org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.5.2
11 | org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.2
12 | org.jetbrains:annotations:13.0
13 | org.junit.jupiter:junit-jupiter-api:5.9.0
14 | org.junit.jupiter:junit-jupiter-engine:5.9.0
15 | org.junit.jupiter:junit-jupiter-params:5.9.0
16 | org.junit.jupiter:junit-jupiter:5.9.0
17 | org.junit.platform:junit-platform-commons:1.9.0
18 | org.junit.platform:junit-platform-engine:1.9.0
19 | org.junit:junit-bom:5.9.0
20 | org.opentest4j:opentest4j:1.2.0
21 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-test-junit5
16 | POM_NAME=dispatch-test-junit5
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/main/java/dispatch/test/CoroutineTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test
17 |
18 | import kotlinx.coroutines.ExperimentalCoroutinesApi
19 | import org.junit.jupiter.api.extension.ExtendWith
20 | import kotlin.reflect.KClass
21 |
22 | /**
23 | * Annotation for specifying a custom [CoroutineTestExtension.ScopeFactory] while extending a test
24 | * class or function with [CoroutineTestExtension].
25 | *
26 | * @property scopeFactory *optional* KClass which extends [CoroutineTestExtension.ScopeFactory].
27 | * **This class must have a default constructor** An instance will
28 | * be automatically initialized inside the [CoroutineTestExtension]
29 | * and used to create custom [TestProvidedCoroutineScope] instances.
30 | * @sample dispatch.test.samples.CoroutineTestDefaultFactorySample
31 | * @sample dispatch.test.samples.CoroutineTestNamedFactorySample
32 | * @see CoroutineTestExtension
33 | */
34 | @ExperimentalCoroutinesApi
35 | @ExtendWith(CoroutineTestExtension::class)
36 | public annotation class CoroutineTest(
37 | val scopeFactory: KClass<*> = CoroutineTestExtension.ScopeFactory::class
38 | )
39 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/main/java/dispatch/test/internal/ResetManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.internal
17 |
18 | internal class LazyResets(
19 | private val resetManager: ResetManager,
20 | private val valueFactory: () -> T
21 | ) : Lazy,
22 | Resets {
23 |
24 | private var lazyHolder: Lazy = createLazy()
25 |
26 | override val value: T
27 | get() = lazyHolder.value
28 |
29 | override fun isInitialized(): Boolean = lazyHolder.isInitialized()
30 |
31 | private fun createLazy() = lazy {
32 | resetManager.register(this)
33 | valueFactory()
34 | }
35 |
36 | override fun reset() {
37 | lazyHolder = createLazy()
38 | }
39 | }
40 |
41 | internal interface Resets {
42 | fun reset()
43 | }
44 |
45 | internal class ResetManager(
46 | private val delegates: MutableCollection = mutableListOf()
47 | ) {
48 |
49 | fun register(delegate: Resets) {
50 | synchronized(delegates) {
51 | delegates.add(delegate)
52 | }
53 | }
54 |
55 | fun resetAll() {
56 | synchronized(delegates) {
57 | delegates.forEach { it.reset() }
58 | delegates.clear()
59 | }
60 | }
61 | }
62 |
63 | internal inline fun ResetManager.resets(
64 | noinline valueFactory: () -> T
65 | ): LazyResets = LazyResets(this, valueFactory)
66 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/main/java/dispatch/test/internal/reflect.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.internal
17 |
18 | import org.junit.jupiter.api.extension.ExtensionContext
19 | import java.lang.reflect.AnnotatedElement
20 | import java.lang.reflect.Parameter
21 |
22 | internal inline fun ExtensionContext.getAnnotationRecursive(): T? {
23 |
24 | return this.elementOrNull()
25 | ?.getAnnotation(T::class.java) ?: parentOrNull()?.getAnnotationRecursive(T::class.java)
26 | }
27 |
28 | internal fun ExtensionContext.getAnnotationRecursive(aClass: Class): T? {
29 |
30 | return this.elementOrNull()
31 | ?.getAnnotation(aClass) ?: parentOrNull()?.getAnnotationRecursive(aClass)
32 | }
33 |
34 | @Suppress("NewApi")
35 | internal fun ExtensionContext.elementOrNull(): AnnotatedElement? = if (element.isPresent) {
36 | element.get()
37 | } else {
38 | null
39 | }
40 |
41 | @Suppress("NewApi")
42 | internal inline fun Parameter.annotationOrNull(): T? =
43 | getAnnotation(T::class.java) ?: null
44 |
45 | @Suppress("NewApi")
46 | internal fun ExtensionContext.parentOrNull(): ExtensionContext? = if (parent.isPresent) {
47 | parent.get()
48 | } else {
49 | null
50 | }
51 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/main/java/dispatch/test/internal/resolutionException.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.internal
17 |
18 | import dispatch.test.CoroutineTest
19 | import dispatch.test.CoroutineTestExtension
20 | import kotlinx.coroutines.ExperimentalCoroutinesApi
21 | import org.junit.jupiter.api.extension.ParameterResolutionException
22 | import kotlin.reflect.KClass
23 |
24 | @ExperimentalCoroutinesApi
25 | internal fun resolutionException(factoryClass: KClass<*>): ParameterResolutionException {
26 | return ParameterResolutionException(
27 | """A ${CoroutineTest::class.simpleName} annotation was found with an incompatible factory type.
28 | |
29 | |The specified factory must be <${CoroutineTestExtension.ScopeFactory::class.qualifiedName}> or a subtype.
30 | |
31 | |The provided factory type was: <${factoryClass.qualifiedName}>
32 | |
33 | """.trimMargin()
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/CoroutineTestExtensionInjectionTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test
17 |
18 | import io.kotest.matchers.shouldNotBe
19 | import kotlinx.coroutines.ExperimentalCoroutinesApi
20 | import org.junit.jupiter.api.BeforeAll
21 | import org.junit.jupiter.api.BeforeEach
22 | import org.junit.jupiter.api.Nested
23 | import org.junit.jupiter.api.Test
24 | import org.junit.jupiter.api.extension.RegisterExtension
25 |
26 | @ExperimentalCoroutinesApi
27 | class CoroutineTestExtensionInjectionTest {
28 |
29 | @JvmField @RegisterExtension
30 | val extension = CoroutineTestExtension()
31 |
32 | @Nested
33 | inner class `nested classes` {
34 |
35 | @Test
36 | fun `function arguments should be automatically injected`(scope: TestProvidedCoroutineScope) {
37 |
38 | scope shouldNotBe null
39 | }
40 | }
41 |
42 | @Nested
43 | inner class `lifecycle callback functions` {
44 |
45 | var beforeAllInjectedScope: TestProvidedCoroutineScope? = null
46 | var beforeEachInjectedScope: TestProvidedCoroutineScope? = null
47 |
48 | @BeforeAll
49 | fun beforeAll(scope: TestProvidedCoroutineScope) {
50 | beforeAllInjectedScope = scope
51 | }
52 |
53 | @BeforeEach
54 | fun beforeEach(scope: TestProvidedCoroutineScope) {
55 | beforeEachInjectedScope = scope
56 | }
57 |
58 | @Test
59 | fun `beforeAll should be injected before a function is called`() {
60 |
61 | beforeAllInjectedScope shouldNotBe null
62 | }
63 |
64 | @Test
65 | fun `beforeEach should be injected before a function is called`() {
66 |
67 | beforeEachInjectedScope shouldNotBe null
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/SetMainTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test
17 |
18 | import io.kotest.matchers.shouldBe
19 | import kotlinx.coroutines.Dispatchers
20 | import kotlinx.coroutines.ExperimentalCoroutinesApi
21 | import kotlinx.coroutines.test.setMain
22 | import org.junit.jupiter.api.Nested
23 | import org.junit.jupiter.api.Test
24 | import org.junit.jupiter.api.extension.RegisterExtension
25 |
26 | @Suppress("HardCodedDispatcher")
27 | @ExperimentalCoroutinesApi
28 | class SetMainTest {
29 |
30 | @RegisterExtension @JvmField
31 | val ext = CoroutineTestExtension()
32 |
33 | @Test
34 | fun `extension's internal scope's dispatcher should be set as Main by default`() {
35 |
36 | val beforeSet = Dispatchers.Main
37 |
38 | Dispatchers.setMain(ext.scope.dispatcherProvider.main)
39 |
40 | beforeSet shouldBe Dispatchers.Main
41 | }
42 |
43 | @Test
44 | fun `function injected scope's dispatcher should be set as Main by default`(
45 | scope: TestProvidedCoroutineScope
46 | ) {
47 |
48 | val beforeSet = Dispatchers.Main
49 |
50 | Dispatchers.setMain(scope.dispatcherProvider.main)
51 |
52 | beforeSet shouldBe Dispatchers.Main
53 | }
54 |
55 | @Nested
56 | inner class `constructor injection`(
57 | val scope: TestProvidedCoroutineScope
58 | ) {
59 |
60 | @Test
61 | fun `constructor injected scope's dispatcher should be set as Main by default`() {
62 |
63 | val beforeSet = Dispatchers.Main
64 |
65 | Dispatchers.setMain(scope.dispatcherProvider.main)
66 |
67 | beforeSet shouldBe Dispatchers.Main
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/CoroutineTestDefaultFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 |
18 | package dispatch.test.samples
19 |
20 | import dispatch.test.CoroutineTest
21 | import dispatch.test.TestProvidedCoroutineScope
22 | import io.kotest.matchers.shouldBe
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import kotlinx.coroutines.runBlocking
25 | import org.junit.jupiter.api.Test
26 |
27 | @CoroutineTest
28 | class CoroutineTestDefaultFactorySample(
29 | val testScope: TestProvidedCoroutineScope
30 | ) {
31 |
32 | @Test
33 | fun `extension should automatically inject into test class`() = runBlocking {
34 |
35 | val subject = SomeClass(testScope)
36 |
37 | val resultDeferred = subject.someFunction()
38 |
39 | testScope.advanceUntilIdle()
40 |
41 | resultDeferred.await() shouldBe someValue
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/CoroutineTestExtensionExtendWithSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 |
18 | package dispatch.test.samples
19 |
20 | import dispatch.test.CoroutineTestExtension
21 | import dispatch.test.TestProvidedCoroutineScope
22 | import io.kotest.matchers.shouldNotBe
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import org.junit.jupiter.api.Test
25 | import org.junit.jupiter.api.extension.ExtendWith
26 |
27 | @ExtendWith(CoroutineTestExtension::class)
28 | class CoroutineTestExtensionExtendWithSample(
29 | val testScope: TestProvidedCoroutineScope
30 | ) {
31 |
32 | @Test
33 | fun `injected scope should be injected`() {
34 |
35 | testScope shouldNotBe null
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/CoroutineTestNamedFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 |
18 | package dispatch.test.samples
19 |
20 | import dispatch.test.CoroutineTest
21 | import dispatch.test.CoroutineTestExtension
22 | import dispatch.test.TestProvidedCoroutineScope
23 | import io.kotest.matchers.shouldNotBe
24 | import kotlinx.coroutines.ExperimentalCoroutinesApi
25 | import kotlinx.coroutines.Job
26 | import kotlinx.coroutines.runBlocking
27 | import org.junit.jupiter.api.Test
28 |
29 | class CoroutineTestNamedFactorySample {
30 |
31 | class TestCoroutineScopeWithJobFactory : CoroutineTestExtension.ScopeFactory() {
32 |
33 | override fun create(): TestProvidedCoroutineScope {
34 | return TestProvidedCoroutineScope(context = Job())
35 | }
36 | }
37 |
38 | @CoroutineTest(TestCoroutineScopeWithJobFactory::class)
39 | class CustomFactorySample(val testScope: TestProvidedCoroutineScope) {
40 |
41 | @Test
42 | fun `injected scope should have a Job context`() = runBlocking {
43 |
44 | testScope.coroutineContext[Job] shouldNotBe null
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/RegisterSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 |
18 | package dispatch.test.samples
19 |
20 | import dispatch.test.TestProvidedCoroutineScope
21 | import dispatch.test.coroutineTestExtension
22 | import io.kotest.matchers.shouldBe
23 | import io.kotest.matchers.types.shouldBeInstanceOf
24 | import kotlinx.coroutines.ExperimentalCoroutinesApi
25 | import kotlinx.coroutines.runBlocking
26 | import org.junit.jupiter.api.Test
27 | import org.junit.jupiter.api.extension.RegisterExtension
28 |
29 | class RegisterSample {
30 |
31 | @JvmField
32 | @RegisterExtension
33 | val extension = coroutineTestExtension()
34 |
35 | @Test
36 | fun `extension should be a TestProvidedCoroutineScope`() = runBlocking {
37 |
38 | extension.scope.shouldBeInstanceOf()
39 | }
40 |
41 | @Test
42 | fun `extension should automatically inject into functions`(scope: TestProvidedCoroutineScope) =
43 | runBlocking {
44 |
45 | val subject = SomeClass(scope)
46 |
47 | val resultDeferred = subject.someFunction()
48 |
49 | scope.advanceUntilIdle()
50 |
51 | resultDeferred.await() shouldBe someValue
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/RegisterWithFactorySample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | @file:OptIn(ExperimentalCoroutinesApi::class)
17 |
18 | package dispatch.test.samples
19 |
20 | import dispatch.test.TestProvidedCoroutineScope
21 | import dispatch.test.coroutineTestExtension
22 | import io.kotest.matchers.shouldBe
23 | import kotlinx.coroutines.CoroutineName
24 | import kotlinx.coroutines.ExperimentalCoroutinesApi
25 | import kotlinx.coroutines.runBlocking
26 | import org.junit.jupiter.api.Test
27 | import org.junit.jupiter.api.extension.RegisterExtension
28 |
29 | class RegisterWithFactorySample {
30 |
31 | @JvmField
32 | @RegisterExtension
33 | val extension = coroutineTestExtension {
34 | TestProvidedCoroutineScope(context = CoroutineName("custom name"))
35 | }
36 |
37 | @Test
38 | fun `extension should provide a scope from the custom factory`() = runBlocking {
39 |
40 | extension.scope.coroutineContext[CoroutineName] shouldBe CoroutineName("custom name")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/dispatch-test-junit5/src/test/kotlin/dispatch/test/samples/utils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.samples
17 |
18 | import kotlinx.coroutines.CoroutineScope
19 | import kotlinx.coroutines.Deferred
20 | import kotlinx.coroutines.async
21 |
22 | @Suppress("TopLevelPropertyNaming")
23 | public const val someValue: Boolean = true
24 |
25 | public class SomeClass(public val coroutineScope: CoroutineScope) {
26 |
27 | public fun someFunction(): Deferred = coroutineScope.async { true }
28 | }
29 |
--------------------------------------------------------------------------------
/dispatch-test/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/dispatch-test/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | plugins {
17 | id("kotlinx-atomicfu")
18 | javaLibrary
19 | published
20 | }
21 |
22 | dependencies {
23 |
24 | api(libs.kotlinx.coroutines.core)
25 | api(libs.kotlinx.coroutines.jvm)
26 | api(libs.kotlinx.coroutines.test)
27 |
28 | api(projects.dispatchCore)
29 |
30 | testImplementation(libs.junit.api)
31 | testImplementation(libs.kotest.assertions)
32 | testImplementation(libs.kotest.properties)
33 | testImplementation(libs.kotest.runner)
34 | testImplementation(libs.kotlin.test.common)
35 | testImplementation(libs.kotlin.test.core)
36 | testImplementation(libs.mockk)
37 |
38 | testImplementation(projects.dispatchInternalTest)
39 |
40 | testRuntimeOnly(libs.junit.jupiter)
41 | }
42 |
--------------------------------------------------------------------------------
/dispatch-test/dependencies/runtimeClasspath.txt:
--------------------------------------------------------------------------------
1 | net.java.dev.jna:jna-platform:5.5.0
2 | net.java.dev.jna:jna:5.5.0
3 | org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
4 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
5 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
6 | org.jetbrains.kotlin:kotlin-stdlib:1.7.10
7 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
8 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
9 | org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.5.2
10 | org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.2
11 | org.jetbrains:annotations:13.0
12 |
--------------------------------------------------------------------------------
/dispatch-test/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | POM_ARTIFACT_ID=dispatch-test
16 | POM_NAME=dispatch-test
17 | POM_PACKAGING=jar
18 |
--------------------------------------------------------------------------------
/dispatch-test/src/main/java/dispatch/test/defaultDispatcherProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test
17 |
18 | import dispatch.core.DefaultDispatcherProvider
19 | import dispatch.core.DispatcherProvider
20 |
21 | /**
22 | * Resets the singleton [DispatcherProvider] instance to the true default. This default instance
23 | * delegates to the [Dispatchers][kotlinx.coroutines.Dispatchers] singleton object properties.
24 | *
25 | * @see DefaultDispatcherProvider
26 | * @sample dispatch.test.samples.DefaultDispatcherProviderExtensionSample.resetSample
27 | */
28 | @Suppress("unused")
29 | public fun DefaultDispatcherProvider.reset() {
30 | set(object : DispatcherProvider {})
31 | }
32 |
--------------------------------------------------------------------------------
/dispatch-test/src/test/kotlin/dispatch/test/samples/BuildersSample.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.samples
17 |
18 | import dispatch.internal.test.Sample5
19 | import dispatch.test.TestProvidedCoroutineScope
20 | import dispatch.test.runBlockingProvided
21 | import dispatch.test.testProvided
22 | import io.kotest.matchers.shouldBe
23 | import kotlinx.coroutines.ExperimentalCoroutinesApi
24 | import org.junit.jupiter.api.Test
25 |
26 | @ExperimentalCoroutinesApi
27 | class BuildersSample {
28 |
29 | @Sample5
30 | fun runBlockingProvidedSample() {
31 |
32 | @Test
33 | fun someTest() = runBlockingProvided {
34 |
35 | val subject = SomeClass(this)
36 |
37 | val myData = Data()
38 |
39 | subject.dataDeferred()
40 | .await() shouldBe myData
41 | }
42 | }
43 |
44 | @Sample5
45 | fun testProvidedSample() {
46 |
47 | @Test
48 | fun someTest() = testProvided {
49 |
50 | val subject = SomeClass(this)
51 |
52 | val myData = Data()
53 |
54 | subject.dataDeferred()
55 | .await() shouldBe myData
56 | }
57 | }
58 |
59 | @Sample5
60 | fun testProvidedExtensionSample() {
61 |
62 | val scope = TestProvidedCoroutineScope()
63 |
64 | @Test
65 | fun someTest() = scope.testProvided {
66 |
67 | val subject = SomeClass(this)
68 |
69 | val myData = Data()
70 |
71 | subject.dataDeferred()
72 | .await() shouldBe myData
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/dispatch-test/src/test/kotlin/dispatch/test/samples/SomeClass.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | package dispatch.test.samples
17 |
18 | import kotlinx.coroutines.CoroutineScope
19 | import kotlinx.coroutines.async
20 |
21 | class SomeClass(val coroutineScope: CoroutineScope) {
22 |
23 | fun dataDeferred() = coroutineScope.async { Data() }
24 | }
25 |
26 | @Suppress("FunctionOnlyReturningConstant")
27 | fun Data() = 1
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2022 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | kapt.incremental.apt=true
16 | org.gradle.caching=true
17 | org.gradle.configureondemand=true
18 | org.gradle.daemon=true
19 | org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC
20 | org.gradle.parallel=true
21 | org.gradle.vfs.watch=true
22 | android.useAndroidX=true
23 | android.enableJetifier=false
24 | android.lifecycleProcessor.incremental=true
25 | # Maven
26 | GROUP=com.rickbusarow.dispatch
27 | VERSION_NAME=1.0.0-beta10-SNAPSHOT
28 | POM_DESCRIPTION=Quality of life coroutine utilities.
29 | POM_INCEPTION_YEAR=2019
30 | POM_URL=https://github.com/rbusarow/Dispatch
31 | POM_SCM_URL=https://github.com/rbusarow/Dispatch.git
32 | POM_SCM_CONNECTION=scm:git:github.com/rbusarow/Dispatch.git
33 | POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/rbusarow/Dispatch.git
34 | POM_LICENCE_NAME=The Apache License, Version 2.0
35 | POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
36 | POM_LICENCE_DIST=repo
37 | POM_DEVELOPER_ID=rbusarow
38 | POM_DEVELOPER_NAME=Rick Busarow
39 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/knit.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2021 Rick Busarow
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | knit.dir=src/test/java/example/
16 | knit.package=com.example
17 | test.dir=src/test/kotlin/example/test/
18 | test.package=com.example.test
19 | site.root=https://rbusarow.github.io/Dispatch/
20 | module.roots=.
21 | module.marker=build.gradle build.gradle.kts
22 | module.docs=build/dokka
23 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Copyright (C) 2022 Rick Busarow
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | # exit when any command fails
19 | set -e
20 |
21 | # keep track of the last executed command
22 | trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
23 | # echo an error message before exiting
24 | trap 'echo "\"${last_command}\" command filed with exit code $?."' EXIT
25 |
26 | ./gradlew clean
27 |
28 | # Publish Maven release
29 | ./gradlew publish --no-daemon --no-parallel --no-configuration-cache
30 |
31 | # Close Maven release
32 | ./gradlew closeAndReleaseRepository --no-daemon --no-parallel --no-configuration-cache
33 |
34 | # Create new website docs version
35 | ./gradlew versionDocs
36 |
37 | # Set all versions in the root README to the new version
38 | ./gradlew updateProjectReadmeVersionRefs --no-configuration-cache
39 |
40 | # Copy the CHANGELOG from project root to the website dir and update its formatting
41 | ./gradlew updateWebsiteChangelog
42 |
43 | echo
44 | echo ' ___ _ _ ___ ___ ___ ___ ___'
45 | echo '/ __| | | |/ __/ __/ _ \/ __/ __|'
46 | echo '\__ \ |_| | (_| (_| __/\__ \__ \'
47 | echo '|___/\__,_|\___\___\___||___/___/'
48 | echo
49 | echo
50 | echo The release is done and a new docs version has been created for Docusaurus.
51 | echo
52 | echo These changes need to get merged into main and published.
53 | echo
54 | echo
55 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "labels": ["dependencies", "automerge"],
3 | "extends": [
4 | "config:base"
5 | ],
6 | "rebaseWhen": "never",
7 | "rebaseLabel": "rebase"
8 | }
9 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2022 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | pluginManagement {
17 | repositories {
18 | gradlePluginPortal()
19 | mavenCentral()
20 | google()
21 | }
22 | }
23 |
24 | dependencyResolutionManagement {
25 | @Suppress("UnstableApiUsage")
26 | repositories {
27 | google()
28 | mavenCentral()
29 | }
30 | }
31 |
32 | plugins {
33 | id("com.gradle.enterprise").version("3.10")
34 | }
35 |
36 | gradleEnterprise {
37 | buildScan {
38 | termsOfServiceUrl = "https://gradle.com/terms-of-service"
39 | termsOfServiceAgree = "yes"
40 | publishAlways()
41 | }
42 | }
43 |
44 | rootProject.name = "Dispatch"
45 |
46 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
47 |
48 | include(":dispatch-android-espresso")
49 | include(":dispatch-android-lifecycle")
50 | include(":dispatch-android-lifecycle-extensions")
51 | include(":dispatch-android-viewmodel")
52 | include(":dispatch-bom")
53 | include(":dispatch-core")
54 | include(":dispatch-test")
55 | include(":dispatch-test-junit4")
56 | include(":dispatch-test-junit5")
57 | include(":dispatch-detekt")
58 | include(":dispatch-internal-test")
59 | include(":dispatch-internal-test-android")
60 | include(":dispatch-sample")
61 |
--------------------------------------------------------------------------------
/website/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator.
4 |
5 | ## Installation
6 |
7 | ```console
8 | yarn install
9 | ```
10 |
11 | ## Local Development
12 |
13 | ```console
14 | yarn start
15 | ```
16 |
17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ## Build
20 |
21 | ```console
22 | yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ## Deployment
28 |
29 | ```console
30 | GIT_USER= USE_SSH=true yarn deploy
31 | ```
32 |
33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
34 |
--------------------------------------------------------------------------------
/website/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
3 | };
4 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dispatch",
3 | "version": "1.0.0-beta10-SNAPSHOT",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "serve": "docusaurus serve",
12 | "clear": "docusaurus clear"
13 | },
14 | "dependencies": {
15 | "@babel/core": "7.19.1",
16 | "@babel/helper-compilation-targets": "7.19.1",
17 | "@docusaurus/core": "2.1.0",
18 | "@docusaurus/plugin-content-docs": "2.1.0",
19 | "@docusaurus/plugin-content-pages": "2.1.0",
20 | "@docusaurus/preset-classic": "2.1.0",
21 | "@docusaurus/theme-classic": "2.1.0",
22 | "@mdx-js/react": "1.6.22",
23 | "clsx": "1.2.1",
24 | "mdx-mermaid": "1.3.2",
25 | "mermaid": "9.1.7",
26 | "prism-react-renderer": "1.3.5",
27 | "react": "18.2.0",
28 | "react-dom": "18.2.0",
29 | "react-infima": "0.0.1-alpha.4"
30 | },
31 | "browserslist": {
32 | "production": [
33 | ">0.5%",
34 | "not dead",
35 | "not op_mini all"
36 | ],
37 | "development": [
38 | "last 1 chrome version",
39 | "last 1 firefox version",
40 | "last 1 safari version"
41 | ]
42 | },
43 | "main": "index.js",
44 | "license": "MIT"
45 | }
46 |
--------------------------------------------------------------------------------
/website/sidebars.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 Rick Busarow
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | module.exports = {
17 | // mySidebar: [
18 | // {
19 | // type: 'autogenerated',
20 | // dirName: '.', // generate sidebar slice from the docs folder (or versioned_docs/)
21 | // },
22 | // ],
23 | Docs: [
24 | "intro",
25 | "quickstart",
26 | "modules/dispatch-core",
27 | "modules/dispatch-detekt",
28 | {
29 | type: "category",
30 | label: "Android",
31 | collapsed: false,
32 | items: [
33 | "modules/dispatch-android-espresso",
34 | "modules/dispatch-android-lifecycle",
35 | "modules/dispatch-android-lifecycle-extensions",
36 | "modules/dispatch-android-viewmodel",
37 | ],
38 | },
39 | {
40 | type: "category",
41 | label: "Testing",
42 | collapsed: false,
43 | items: [
44 | "modules/dispatch-test",
45 | "modules/dispatch-test-junit4",
46 | "modules/dispatch-test-junit5",
47 | ],
48 | },
49 | ]
50 | }
51 | ;
52 |
--------------------------------------------------------------------------------
/website/src/pages/styles.module.css:
--------------------------------------------------------------------------------
1 | /* stylelint-disable docusaurus/copyright-header */
2 |
3 | /**
4 | * CSS files with the .module.css suffix will be treated as CSS modules
5 | * and scoped locally.
6 | */
7 |
8 | .heroBanner {
9 | padding: 4rem 0;
10 | text-align: center;
11 | position: relative;
12 | overflow: hidden;
13 | }
14 |
15 | @media screen and (max-width: 966px) {
16 | .heroBanner {
17 | padding: 2rem;
18 | }
19 | }
20 |
21 | .buttons {
22 | display: flex;
23 | align-items: center;
24 | justify-content: center;
25 | }
26 |
27 | .container {
28 | display: inline-block;
29 | width: 100%;
30 | text-align: center;
31 | }
32 |
33 | .badges {
34 | text-align: center;
35 | padding: 2rem;
36 | }
37 |
38 | .features {
39 | margin: auto;
40 | text-align: left;
41 | display: flex;
42 | align-items: center;
43 | padding: 2rem 0;
44 | width: 100%;
45 | }
46 |
47 | .feature {
48 | margin: 15px;
49 | width: 100%;
50 | }
51 |
52 | .row {
53 | align-items: center;
54 | text-align: left;
55 | display: flex;
56 | flex-direction: row;
57 | flex-wrap: wrap;
58 | width: 100%;
59 | }
60 |
61 | .column {
62 | display: flex;
63 | flex-direction: column;
64 | margin: 20px;
65 | flex: 1;
66 | }
67 |
68 | .featureImage {
69 | height: 200px;
70 | width: 200px;
71 | }
72 |
73 | .heroSlogan {
74 | font-size: 3em;
75 | line-height: normal;
76 | color: var(--ifm-color-white) !important;
77 | }
78 |
79 | /*.heroSlogan strong {*/
80 | /* color: #8000ff;*/
81 | /*}*/
82 |
83 | .gettingStartedButton {
84 | background: #ffffff;
85 | color: var(--ifm-color-gray-900) !important;
86 | }
87 |
88 | .gettingStartedButton:hover {
89 | background: #ffffff;
90 | color: var(--ifm-color-primary) !important;
91 | }
92 |
--------------------------------------------------------------------------------
/website/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RBusarow/Dispatch/4b231ef18802c064375eee7a58326f8283794dcd/website/static/.nojekyll
--------------------------------------------------------------------------------
/website/static/img/coffee-solid.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/website/static/img/power-off-solid.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/website/static/img/syringe-solid.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/website/versioned_sidebars/version-1.0.0-beta10-sidebars.json:
--------------------------------------------------------------------------------
1 | {
2 | "version-1.0.0-beta10/Basics": [
3 | {
4 | "type": "doc",
5 | "id": "version-1.0.0-beta10/intro"
6 | },
7 | {
8 | "type": "doc",
9 | "id": "version-1.0.0-beta10/quickstart"
10 | },
11 | {
12 | "type": "doc",
13 | "id": "version-1.0.0-beta10/modules/dispatch-core"
14 | },
15 | {
16 | "type": "doc",
17 | "id": "version-1.0.0-beta10/modules/dispatch-detekt"
18 | },
19 | {
20 | "type": "category",
21 | "label": "Android",
22 | "collapsed": false,
23 | "items": [
24 | {
25 | "type": "doc",
26 | "id": "version-1.0.0-beta10/modules/dispatch-android-espresso"
27 | },
28 | {
29 | "type": "doc",
30 | "id": "version-1.0.0-beta10/modules/dispatch-android-lifecycle"
31 | },
32 | {
33 | "type": "doc",
34 | "id": "version-1.0.0-beta10/modules/dispatch-android-lifecycle-extensions"
35 | },
36 | {
37 | "type": "doc",
38 | "id": "version-1.0.0-beta10/modules/dispatch-android-viewmodel"
39 | }
40 | ],
41 | "collapsible": true
42 | },
43 | {
44 | "type": "category",
45 | "label": "Testing",
46 | "collapsed": false,
47 | "items": [
48 | {
49 | "type": "doc",
50 | "id": "version-1.0.0-beta10/modules/dispatch-test"
51 | },
52 | {
53 | "type": "doc",
54 | "id": "version-1.0.0-beta10/modules/dispatch-test-junit4"
55 | },
56 | {
57 | "type": "doc",
58 | "id": "version-1.0.0-beta10/modules/dispatch-test-junit5"
59 | }
60 | ],
61 | "collapsible": true
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/website/versions.json:
--------------------------------------------------------------------------------
1 | [
2 | "1.0.0-beta10"
3 | ]
4 |
--------------------------------------------------------------------------------