1 /*
2  * Copyright (C) 2024 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.screenrecord.data.repository
18 
19 import android.media.projection.StopReason
20 import androidx.test.ext.junit.runners.AndroidJUnit4
21 import androidx.test.filters.SmallTest
22 import com.android.systemui.SysuiTestCase
23 import com.android.systemui.coroutines.collectLastValue
24 import com.android.systemui.kosmos.Kosmos
25 import com.android.systemui.kosmos.testScope
26 import com.android.systemui.screenrecord.RecordingController
27 import com.android.systemui.screenrecord.data.model.ScreenRecordModel
28 import com.google.common.truth.Truth.assertThat
29 import kotlinx.coroutines.ExperimentalCoroutinesApi
30 import kotlinx.coroutines.test.runCurrent
31 import kotlinx.coroutines.test.runTest
32 import org.junit.Test
33 import org.junit.runner.RunWith
34 import org.mockito.kotlin.argumentCaptor
35 import org.mockito.kotlin.eq
36 import org.mockito.kotlin.mock
37 import org.mockito.kotlin.verify
38 import org.mockito.kotlin.whenever
39 
40 @SmallTest
41 @OptIn(ExperimentalCoroutinesApi::class)
42 @RunWith(AndroidJUnit4::class)
43 class ScreenRecordRepositoryTest : SysuiTestCase() {
44     private val kosmos = Kosmos()
45     private val testScope = kosmos.testScope
46     private val recordingController = mock<RecordingController>()
47 
48     private val underTest =
49         ScreenRecordRepositoryImpl(
50             bgCoroutineContext = testScope.testScheduler,
51             recordingController = recordingController,
52         )
53 
54     private val isRecording = ScreenRecordModel.Recording
55     private val isDoingNothing = ScreenRecordModel.DoingNothing
56     private val isStarting0 = ScreenRecordModel.Starting(0)
57 
58     @Test
dataMatchesControllernull59     fun dataMatchesController() =
60         testScope.runTest {
61             whenever(recordingController.isRecording).thenReturn(false)
62             whenever(recordingController.isStarting).thenReturn(false)
63 
64             val callbackCaptor = argumentCaptor<RecordingController.RecordingStateChangeCallback>()
65 
66             val lastModel by collectLastValue(underTest.screenRecordState)
67             runCurrent()
68 
69             verify(recordingController).addCallback(callbackCaptor.capture())
70             val callback = callbackCaptor.firstValue
71 
72             assertThat(lastModel).isEqualTo(isDoingNothing)
73 
74             val expectedModelStartingIn1 = ScreenRecordModel.Starting(1)
75             callback.onCountdown(1)
76             assertThat(lastModel).isEqualTo(expectedModelStartingIn1)
77 
78             val expectedModelStartingIn0 = isStarting0
79             callback.onCountdown(0)
80             assertThat(lastModel).isEqualTo(expectedModelStartingIn0)
81 
82             callback.onCountdownEnd()
83             assertThat(lastModel).isEqualTo(isDoingNothing)
84 
85             callback.onRecordingStart()
86             assertThat(lastModel).isEqualTo(isRecording)
87 
88             callback.onRecordingEnd()
89             assertThat(lastModel).isEqualTo(isDoingNothing)
90         }
91 
92     @Test
data_whenRecording_matchesControllernull93     fun data_whenRecording_matchesController() =
94         testScope.runTest {
95             whenever(recordingController.isRecording).thenReturn(true)
96             whenever(recordingController.isStarting).thenReturn(false)
97 
98             val lastModel by collectLastValue(underTest.screenRecordState)
99             runCurrent()
100 
101             assertThat(lastModel).isEqualTo(isRecording)
102         }
103 
104     @Test
data_whenStarting_matchesControllernull105     fun data_whenStarting_matchesController() =
106         testScope.runTest {
107             whenever(recordingController.isRecording).thenReturn(false)
108             whenever(recordingController.isStarting).thenReturn(true)
109 
110             val lastModel by collectLastValue(underTest.screenRecordState)
111             runCurrent()
112 
113             assertThat(lastModel).isEqualTo(isStarting0)
114         }
115 
116     @Test
data_whenRecordingAndStarting_matchesControllerRecordingnull117     fun data_whenRecordingAndStarting_matchesControllerRecording() =
118         testScope.runTest {
119             whenever(recordingController.isRecording).thenReturn(true)
120             whenever(recordingController.isStarting).thenReturn(true)
121 
122             val lastModel by collectLastValue(underTest.screenRecordState)
123             runCurrent()
124 
125             assertThat(lastModel).isEqualTo(isRecording)
126         }
127 
128     @Test
stopRecording_invokesControllernull129     fun stopRecording_invokesController() =
130         testScope.runTest {
131             underTest.stopRecording(StopReason.STOP_PRIVACY_CHIP)
132 
133             verify(recordingController).stopRecording(eq(StopReason.STOP_PRIVACY_CHIP))
134         }
135 }
136