1 /*
2  * Copyright (C) 2023 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 android.tools.integration
18 
19 import android.app.Instrumentation
20 import android.graphics.Region
21 import android.tools.Timestamps
22 import android.tools.device.apphelpers.MessagingAppHelper
23 import android.tools.flicker.AssertionInvocationGroup
24 import android.tools.flicker.FlickerConfig
25 import android.tools.flicker.ScenarioInstance
26 import android.tools.flicker.annotation.ExpectedScenarios
27 import android.tools.flicker.annotation.FlickerConfigProvider
28 import android.tools.flicker.assertions.FlickerTest
29 import android.tools.flicker.assertors.AssertionTemplate
30 import android.tools.flicker.config.FlickerConfig
31 import android.tools.flicker.config.FlickerConfigEntry
32 import android.tools.flicker.config.FlickerServiceConfig
33 import android.tools.flicker.config.ScenarioId
34 import android.tools.flicker.extractors.ScenarioExtractor
35 import android.tools.flicker.extractors.TraceSlice
36 import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
37 import android.tools.flicker.subject.FlickerSubject
38 import android.tools.flicker.subject.layers.LayersTraceSubject
39 import android.tools.flicker.subject.region.RegionSubject
40 import android.tools.flicker.subject.wm.WindowManagerTraceSubject
41 import android.tools.io.Reader
42 import android.tools.traces.parsers.WindowManagerStateHelper
43 import androidx.test.platform.app.InstrumentationRegistry
44 import com.google.common.truth.Truth
45 import org.junit.After
46 import org.junit.Before
47 import org.junit.Test
48 import org.junit.runner.RunWith
49 
50 @RunWith(FlickerServiceJUnit4ClassRunner::class)
51 class FullTestRun {
52     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
53     private val wmHelper = WindowManagerStateHelper(instrumentation)
54     private val testApp = MessagingAppHelper(instrumentation)
55 
56     @Before
setupnull57     fun setup() {
58         // Nothing to do
59     }
60 
61     @ExpectedScenarios(["ENTIRE_TRACE"])
62     @Test
openAppnull63     fun openApp() {
64         testApp.launchViaIntent(wmHelper)
65     }
66 
67     @After
teardownnull68     fun teardown() {
69         testApp.exit(wmHelper)
70     }
71 
72     companion object {
73         @JvmStatic
74         @FlickerConfigProvider
flickerConfigProvidernull75         fun flickerConfigProvider(): FlickerConfig =
76             FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CUSTOM_CONFIG)
77 
78         val CUSTOM_CONFIG =
79             FlickerConfigEntry(
80                 scenarioId = ScenarioId("MY_CUSTOM_SCENARIO"),
81                 extractor =
82                     object : ScenarioExtractor {
83                         override fun extract(reader: Reader): List<TraceSlice> {
84                             return listOf(TraceSlice(Timestamps.min(), Timestamps.max()))
85                         }
86                     },
87                 assertions =
88                     mapOf(
89                         object : AssertionTemplate("internalWmCheck") {
doEvaluatenull90                             override fun doEvaluate(
91                                 scenarioInstance: ScenarioInstance,
92                                 flicker: FlickerTest
93                             ) {
94                                 var trace: WindowManagerTraceSubject? = null
95                                 var executionCount = 0
96                                 flicker.assertWm {
97                                     executionCount++
98                                     trace = this
99                                     this.isNotEmpty()
100 
101                                     Truth.assertWithMessage("Execution count")
102                                         .that(executionCount)
103                                         .isEqualTo(1)
104                                 }
105                                 flicker.assertWm {
106                                     executionCount++
107                                     val failure: Result<Any> = runCatching { this.isEmpty() }
108                                     if (failure.isSuccess) {
109                                         error("Should have thrown failure")
110                                     }
111 
112                                     Truth.assertWithMessage("Execution count")
113                                         .that(executionCount)
114                                         .isEqualTo(2)
115                                 }
116                                 flicker.assertWmStart {
117                                     executionCount++
118                                     validateState(this, trace?.first())
119                                     validateVisibleRegion(
120                                         this.visibleRegion(),
121                                         trace?.first()?.visibleRegion()
122                                     )
123 
124                                     Truth.assertWithMessage("Execution count")
125                                         .that(executionCount)
126                                         .isEqualTo(3)
127                                 }
128                                 flicker.assertWmEnd {
129                                     executionCount++
130                                     validateState(this, trace?.last())
131                                     validateVisibleRegion(
132                                         this.visibleRegion(),
133                                         trace?.last()?.visibleRegion()
134                                     )
135 
136                                     Truth.assertWithMessage("Execution count")
137                                         .that(executionCount)
138                                         .isEqualTo(4)
139                                 }
140                             }
141                         } to AssertionInvocationGroup.BLOCKING,
142                         object : AssertionTemplate("internalLayersCheck") {
doEvaluatenull143                             override fun doEvaluate(
144                                 scenarioInstance: ScenarioInstance,
145                                 flicker: FlickerTest
146                             ) {
147                                 var trace: LayersTraceSubject? = null
148                                 var executionCount = 0
149                                 flicker.assertLayers {
150                                     executionCount++
151                                     trace = this
152                                     this.isNotEmpty()
153 
154                                     Truth.assertWithMessage("Execution count")
155                                         .that(executionCount)
156                                         .isEqualTo(1)
157                                 }
158                                 flicker.assertLayers {
159                                     executionCount++
160                                     val failure: Result<Any> = runCatching { this.isEmpty() }
161                                     if (failure.isSuccess) {
162                                         error("Should have thrown failure")
163                                     }
164 
165                                     Truth.assertWithMessage("Execution count")
166                                         .that(executionCount)
167                                         .isEqualTo(2)
168                                 }
169                                 flicker.assertLayersStart {
170                                     executionCount++
171                                     validateState(this, trace?.first())
172                                     validateVisibleRegion(
173                                         this.visibleRegion(),
174                                         trace?.first()?.visibleRegion()
175                                     )
176 
177                                     Truth.assertWithMessage("Execution count")
178                                         .that(executionCount)
179                                         .isEqualTo(3)
180                                 }
181                                 flicker.assertLayersEnd {
182                                     executionCount++
183                                     validateState(this, trace?.last())
184                                     validateVisibleRegion(
185                                         this.visibleRegion(),
186                                         trace?.last()?.visibleRegion()
187                                     )
188 
189                                     Truth.assertWithMessage("Execution count")
190                                         .that(executionCount)
191                                         .isEqualTo(4)
192                                 }
193                             }
194                         } to AssertionInvocationGroup.BLOCKING
195                     ),
196                 enabled = true
197             )
198 
validateStatenull199         private fun validateState(actual: FlickerSubject?, expected: FlickerSubject?) {
200             Truth.assertWithMessage("Actual state").that(actual).isNotNull()
201             Truth.assertWithMessage("Expected state").that(expected).isNotNull()
202         }
203 
validateVisibleRegionnull204         private fun validateVisibleRegion(
205             actual: RegionSubject?,
206             expected: RegionSubject?,
207         ) {
208             Truth.assertWithMessage("Actual visible region").that(actual).isNotNull()
209             Truth.assertWithMessage("Expected visible region").that(expected).isNotNull()
210             actual?.coversExactly(expected?.region ?: Region())
211 
212             val failure: Result<Any?> = runCatching {
213                 actual?.isHigher(expected?.region ?: Region())
214             }
215             if (failure.isSuccess) {
216                 error("Should have thrown failure")
217             }
218         }
219     }
220 }
221