1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.lifecycle
18 
19 import androidx.kruth.assertWithMessage
20 import androidx.testutils.lifecycle.FakeLifecycleOwner
21 import kotlin.test.Test
22 import kotlin.test.assertEquals
23 import kotlin.test.assertFailsWith
24 import kotlinx.coroutines.async
25 import kotlinx.coroutines.launch
26 import kotlinx.coroutines.yield
27 
28 class WithLifecycleStateTest {
29     @Test
<lambda>null30     fun testInitialResumed() = runLifecycleTest {
31         val owner = FakeLifecycleOwner(Lifecycle.State.RESUMED)
32 
33         val expected = "initial value"
34         var toRead = expected
35         launch { toRead = "value set by launch" }
36         val readByWithStarted = owner.withStarted { toRead }
37         assertEquals(expected, readByWithStarted)
38     }
39 
40     @Test
<lambda>null41     fun testBlockRunsWithLifecycleStateChange() = runLifecycleTest {
42         val owner = FakeLifecycleOwner()
43 
44         val initial = "initial value"
45         val afterSetState = "value set after setState"
46         var toRead = initial
47         launch {
48             owner.setState(Lifecycle.State.RESUMED)
49             toRead = afterSetState
50         }
51         val readByWithStarted = owner.withStarted { toRead }
52         val readAfterResumed = toRead
53         assertEquals(initial, readByWithStarted)
54         assertEquals(afterSetState, readAfterResumed)
55     }
56 
57     @Test
<lambda>null58     fun testBlockCancelledWhenInitiallyDestroyed() = runLifecycleTest {
59         val owner = FakeLifecycleOwner(Lifecycle.State.CREATED)
60         owner.setState(Lifecycle.State.DESTROYED)
61 
62         assertFailsWith<LifecycleDestroyedException> { owner.withStarted {} }
63     }
64 
65     @Test
<lambda>null66     fun testBlockCancelledWhenDestroyedWhileSuspended() = runLifecycleTest {
67         val owner = FakeLifecycleOwner(Lifecycle.State.CREATED)
68 
69         var launched = false
70         val resultTask = async {
71             launched = true
72             runCatching { owner.withStarted {} }
73         }
74         yield()
75 
76         assertWithMessage("test ran to first suspension after successfully launching")
77             .that(launched)
78             .isTrue()
79         assertWithMessage("withStarted is still active").that(resultTask.isActive).isTrue()
80 
81         owner.setState(Lifecycle.State.DESTROYED)
82 
83         assertWithMessage("result threw LifecycleDestroyedException")
84             .that(resultTask.await().exceptionOrNull())
85             .isInstanceOf<LifecycleDestroyedException>()
86     }
87 }
88