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.server.wm.flicker
18 
19 import android.app.Instrumentation
20 import android.platform.test.annotations.Presubmit
21 import android.tools.common.traces.component.ComponentNameMatcher
22 import android.tools.device.flicker.junit.FlickerBuilderProvider
23 import android.tools.device.flicker.legacy.FlickerBuilder
24 import android.tools.device.flicker.legacy.LegacyFlickerTest
25 import android.util.Log
26 import androidx.test.platform.app.InstrumentationRegistry
27 import com.android.launcher3.tapl.LauncherInstrumentation
28 import org.junit.Assume
29 import org.junit.AssumptionViolatedException
30 import org.junit.Test
31 
32 /**
33  * Base test class containing common assertions for [ComponentNameMatcher.NAV_BAR],
34  * [ComponentNameMatcher.TASK_BAR], [ComponentNameMatcher.STATUS_BAR], and general assertions
35  * (layers visible in consecutive states, entire screen covered, etc.)
36  */
37 abstract class BaseTest
38 @JvmOverloads
39 constructor(
40     protected val flicker: LegacyFlickerTest,
41     protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation(),
42     protected val tapl: LauncherInstrumentation = LauncherInstrumentation()
43 ) {
44     init {
45         tapl.setExpectedRotationCheckEnabled(true)
46     }
47 
48     private val logTag = this::class.java.simpleName
49 
50     /** Specification of the test transition to execute */
51     abstract val transition: FlickerBuilder.() -> Unit
52 
53     /**
54      * Entry point for the test runner. It will use this method to initialize and cache flicker
55      * executions
56      */
57     @FlickerBuilderProvider
58     fun buildFlicker(): FlickerBuilder {
59         return FlickerBuilder(instrumentation).apply {
60             setup { flicker.scenario.setIsTablet(wmHelper.currentState.wmState.isTablet) }
61             transition()
62         }
63     }
64 
65     /** Checks that all parts of the screen are covered during the transition */
66     @Presubmit @Test open fun entireScreenCovered() = flicker.entireScreenCovered()
67 
68     /**
69      * Checks that the [ComponentNameMatcher.NAV_BAR] layer is visible during the whole transition
70      *
71      * Note: Phones only
72      */
73     @Presubmit
74     @Test
75     open fun navBarLayerIsVisibleAtStartAndEnd() {
76         Assume.assumeFalse(flicker.scenario.isTablet)
77         flicker.navBarLayerIsVisibleAtStartAndEnd()
78     }
79 
80     /**
81      * Checks the position of the [ComponentNameMatcher.NAV_BAR] at the start and end of the
82      * transition
83      *
84      * Note: Phones only
85      */
86     @Presubmit
87     @Test
88     open fun navBarLayerPositionAtStartAndEnd() {
89         Assume.assumeFalse(flicker.scenario.isTablet)
90         flicker.navBarLayerPositionAtStartAndEnd()
91     }
92 
93     /**
94      * Checks that the [ComponentNameMatcher.NAV_BAR] window is visible during the whole transition
95      *
96      * Note: Phones only
97      */
98     @Presubmit
99     @Test
100     open fun navBarWindowIsAlwaysVisible() {
101         Assume.assumeFalse(flicker.scenario.isTablet)
102         Assume.assumeFalse(flicker.scenario.isLandscapeOrSeascapeAtStart)
103         flicker.navBarWindowIsAlwaysVisible()
104     }
105 
106     /**
107      * Checks that the [ComponentNameMatcher.NAV_BAR] window is visible at the start and end of the
108      * transition
109      *
110      * Note: Phones only
111      */
112     @Presubmit
113     @Test
114     open fun navBarWindowIsVisibleAtStartAndEnd() {
115         Assume.assumeFalse(flicker.scenario.isTablet)
116         flicker.navBarWindowIsVisibleAtStartAndEnd()
117     }
118 
119     /**
120      * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of the
121      * transition
122      *
123      * Note: Large screen only
124      */
125     @Presubmit
126     @Test
127     open fun taskBarLayerIsVisibleAtStartAndEnd() {
128         Assume.assumeTrue(flicker.scenario.isTablet)
129         flicker.taskBarLayerIsVisibleAtStartAndEnd()
130     }
131 
132     /**
133      * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole transition
134      *
135      * Note: Large screen only
136      */
137     @Presubmit
138     @Test
139     open fun taskBarWindowIsAlwaysVisible() {
140         Assume.assumeTrue(flicker.scenario.isTablet)
141         flicker.taskBarWindowIsAlwaysVisible()
142     }
143 
144     /**
145      * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the start and end of
146      * the transition
147      */
148     @Presubmit
149     @Test
150     open fun statusBarLayerIsVisibleAtStartAndEnd() = flicker.statusBarLayerIsVisibleAtStartAndEnd()
151 
152     /**
153      * Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
154      * transition
155      */
156     @Presubmit
157     @Test
158     open fun statusBarLayerPositionAtStartAndEnd() = flicker.statusBarLayerPositionAtStartAndEnd()
159 
160     /**
161      * Checks that the [ComponentNameMatcher.STATUS_BAR] window is visible during the whole
162      * transition
163      */
164     @Presubmit
165     @Test
166     open fun statusBarWindowIsAlwaysVisible() = flicker.statusBarWindowIsAlwaysVisible()
167 
168     /**
169      * Checks that all layers that are visible on the trace, are visible for at least 2 consecutive
170      * entries.
171      */
172     @Presubmit
173     @Test
174     open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
175         flicker.assertLayers { this.visibleLayersShownMoreThanOneConsecutiveEntry() }
176     }
177 
178     /**
179      * Checks that all windows that are visible on the trace, are visible for at least 2 consecutive
180      * entries.
181      */
182     @Presubmit
183     @Test
184     open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
185         flicker.assertWm { this.visibleWindowsShownMoreThanOneConsecutiveEntry() }
186     }
187 
188     open fun cujCompleted() {
189         runAndIgnoreAssumptionViolation { entireScreenCovered() }
190         runAndIgnoreAssumptionViolation { statusBarLayerIsVisibleAtStartAndEnd() }
191         runAndIgnoreAssumptionViolation { statusBarLayerPositionAtStartAndEnd() }
192         runAndIgnoreAssumptionViolation { statusBarWindowIsAlwaysVisible() }
193         runAndIgnoreAssumptionViolation { visibleLayersShownMoreThanOneConsecutiveEntry() }
194         runAndIgnoreAssumptionViolation { visibleWindowsShownMoreThanOneConsecutiveEntry() }
195         runAndIgnoreAssumptionViolation { taskBarLayerIsVisibleAtStartAndEnd() }
196         runAndIgnoreAssumptionViolation { taskBarWindowIsAlwaysVisible() }
197         runAndIgnoreAssumptionViolation { navBarLayerIsVisibleAtStartAndEnd() }
198         runAndIgnoreAssumptionViolation { navBarWindowIsAlwaysVisible() }
199         runAndIgnoreAssumptionViolation { navBarWindowIsVisibleAtStartAndEnd() }
200     }
201 
202     protected fun runAndIgnoreAssumptionViolation(predicate: () -> Unit) {
203         try {
204             predicate()
205         } catch (e: AssumptionViolatedException) {
206             Log.e(logTag, "Assumption violation on CUJ complete", e)
207         }
208     }
209 }
210