Skip to content

Commit 96eff2d

Browse files
WIP: Upgrade coroutines to 1.6.1
1 parent 35d9232 commit 96eff2d

File tree

5 files changed

+44
-53
lines changed

5 files changed

+44
-53
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ kotest = "5.1.0"
4949
kotlin = "1.6.10"
5050

5151
kotlinx-binary-compatibility = "0.6.0"
52-
kotlinx-coroutines = "1.5.1"
52+
kotlinx-coroutines = "1.6.1"
5353
# The 1.5.1 test artifact is jvm-only. The commonTest module should use 1.6.1.
5454
kotlinx-coroutines-test-common = "1.6.1"
5555
kotlinx-serialization-json = "1.3.2"

workflow-testing/src/test/java/com/squareup/workflow1/WorkerTest.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
package com.squareup.workflow1
44

55
import com.squareup.workflow1.testing.test
6+
import kotlinx.coroutines.ExperimentalCoroutinesApi
67
import kotlinx.coroutines.flow.flowOn
7-
import kotlinx.coroutines.test.TestCoroutineDispatcher
8+
import kotlinx.coroutines.test.StandardTestDispatcher
89
import kotlin.test.Test
910
import kotlin.test.assertEquals
1011
import kotlin.test.assertNotSame
1112
import kotlin.test.assertTrue
1213

1314
/** Worker tests that use the [Worker.test] function. Core tests are in the core module. */
15+
@OptIn(ExperimentalCoroutinesApi::class)
1416
internal class WorkerTest {
1517

1618
private class ExpectedException : RuntimeException()
@@ -119,7 +121,7 @@ internal class WorkerTest {
119121
}
120122

121123
@Test fun `timer emits and finishes after delay`() {
122-
val testDispatcher = TestCoroutineDispatcher()
124+
val testDispatcher = StandardTestDispatcher()
123125
val worker = Worker.timer(1000)
124126
// Run the timer on the test dispatcher so we can control time.
125127
.transform { it.flowOn(testDispatcher) }
@@ -128,11 +130,13 @@ internal class WorkerTest {
128130
assertNoOutput()
129131
assertNotFinished()
130132

131-
testDispatcher.advanceTimeBy(999)
133+
testDispatcher.scheduler.advanceTimeBy(999)
134+
testDispatcher.scheduler.runCurrent()
132135
assertNoOutput()
133136
assertNotFinished()
134137

135-
testDispatcher.advanceTimeBy(1)
138+
testDispatcher.scheduler.advanceTimeBy(1)
139+
testDispatcher.scheduler.runCurrent()
136140
assertEquals(Unit, nextOutput())
137141
assertFinished()
138142
}

workflow-testing/src/test/java/com/squareup/workflow1/testing/RenderIdempotencyCheckerTest.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ import com.squareup.workflow1.stateless
88
import kotlinx.coroutines.CoroutineScope
99
import kotlinx.coroutines.Dispatchers.Unconfined
1010
import kotlinx.coroutines.ExperimentalCoroutinesApi
11-
import kotlinx.coroutines.Job
1211
import kotlinx.coroutines.flow.MutableStateFlow
13-
import kotlinx.coroutines.test.TestCoroutineScope
12+
import kotlinx.coroutines.test.TestScope
1413
import kotlin.test.Test
1514
import kotlin.test.assertEquals
1615

@@ -26,8 +25,7 @@ class RenderIdempotencyCheckerTest {
2625
rootRenders++
2726
renderChild(leafWorkflow)
2827
}
29-
val scope = TestCoroutineScope(Job())
30-
.apply { pauseDispatcher() }
28+
val scope = TestScope()
3129

3230
renderWorkflowIn(
3331
rootWorkflow, scope, MutableStateFlow(Unit), interceptors = listOf(RenderIdempotencyChecker)

workflow-ui/compose/src/androidTest/java/com/squareup/workflow1/ui/compose/RenderAsStateTest.kt

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ import kotlinx.coroutines.Job
3333
import kotlinx.coroutines.awaitCancellation
3434
import kotlinx.coroutines.isActive
3535
import kotlinx.coroutines.job
36-
import kotlinx.coroutines.test.TestCoroutineScope
36+
import kotlinx.coroutines.test.TestScope
37+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
38+
import kotlinx.coroutines.test.advanceUntilIdle
39+
import kotlinx.coroutines.test.runTest
3740
import okio.ByteString
3841
import okio.ByteString.Companion.decodeBase64
3942
import org.junit.Rule
@@ -236,21 +239,15 @@ internal class RenderAsStateTest {
236239

237240
@Test fun renderingIsAvailableImmediatelyWhenWorkflowScopeUsesDifferentDispatcher() {
238241
val workflow = Workflow.rendering("hello")
239-
val scope = TestCoroutineScope()
242+
val scope = TestScope()
240243

241-
// Ensure the workflow runtime won't actually run aside from the synchronous first pass.
242-
scope.pauseDispatcher()
243-
244-
try {
245-
composeRule.setContent {
246-
val initialRendering = workflow.renderAsState(
247-
props = Unit, onOutput = {},
248-
scope = scope
249-
)
250-
assertThat(initialRendering.value).isNotNull()
251-
}
252-
} finally {
253-
scope.cleanupTestCoroutines()
244+
composeRule.setContent {
245+
val initialRendering = workflow.renderAsState(
246+
props = Unit,
247+
onOutput = {},
248+
scope = scope
249+
)
250+
assertThat(initialRendering.value).isNotNull()
254251
}
255252
}
256253

@@ -262,11 +259,11 @@ internal class RenderAsStateTest {
262259
awaitCancellation()
263260
}
264261
}
265-
val scope = TestCoroutineScope()
262+
val scope = TestScope(UnconfinedTestDispatcher())
266263

267264
class CancelCompositionException : RuntimeException()
268265

269-
try {
266+
scope.runTest {
270267
assertFailsWith<CancelCompositionException> {
271268
composeRule.setContent {
272269
workflow.renderAsState(props = Unit, onOutput = {}, scope = scope)
@@ -275,22 +272,18 @@ internal class RenderAsStateTest {
275272
}
276273

277274
composeRule.runOnIdle {
278-
scope.advanceUntilIdle()
279-
280275
assertThat(innerJob).isNotNull()
281276
assertThat(innerJob!!.isCancelled).isTrue()
282277
}
283-
} finally {
284-
scope.cleanupTestCoroutines()
285278
}
286279
}
287280

288281
@Test fun workflowScopeIsNotCancelledWhenRemovedFromComposition() {
289282
val workflow = Workflow.stateless<Unit, Nothing, Unit> {}
290-
val scope = TestCoroutineScope(Job())
283+
val scope = TestScope()
291284
var shouldRunWorkflow by mutableStateOf(true)
292285

293-
try {
286+
scope.runTest {
294287
composeRule.setContent {
295288
if (shouldRunWorkflow) {
296289
workflow.renderAsState(props = Unit, onOutput = {}, scope = scope)
@@ -307,8 +300,6 @@ internal class RenderAsStateTest {
307300
scope.advanceUntilIdle()
308301
assertThat(scope.isActive).isTrue()
309302
}
310-
} finally {
311-
scope.cleanupTestCoroutines()
312303
}
313304
}
314305

workflow-ui/core-android/src/test/java/com/squareup/workflow1/ui/ViewLaunchWhenAttachedTest.kt

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
1313
import kotlinx.coroutines.Job
1414
import kotlinx.coroutines.job
1515
import kotlinx.coroutines.suspendCancellableCoroutine
16-
import kotlinx.coroutines.test.TestCoroutineDispatcher
16+
import kotlinx.coroutines.test.StandardTestDispatcher
17+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
1718
import kotlinx.coroutines.test.resetMain
19+
import kotlinx.coroutines.test.runTest
1820
import kotlinx.coroutines.test.setMain
1921
import org.junit.After
2022
import org.junit.Before
@@ -34,26 +36,22 @@ import org.mockito.kotlin.whenever
3436
@OptIn(ExperimentalCoroutinesApi::class, WorkflowUiExperimentalApi::class)
3537
internal class ViewLaunchWhenAttachedTest {
3638

37-
private val dispatcher = TestCoroutineDispatcher()
3839
private val view = mockView()
3940
private val onAttachStateChangeListener = argumentCaptor<OnAttachStateChangeListener>()
4041

4142
@Before
4243
fun setUp() {
43-
Dispatchers.setMain(dispatcher)
44+
Dispatchers.setMain(StandardTestDispatcher())
4445
}
4546

4647
@After fun tearDown() {
47-
dispatcher.cleanupTestCoroutines()
4848
Dispatchers.resetMain()
4949
}
5050

51-
@Test fun `launchWhenAttached launches synchronously when already attached`() {
51+
@Test fun `launchWhenAttached launches synchronously when already attached`() = runTest {
5252
var innerJob: Job? = null
5353
var started = false
5454
mockAttachedToWindow(view, true)
55-
// Pause the dispatcher to verify that the coroutine is started synchronously.
56-
dispatcher.pauseDispatcher()
5755

5856
// Action: launch a coroutine!
5957
view.launchWhenAttached {
@@ -74,9 +72,8 @@ internal class ViewLaunchWhenAttachedTest {
7472
assertThat(innerJob!!.isCancelled).isTrue()
7573
}
7674

77-
@Test fun `launchWhenAttached cancels when detached while launching`() {
75+
@Test fun `launchWhenAttached cancels when detached while launching`() = runTest {
7876
mockAttachedToWindow(view, true)
79-
dispatcher.pauseDispatcher()
8077

8178
// Action: launch a coroutine!
8279
view.launchWhenAttached {
@@ -88,7 +85,7 @@ internal class ViewLaunchWhenAttachedTest {
8885
}
8986
}
9087

91-
@Test fun `launchWhenAttached launches when attached later`() {
88+
@Test fun `launchWhenAttached launches when attached later`() = runTest {
9289
var innerJob: Job? = null
9390
mockAttachedToWindow(view, false)
9491

@@ -99,14 +96,14 @@ internal class ViewLaunchWhenAttachedTest {
9996
}
10097
}
10198

102-
dispatcher.advanceUntilIdle()
99+
testScheduler.advanceUntilIdle()
103100
assertThat(innerJob).isNull()
104101

105102
verify(view).setTag(isA(), isA<OnAttachStateChangeListener>())
106103

107104
// Action: attach view!
108105
performViewAttach()
109-
dispatcher.advanceUntilIdle()
106+
testScheduler.advanceUntilIdle()
110107
assertThat(innerJob).isNotNull()
111108
assertThat(innerJob!!.isActive).isTrue()
112109

@@ -115,7 +112,7 @@ internal class ViewLaunchWhenAttachedTest {
115112
assertThat(innerJob!!.isCancelled).isTrue()
116113
}
117114

118-
@Test fun `launchWhenAttached launches when reattached`() {
115+
@Test fun `launchWhenAttached launches when reattached`() = runTest {
119116
var innerJob: Job? = null
120117
mockAttachedToWindow(view, true)
121118

@@ -131,7 +128,7 @@ internal class ViewLaunchWhenAttachedTest {
131128
}
132129

133130
// The coroutine shouldn't have started since the view is detached.
134-
dispatcher.advanceUntilIdle()
131+
testScheduler.advanceUntilIdle()
135132
assertThat(innerJob).isNull()
136133

137134
// Action: re-attach view!
@@ -144,7 +141,7 @@ internal class ViewLaunchWhenAttachedTest {
144141
assertThat(innerJob!!.isActive).isTrue()
145142
}
146143

147-
@Test fun `launchWhenAttached coroutine is child of ViewTreeLifecycleOwner`() {
144+
@Test fun `launchWhenAttached coroutine is child of ViewTreeLifecycleOwner`() = runTest {
148145
var innerJob: Job? = null
149146
mockAttachedToWindow(view, true)
150147

@@ -154,6 +151,7 @@ internal class ViewLaunchWhenAttachedTest {
154151
innerJob = continuation.context.job
155152
}
156153
}
154+
testScheduler.advanceUntilIdle()
157155

158156
assertThat(innerJob!!.isActive).isTrue()
159157

@@ -164,7 +162,7 @@ internal class ViewLaunchWhenAttachedTest {
164162
assertThat(innerJob!!.isCancelled).isTrue()
165163
}
166164

167-
@Test fun `launchWhenAttached includes view classname in coroutine name`() {
165+
@Test fun `launchWhenAttached includes view classname in coroutine name`() = runTest {
168166
var coroutineName: String? = null
169167
mockAttachedToWindow(view, true)
170168

@@ -178,7 +176,7 @@ internal class ViewLaunchWhenAttachedTest {
178176
assertThat(coroutineName).contains("${view.hashCode()}")
179177
}
180178

181-
@Test fun `launchWhenAttached includes view id name in coroutine name`() {
179+
@Test fun `launchWhenAttached includes view id name in coroutine name`() = runTest {
182180
var coroutineName: String? = null
183181
mockAttachedToWindow(view, true)
184182
whenever(view.resources.getResourceEntryName(anyInt())).thenReturn("fnord")
@@ -191,7 +189,7 @@ internal class ViewLaunchWhenAttachedTest {
191189
assertThat(coroutineName).contains("fnord")
192190
}
193191

194-
@Test fun `launchWhenAttached tolerates garbage ids`() {
192+
@Test fun `launchWhenAttached tolerates garbage ids`() = runTest {
195193
var coroutineName: String? = null
196194
mockAttachedToWindow(view, true)
197195
whenever(view.resources.getResourceEntryName(anyInt())).thenThrow(NotFoundException())
@@ -224,7 +222,7 @@ internal class ViewLaunchWhenAttachedTest {
224222
return mock<View>(defaultAnswer = RETURNS_DEEP_STUBS).also {
225223
mockTags(it)
226224
mockAttachedToWindow(it)
227-
ViewTreeLifecycleOwner.set(it, TestLifecycleOwner(coroutineDispatcher = dispatcher))
225+
ViewTreeLifecycleOwner.set(it, TestLifecycleOwner(coroutineDispatcher = UnconfinedTestDispatcher()))
228226
}
229227
}
230228

0 commit comments

Comments
 (0)