1 /*
2  * Copyright (C) 2022 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 com.android.systemui.statusbar.pipeline.wifi.domain.interactor
18 
19 import android.net.wifi.WifiManager
20 import androidx.test.ext.junit.runners.AndroidJUnit4
21 import androidx.test.filters.SmallTest
22 import com.android.systemui.RoboPilotTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.coroutines.collectLastValue
25 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
26 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
27 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
28 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
29 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
30 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
31 import com.google.common.truth.Truth.assertThat
32 import kotlinx.coroutines.ExperimentalCoroutinesApi
33 import kotlinx.coroutines.flow.launchIn
34 import kotlinx.coroutines.flow.onEach
35 import kotlinx.coroutines.test.TestScope
36 import kotlinx.coroutines.test.runCurrent
37 import kotlinx.coroutines.test.runTest
38 import kotlinx.coroutines.yield
39 import org.junit.Before
40 import org.junit.Test
41 import org.junit.runner.RunWith
42 
43 @OptIn(ExperimentalCoroutinesApi::class)
44 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
45 @SmallTest
46 @RoboPilotTest
47 @RunWith(AndroidJUnit4::class)
48 class WifiInteractorImplTest : SysuiTestCase() {
49 
50     private lateinit var underTest: WifiInteractor
51 
52     private lateinit var connectivityRepository: FakeConnectivityRepository
53     private lateinit var wifiRepository: FakeWifiRepository
54 
55     private val testScope = TestScope()
56 
57     @Before
58     fun setUp() {
59         connectivityRepository = FakeConnectivityRepository()
60         wifiRepository = FakeWifiRepository()
61         underTest =
62             WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
63     }
64 
65     @Test
66     fun ssid_unavailableNetwork_outputsNull() =
67         testScope.runTest {
68             wifiRepository.setWifiNetwork(WifiNetworkModel.Unavailable)
69 
70             var latest: String? = "default"
71             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
72             runCurrent()
73 
74             assertThat(latest).isNull()
75 
76             job.cancel()
77         }
78 
79     @Test
80     fun ssid_inactiveNetwork_outputsNull() =
81         testScope.runTest {
82             wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
83 
84             var latest: String? = "default"
85             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
86             runCurrent()
87 
88             assertThat(latest).isNull()
89 
90             job.cancel()
91         }
92 
93     @Test
94     fun ssid_carrierMergedNetwork_outputsNull() =
95         testScope.runTest {
96             wifiRepository.setWifiNetwork(
97                 WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1)
98             )
99 
100             var latest: String? = "default"
101             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
102             runCurrent()
103 
104             assertThat(latest).isNull()
105 
106             job.cancel()
107         }
108 
109     @Test
110     fun ssid_isPasspointAccessPoint_outputsPasspointName() =
111         testScope.runTest {
112             wifiRepository.setWifiNetwork(
113                 WifiNetworkModel.Active(
114                     networkId = 1,
115                     level = 1,
116                     isPasspointAccessPoint = true,
117                     passpointProviderFriendlyName = "friendly",
118                 )
119             )
120 
121             var latest: String? = null
122             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
123             runCurrent()
124 
125             assertThat(latest).isEqualTo("friendly")
126 
127             job.cancel()
128         }
129 
130     @Test
131     fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() =
132         testScope.runTest {
133             wifiRepository.setWifiNetwork(
134                 WifiNetworkModel.Active(
135                     networkId = 1,
136                     level = 1,
137                     isOnlineSignUpForPasspointAccessPoint = true,
138                     passpointProviderFriendlyName = "friendly",
139                 )
140             )
141 
142             var latest: String? = null
143             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
144             runCurrent()
145 
146             assertThat(latest).isEqualTo("friendly")
147 
148             job.cancel()
149         }
150 
151     @Test
152     fun ssid_unknownSsid_outputsNull() =
153         testScope.runTest {
154             wifiRepository.setWifiNetwork(
155                 WifiNetworkModel.Active(
156                     networkId = 1,
157                     level = 1,
158                     ssid = WifiManager.UNKNOWN_SSID,
159                 )
160             )
161 
162             var latest: String? = "default"
163             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
164             runCurrent()
165 
166             assertThat(latest).isNull()
167 
168             job.cancel()
169         }
170 
171     @Test
172     fun ssid_validSsid_outputsSsid() =
173         testScope.runTest {
174             wifiRepository.setWifiNetwork(
175                 WifiNetworkModel.Active(
176                     networkId = 1,
177                     level = 1,
178                     ssid = "MyAwesomeWifiNetwork",
179                 )
180             )
181 
182             var latest: String? = null
183             val job = underTest.ssid.onEach { latest = it }.launchIn(this)
184             runCurrent()
185 
186             assertThat(latest).isEqualTo("MyAwesomeWifiNetwork")
187 
188             job.cancel()
189         }
190 
191     @Test
192     fun isEnabled_matchesRepoIsEnabled() =
193         testScope.runTest {
194             var latest: Boolean? = null
195             val job = underTest.isEnabled.onEach { latest = it }.launchIn(this)
196 
197             wifiRepository.setIsWifiEnabled(true)
198             yield()
199             assertThat(latest).isTrue()
200 
201             wifiRepository.setIsWifiEnabled(false)
202             yield()
203             assertThat(latest).isFalse()
204 
205             wifiRepository.setIsWifiEnabled(true)
206             yield()
207             assertThat(latest).isTrue()
208 
209             job.cancel()
210         }
211 
212     @Test
213     fun isDefault_matchesRepoIsDefault() =
214         testScope.runTest {
215             var latest: Boolean? = null
216             val job = underTest.isDefault.onEach { latest = it }.launchIn(this)
217 
218             wifiRepository.setIsWifiDefault(true)
219             yield()
220             assertThat(latest).isTrue()
221 
222             wifiRepository.setIsWifiDefault(false)
223             yield()
224             assertThat(latest).isFalse()
225 
226             wifiRepository.setIsWifiDefault(true)
227             yield()
228             assertThat(latest).isTrue()
229 
230             job.cancel()
231         }
232 
233     @Test
234     fun wifiNetwork_matchesRepoWifiNetwork() =
235         testScope.runTest {
236             val wifiNetwork =
237                 WifiNetworkModel.Active(
238                     networkId = 45,
239                     isValidated = true,
240                     level = 3,
241                     ssid = "AB",
242                     passpointProviderFriendlyName = "friendly"
243                 )
244             wifiRepository.setWifiNetwork(wifiNetwork)
245 
246             var latest: WifiNetworkModel? = null
247             val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this)
248             runCurrent()
249 
250             assertThat(latest).isEqualTo(wifiNetwork)
251 
252             job.cancel()
253         }
254 
255     @Test
256     fun activity_matchesRepoWifiActivity() =
257         testScope.runTest {
258             var latest: DataActivityModel? = null
259             val job = underTest.activity.onEach { latest = it }.launchIn(this)
260 
261             val activity1 = DataActivityModel(hasActivityIn = true, hasActivityOut = true)
262             wifiRepository.setWifiActivity(activity1)
263             yield()
264             assertThat(latest).isEqualTo(activity1)
265 
266             val activity2 = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
267             wifiRepository.setWifiActivity(activity2)
268             yield()
269             assertThat(latest).isEqualTo(activity2)
270 
271             val activity3 = DataActivityModel(hasActivityIn = true, hasActivityOut = false)
272             wifiRepository.setWifiActivity(activity3)
273             yield()
274             assertThat(latest).isEqualTo(activity3)
275 
276             job.cancel()
277         }
278 
279     @Test
280     fun isForceHidden_repoHasWifiHidden_outputsTrue() =
281         testScope.runTest {
282             connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI))
283 
284             var latest: Boolean? = null
285             val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
286             runCurrent()
287 
288             assertThat(latest).isTrue()
289 
290             job.cancel()
291         }
292 
293     @Test
294     fun isForceHidden_repoDoesNotHaveWifiHidden_outputsFalse() =
295         testScope.runTest {
296             connectivityRepository.setForceHiddenIcons(setOf())
297 
298             var latest: Boolean? = null
299             val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
300             runCurrent()
301 
302             assertThat(latest).isFalse()
303 
304             job.cancel()
305         }
306 
307     @Test
308     fun areNetworksAvailable_noneActive_noResults() =
309         testScope.runTest {
310             val latest by collectLastValue(underTest.areNetworksAvailable)
311 
312             wifiRepository.wifiScanResults.value = emptyList()
313             wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
314 
315             assertThat(latest).isFalse()
316         }
317 
318     @Test
319     fun areNetworksAvailable_noneActive_nonEmptyResults() =
320         testScope.runTest {
321             val latest by collectLastValue(underTest.areNetworksAvailable)
322 
323             wifiRepository.wifiScanResults.value =
324                 listOf(
325                     WifiScanEntry(ssid = "ssid 1"),
326                     WifiScanEntry(ssid = "ssid 2"),
327                     WifiScanEntry(ssid = "ssid 3"),
328                 )
329 
330             wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
331 
332             assertThat(latest).isTrue()
333         }
334 
335     @Test
336     fun areNetworksAvailable_activeNetwork_resultsIncludeOtherNetworks() =
337         testScope.runTest {
338             val latest by collectLastValue(underTest.areNetworksAvailable)
339 
340             wifiRepository.wifiScanResults.value =
341                 listOf(
342                     WifiScanEntry(ssid = "ssid 1"),
343                     WifiScanEntry(ssid = "ssid 2"),
344                     WifiScanEntry(ssid = "ssid 3"),
345                 )
346 
347             wifiRepository.setWifiNetwork(
348                 WifiNetworkModel.Active(
349                     ssid = "ssid 2",
350                     networkId = 1,
351                     level = 2,
352                 )
353             )
354 
355             assertThat(latest).isTrue()
356         }
357 
358     @Test
359     fun areNetworksAvailable_activeNetwork_onlyResultIsTheActiveNetwork() =
360         testScope.runTest {
361             val latest by collectLastValue(underTest.areNetworksAvailable)
362 
363             wifiRepository.wifiScanResults.value =
364                 listOf(
365                     WifiScanEntry(ssid = "ssid 2"),
366                 )
367 
368             wifiRepository.setWifiNetwork(
369                 WifiNetworkModel.Active(
370                     ssid = "ssid 2",
371                     networkId = 1,
372                     level = 2,
373                 )
374             )
375 
376             assertThat(latest).isFalse()
377         }
378 }
379