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