xref: /aosp_15_r20/platform_testing/libraries/flicker/src/android/tools/flicker/legacy/runner/TransitionRunner.kt (revision dd0948b35e70be4c0246aabd6c72554a5eb8b22a)
1 /*
<lambda>null2  * 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 android.tools.flicker.legacy.runner
18 
19 import android.app.Instrumentation
20 import android.platform.test.rule.NavigationModeRule
21 import android.platform.test.rule.PressHomeRule
22 import android.platform.test.rule.UnlockScreenRule
23 import android.tools.Scenario
24 import android.tools.device.apphelpers.MessagingAppHelper
25 import android.tools.flicker.legacy.FlickerTestData
26 import android.tools.flicker.rules.ArtifactSaverRule
27 import android.tools.flicker.rules.ChangeDisplayOrientationRule
28 import android.tools.flicker.rules.LaunchAppRule
29 import android.tools.flicker.rules.RemoveAllTasksButHomeRule
30 import android.tools.rules.StopAllTracesRule
31 import android.tools.traces.io.IResultData
32 import android.tools.traces.io.ResultWriter
33 import android.tools.withTracing
34 import org.junit.rules.RuleChain
35 import org.junit.runner.Description
36 
37 /**
38  * Transition runner that executes a default device setup (based on [scenario]) as well as the
39  * flicker setup/transition/teardown
40  */
41 class TransitionRunner(
42     private val scenario: Scenario,
43     private val instrumentation: Instrumentation,
44     private val resultWriter: ResultWriter = android.tools.flicker.datastore.CachedResultWriter(),
45 ) {
46     /** Executes [flicker] transition and returns the result */
47     fun execute(flicker: FlickerTestData, description: Description?): IResultData {
48         return withTracing("TransitionRunner:execute") {
49             resultWriter.forScenario(scenario).withOutputDir(flicker.outputDir)
50 
51             val ruleChain = buildTestRuleChain(flicker)
52             try {
53                 ruleChain.apply(null, description).evaluate()
54                 resultWriter.setRunComplete()
55             } catch (e: Throwable) {
56                 resultWriter.setRunFailed(e)
57             }
58             resultWriter.write()
59         }
60     }
61 
62     /**
63      * Create the default flicker test setup rules. In order:
64      * - unlock device
65      * - change orientation
66      * - change navigation mode
67      * - launch an app
68      * - remove all apps
69      * - go home
70      *
71      * (b/186740751) An app should be launched because, after changing the navigation mode, the
72      * first app launch is handled as a screen size change (similar to a rotation), this causes
73      * different problems during testing (e.g. IME now shown on app launch)
74      */
75     private fun buildTestRuleChain(flicker: FlickerTestData): RuleChain {
76         val errorRule = ArtifactSaverRule()
77 
78         val rules =
79             listOf(
80                 StopAllTracesRule(),
81                 UnlockScreenRule(),
82                 NavigationModeRule(scenario.navBarMode.value, false),
83                 LaunchAppRule(MessagingAppHelper(instrumentation), clearCacheAfterParsing = false),
84                 RemoveAllTasksButHomeRule(),
85                 ChangeDisplayOrientationRule(
86                     scenario.startRotation,
87                     resetOrientationAfterTest = false,
88                     clearCacheAfterParsing = false,
89                 ),
90                 PressHomeRule(),
91                 TraceMonitorRule(
92                     flicker.traceMonitors,
93                     scenario,
94                     flicker.wmHelper,
95                     resultWriter,
96                     instrumentation,
97                 ),
98                 *flicker.rules.toTypedArray(),
99                 SetupTeardownRule(flicker, resultWriter, scenario, instrumentation),
100                 TransitionExecutionRule(flicker, resultWriter, scenario, instrumentation),
101             )
102 
103         return rules.foldIndexed(RuleChain.outerRule(errorRule)) { index, chain, rule ->
104             chain.around(rule).let {
105                 if (index != rules.lastIndex) {
106                     it.around(errorRule)
107                 } else {
108                     it
109                 }
110             }
111         }
112     }
113 }
114