1
+ import kotlinx.coroutines.*
2
+ import kotlinx.coroutines.test.*
3
+ import java.lang.ref.*
4
+ import kotlin.test.*
5
+
6
+ class TestCoroutineSchedulerJvmTest {
7
+
8
+ /* *
9
+ * This test demonstrates a bug in the TestCoroutineScheduler implementation: canceled delayed
10
+ * jobs are held in memory by TestCoroutineScheduler until the TestCoroutineScheduler current
11
+ * time has moved past the job's planned time, even though said job has long been canceled.
12
+ *
13
+ * Canceled jobs should instead be immediately removed from TestCoroutineScheduler#events.
14
+ */
15
+ @Test
16
+ fun testCancellationLeakInTestCoroutineScheduler () = runTest {
17
+ lateinit var weakRef: WeakReference <* >
18
+ val delayedLeakingJob = launch {
19
+ val leakingObject = Any ()
20
+ weakRef = WeakReference (leakingObject)
21
+ // This delay prevents the job from finishing.
22
+ delay(3 )
23
+ // This is never called as job is canceled before we get here. However this code
24
+ // holds a reference to leakingObject, preventing it from becoming weakly reachable
25
+ // until the job itself is weakly reachable.
26
+ println (leakingObject)
27
+ }
28
+
29
+ // Start running the job and hit delay.
30
+ advanceTimeBy(1 )
31
+
32
+ // At this point, delayedLeakingJob is still in the queue and holding on to leakingObject.
33
+ System .gc()
34
+ assertNotNull(weakRef.get())
35
+
36
+ // We're canceling the job, and now expect leakingObject to become weakly reachable.
37
+ delayedLeakingJob.cancel()
38
+
39
+ // Surprise: the canceled job is not weakly reachable! TestCoroutineScheduler is holding
40
+ // on to it in its TestCoroutineScheduler#events queue.
41
+ System .gc()
42
+ assertNotNull(weakRef.get())
43
+
44
+ // Let's move time forward without going over the delay yet.
45
+ advanceTimeBy(1 )
46
+
47
+ // Still not weakly reachable.
48
+ System .gc()
49
+ assertNotNull(weakRef.get())
50
+
51
+ // Now we move past the delay
52
+ advanceTimeBy(2 )
53
+
54
+ // The job is finally weakly reachable and leakingObject is released.
55
+ System .gc()
56
+ assertNull(weakRef.get())
57
+ }
58
+ }
0 commit comments