1 /* 2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines.tasks 6 7 import com.google.android.gms.tasks.* 8 import kotlinx.coroutines.* 9 import org.junit.* 10 import org.junit.Test 11 import java.util.concurrent.locks.* 12 import kotlin.concurrent.* 13 import kotlin.test.* 14 15 class TaskTest : TestBase() { 16 @Before setupnull17 fun setup() { 18 ignoreLostThreads("ForkJoinPool.commonPool-worker-") 19 } 20 21 @Test <lambda>null22 fun testCompletedDeferredAsTask() = runTest { 23 expect(1) 24 val deferred = async(start = CoroutineStart.UNDISPATCHED) { 25 expect(2) // Completed immediately 26 "OK" 27 } 28 expect(3) 29 val task = deferred.asTask() 30 assertEquals("OK", task.await()) 31 finish(4) 32 } 33 34 @Test <lambda>null35 fun testDeferredAsTask() = runTest { 36 expect(1) 37 val deferred = async { 38 expect(3) // Completed later 39 "OK" 40 } 41 expect(2) 42 val task = deferred.asTask() 43 assertEquals("OK", task.await()) 44 finish(4) 45 } 46 47 @Test testCancelledAsTasknull48 fun testCancelledAsTask() { 49 val deferred = GlobalScope.async { 50 delay(100) 51 }.apply { cancel() } 52 53 val task = deferred.asTask() 54 try { 55 runTest { task.await() } 56 } catch (e: Exception) { 57 assertTrue(e is CancellationException) 58 assertTrue(task.isCanceled) 59 } 60 } 61 62 @Test testThrowingAsTasknull63 fun testThrowingAsTask() { 64 val deferred = GlobalScope.async { 65 throw TestException("Fail") 66 } 67 68 val task = deferred.asTask() 69 runTest(expected = { it is TestException }) { 70 task.await() 71 } 72 } 73 74 @Test <lambda>null75 fun testStateAsTask() = runTest { 76 val lock = ReentrantLock().apply { lock() } 77 78 val deferred: Deferred<Int> = Tasks.call { 79 lock.withLock { 42 } 80 }.asDeferred() 81 82 assertFalse(deferred.isCompleted) 83 lock.unlock() 84 85 assertEquals(42, deferred.await()) 86 assertTrue(deferred.isCompleted) 87 } 88 89 @Test <lambda>null90 fun testTaskAsDeferred() = runTest { 91 val deferred = Tasks.forResult(42).asDeferred() 92 assertEquals(42, deferred.await()) 93 } 94 95 @Test <lambda>null96 fun testNullResultTaskAsDeferred() = runTest { 97 assertNull(Tasks.forResult(null).asDeferred().await()) 98 } 99 100 @Test <lambda>null101 fun testCancelledTaskAsDeferred() = runTest { 102 val deferred = Tasks.forCanceled<Int>().asDeferred() 103 104 assertTrue(deferred.isCancelled) 105 try { 106 deferred.await() 107 fail("deferred.await() should be cancelled") 108 } catch (e: Exception) { 109 assertTrue(e is CancellationException) 110 } 111 } 112 113 @Test testFailedTaskAsDeferrednull114 fun testFailedTaskAsDeferred() = runTest { 115 val deferred = Tasks.forException<Int>(TestException("something went wrong")).asDeferred() 116 117 assertTrue(deferred.isCancelled && deferred.isCompleted) 118 val completionException = deferred.getCompletionExceptionOrNull()!! 119 assertTrue(completionException is TestException) 120 assertEquals("something went wrong", completionException.message) 121 122 try { 123 deferred.await() 124 fail("deferred.await() should throw an exception") 125 } catch (e: Exception) { 126 assertTrue(e is TestException) 127 assertEquals("something went wrong", e.message) 128 } 129 } 130 131 @Test <lambda>null132 fun testFailingTaskAsDeferred() = runTest { 133 val lock = ReentrantLock().apply { lock() } 134 135 val deferred: Deferred<Int> = Tasks.call { 136 lock.withLock { throw TestException("something went wrong") } 137 }.asDeferred() 138 139 assertFalse(deferred.isCompleted) 140 lock.unlock() 141 142 try { 143 deferred.await() 144 fail("deferred.await() should throw an exception") 145 } catch (e: Exception) { 146 assertTrue(e is TestException) 147 assertEquals("something went wrong", e.message) 148 assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation 149 } 150 } 151 152 class TestException(message: String) : Exception(message) 153 } 154