1 /*
2  * Copyright (C) 2018 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.server.wm.flicker;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.inOrder;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.verifyNoMoreInteractions;
26 
27 import android.os.Environment;
28 
29 import androidx.test.runner.AndroidJUnit4;
30 
31 import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
32 import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
33 import com.android.server.wm.flicker.monitor.LayersTraceMonitor;
34 import com.android.server.wm.flicker.monitor.ScreenRecorder;
35 import com.android.server.wm.flicker.monitor.WindowAnimationFrameStatsMonitor;
36 import com.android.server.wm.flicker.monitor.WindowManagerTraceMonitor;
37 
38 import org.junit.Before;
39 import org.junit.FixMethodOrder;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.MethodSorters;
43 import org.mockito.InOrder;
44 import org.mockito.InjectMocks;
45 import org.mockito.Mock;
46 import org.mockito.MockitoAnnotations;
47 
48 import java.nio.file.Paths;
49 import java.util.List;
50 
51 /** Contains {@link TransitionRunner} tests. {@code atest FlickerLibTest:TransitionRunnerTest} */
52 @RunWith(AndroidJUnit4.class)
53 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
54 public class TransitionRunnerTest {
55     @Mock private SimpleUiTransitions mTransitionsMock;
56     @Mock private ScreenRecorder mScreenRecorderMock;
57     @Mock private WindowManagerTraceMonitor mWindowManagerTraceMonitorMock;
58     @Mock private LayersTraceMonitor mLayersTraceMonitorMock;
59     @Mock private WindowAnimationFrameStatsMonitor mWindowAnimationFrameStatsMonitor;
60     @InjectMocks private TransitionBuilder mTransitionBuilder = TransitionRunner.newBuilder();
61 
62     @Before
init()63     public void init() {
64         MockitoAnnotations.initMocks(this);
65     }
66 
67     @Test
transitionsRunInOrder()68     public void transitionsRunInOrder() {
69         TransitionRunner.newBuilder()
70                 .runBeforeAll(mTransitionsMock::turnOnDevice)
71                 .runBefore(mTransitionsMock::openApp)
72                 .run(mTransitionsMock::performMagic)
73                 .runAfter(mTransitionsMock::closeApp)
74                 .runAfterAll(mTransitionsMock::cleanUpTracks)
75                 .skipLayersTrace()
76                 .skipWindowManagerTrace()
77                 .build()
78                 .run();
79 
80         InOrder orderVerifier = inOrder(mTransitionsMock);
81         orderVerifier.verify(mTransitionsMock).turnOnDevice();
82         orderVerifier.verify(mTransitionsMock).openApp();
83         orderVerifier.verify(mTransitionsMock).performMagic();
84         orderVerifier.verify(mTransitionsMock).closeApp();
85         orderVerifier.verify(mTransitionsMock).cleanUpTracks();
86     }
87 
88     @Test
canCombineTransitions()89     public void canCombineTransitions() {
90         TransitionRunner.newBuilder()
91                 .runBeforeAll(mTransitionsMock::turnOnDevice)
92                 .runBeforeAll(mTransitionsMock::turnOnDevice)
93                 .runBefore(mTransitionsMock::openApp)
94                 .runBefore(mTransitionsMock::openApp)
95                 .run(mTransitionsMock::performMagic)
96                 .run(mTransitionsMock::performMagic)
97                 .runAfter(mTransitionsMock::closeApp)
98                 .runAfter(mTransitionsMock::closeApp)
99                 .runAfterAll(mTransitionsMock::cleanUpTracks)
100                 .runAfterAll(mTransitionsMock::cleanUpTracks)
101                 .skipLayersTrace()
102                 .skipWindowManagerTrace()
103                 .build()
104                 .run();
105 
106         final int wantedNumberOfInvocations = 2;
107         verify(mTransitionsMock, times(wantedNumberOfInvocations)).turnOnDevice();
108         verify(mTransitionsMock, times(wantedNumberOfInvocations)).openApp();
109         verify(mTransitionsMock, times(wantedNumberOfInvocations)).performMagic();
110         verify(mTransitionsMock, times(wantedNumberOfInvocations)).closeApp();
111         verify(mTransitionsMock, times(wantedNumberOfInvocations)).cleanUpTracks();
112     }
113 
114     @Test
emptyTransitionPasses()115     public void emptyTransitionPasses() {
116         List<TransitionResult> results =
117                 TransitionRunner.newBuilder()
118                         .skipLayersTrace()
119                         .skipWindowManagerTrace()
120                         .build()
121                         .run()
122                         .getResults();
123         assertThat(results).hasSize(1);
124         assertThat(results.get(0).layersTraceExists()).isFalse();
125         assertThat(results.get(0).windowManagerTraceExists()).isFalse();
126         assertThat(results.get(0).screenCaptureVideoExists()).isFalse();
127     }
128 
129     @Test
canRepeatTransitions()130     public void canRepeatTransitions() {
131         final int wantedNumberOfInvocations = 10;
132         TransitionRunner.newBuilder()
133                 .runBeforeAll(mTransitionsMock::turnOnDevice)
134                 .runBefore(mTransitionsMock::openApp)
135                 .run(mTransitionsMock::performMagic)
136                 .runAfter(mTransitionsMock::closeApp)
137                 .runAfterAll(mTransitionsMock::cleanUpTracks)
138                 .repeat(wantedNumberOfInvocations)
139                 .skipLayersTrace()
140                 .skipWindowManagerTrace()
141                 .build()
142                 .run();
143         verify(mTransitionsMock).turnOnDevice();
144         verify(mTransitionsMock, times(wantedNumberOfInvocations)).openApp();
145         verify(mTransitionsMock, times(wantedNumberOfInvocations)).performMagic();
146         verify(mTransitionsMock, times(wantedNumberOfInvocations)).closeApp();
147         verify(mTransitionsMock).cleanUpTracks();
148     }
149 
emptyTask()150     private void emptyTask() {}
151 
152     @Test
canCaptureWindowManagerTrace()153     public void canCaptureWindowManagerTrace() {
154         mTransitionBuilder
155                 .run(this::emptyTask)
156                 .includeJankyRuns()
157                 .skipLayersTrace()
158                 .withTag("mCaptureWmTraceTransitionRunner")
159                 .build()
160                 .run();
161         InOrder orderVerifier = inOrder(mWindowManagerTraceMonitorMock);
162         orderVerifier.verify(mWindowManagerTraceMonitorMock).start();
163         orderVerifier.verify(mWindowManagerTraceMonitorMock).stop();
164         orderVerifier
165                 .verify(mWindowManagerTraceMonitorMock)
166                 .save("mCaptureWmTraceTransitionRunner", 0);
167         orderVerifier.verify(mWindowManagerTraceMonitorMock).getChecksum();
168         verifyNoMoreInteractions(mWindowManagerTraceMonitorMock);
169     }
170 
171     @Test
canCaptureLayersTrace()172     public void canCaptureLayersTrace() {
173         mTransitionBuilder
174                 .run(this::emptyTask)
175                 .includeJankyRuns()
176                 .skipWindowManagerTrace()
177                 .withTag("mCaptureLayersTraceTransitionRunner")
178                 .build()
179                 .run();
180         InOrder orderVerifier = inOrder(mLayersTraceMonitorMock);
181         orderVerifier.verify(mLayersTraceMonitorMock).start();
182         orderVerifier.verify(mLayersTraceMonitorMock).stop();
183         orderVerifier
184                 .verify(mLayersTraceMonitorMock)
185                 .save("mCaptureLayersTraceTransitionRunner", 0);
186         orderVerifier.verify(mLayersTraceMonitorMock).getChecksum();
187         verifyNoMoreInteractions(mLayersTraceMonitorMock);
188     }
189 
190     @Test
canRecordEachRun()191     public void canRecordEachRun() {
192         mTransitionBuilder
193                 .run(this::emptyTask)
194                 .withTag("mRecordEachRun")
195                 .recordEachRun()
196                 .includeJankyRuns()
197                 .skipLayersTrace()
198                 .skipWindowManagerTrace()
199                 .repeat(2)
200                 .build()
201                 .run();
202         InOrder orderVerifier = inOrder(mScreenRecorderMock);
203         orderVerifier.verify(mScreenRecorderMock).start();
204         orderVerifier.verify(mScreenRecorderMock).stop();
205         orderVerifier.verify(mScreenRecorderMock).save("mRecordEachRun", 0);
206         orderVerifier.verify(mScreenRecorderMock).getChecksum();
207         orderVerifier.verify(mScreenRecorderMock).start();
208         orderVerifier.verify(mScreenRecorderMock).stop();
209         orderVerifier.verify(mScreenRecorderMock).save("mRecordEachRun", 1);
210         orderVerifier.verify(mScreenRecorderMock).getChecksum();
211         verifyNoMoreInteractions(mScreenRecorderMock);
212     }
213 
214     @Test
canRecordAllRuns()215     public void canRecordAllRuns() {
216         doReturn(
217                         Paths.get(
218                                 Environment.getExternalStorageDirectory().getAbsolutePath(),
219                                 "mRecordAllRuns.mp4"))
220                 .when(mScreenRecorderMock)
221                 .save("mRecordAllRuns");
222         mTransitionBuilder
223                 .run(this::emptyTask)
224                 .recordAllRuns()
225                 .includeJankyRuns()
226                 .skipLayersTrace()
227                 .skipWindowManagerTrace()
228                 .withTag("mRecordAllRuns")
229                 .repeat(2)
230                 .build()
231                 .run();
232         InOrder orderVerifier = inOrder(mScreenRecorderMock);
233         orderVerifier.verify(mScreenRecorderMock).start();
234         orderVerifier.verify(mScreenRecorderMock).stop();
235         orderVerifier.verify(mScreenRecorderMock).save("mRecordAllRuns");
236         verifyNoMoreInteractions(mScreenRecorderMock);
237     }
238 
239     @Test
canSkipJankyRuns()240     public void canSkipJankyRuns() {
241         doReturn(false)
242                 .doReturn(true)
243                 .doReturn(false)
244                 .when(mWindowAnimationFrameStatsMonitor)
245                 .jankyFramesDetected();
246         List<TransitionResult> results =
247                 mTransitionBuilder
248                         .run(this::emptyTask)
249                         .skipLayersTrace()
250                         .skipWindowManagerTrace()
251                         .repeat(3)
252                         .build()
253                         .run()
254                         .getResults();
255         assertThat(results).hasSize(2);
256     }
257 
258     public static class SimpleUiTransitions {
turnOnDevice()259         public void turnOnDevice() {}
260 
openApp()261         public void openApp() {}
262 
performMagic()263         public void performMagic() {}
264 
closeApp()265         public void closeApp() {}
266 
cleanUpTracks()267         public void cleanUpTracks() {}
268     }
269 }
270