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.arch.core.executor.ArchTaskExecutor
20 import androidx.test.annotation.UiThreadTest
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.MediumTest
23 import com.google.common.truth.Truth.assertThat
24 import kotlinx.coroutines.CompletableDeferred
25 import kotlinx.coroutines.Dispatchers
26 import kotlinx.coroutines.ExperimentalCoroutinesApi
27 import kotlinx.coroutines.FlowPreview
28 import kotlinx.coroutines.flow.MutableStateFlow
29 import kotlinx.coroutines.flow.channelFlow
30 import kotlinx.coroutines.flow.first
31 import kotlinx.coroutines.runBlocking
32 import kotlinx.coroutines.withContext
33 import org.junit.Before
34 import org.junit.Test
35 import org.junit.runner.RunWith
36 
37 @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
38 @RunWith(AndroidJUnit4::class)
39 class FlowAsLiveDataIntegrationTest {
40 
41     @Before
clearArchExecutorsnull42     fun clearArchExecutors() {
43         // make sure we don't receive a modified delegate. b/159212029
44         ArchTaskExecutor.getInstance().setDelegate(null)
45     }
46 
47     @Test
48     @MediumTest
startStopImmediatelynull49     fun startStopImmediately() {
50         runBlocking {
51             val stopChannelFlow = CompletableDeferred<Unit>()
52             val (mediator, liveData) =
53                 withContext(Dispatchers.Main) {
54                     val mediator = MediatorLiveData<Int>()
55                     val liveData =
56                         channelFlow {
57                                 send(1)
58                                 // prevent block from ending
59                                 stopChannelFlow.await()
60                             }
61                             .asLiveData()
62                     mediator.addSource(liveData) {
63                         mediator.removeSource(liveData)
64                         mediator.value = -it
65                     }
66                     mediator to liveData
67                 }
68             val read = mediator.asFlow().first()
69             assertThat(read).isEqualTo(-1)
70             assertThat(liveData.hasObservers()).isFalse()
71             // make sure this test doesn't leak a running coroutine
72             stopChannelFlow.complete(Unit)
73         }
74     }
75 
76     @UiThreadTest
77     @Test
78     @MediumTest
asLiveData_preserveStateFlowInitialValuenull79     fun asLiveData_preserveStateFlowInitialValue() {
80         val value = "init"
81         val result = MutableStateFlow(value).asLiveData().value
82         assertThat(result).isNotNull()
83         assertThat(result).isEqualTo(value)
84     }
85 }
86