• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2021 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 com.android.server.wm.flicker.FlickerRunResult.Companion.RunStatus
20 import com.android.server.wm.flicker.assertions.AssertionData
21 import com.android.server.wm.flicker.assertions.FlickerAssertionError
22 import com.google.common.truth.Truth
23 
24 /**
25  * Result of a flicker run, including transitions, errors and create tags
26  */
27 data class FlickerResult(
28     /**
29      * Result of each transition run
30      */
31     @JvmField val runResults: List<FlickerRunResult> = listOf(),
32     /**
33      * List of test created during the execution
34      */
35     @JvmField val tags: Set<String> = setOf(),
36     /**
37      * Execution errors which happened during the execution of the Flicker test
38      */
39     @JvmField val executionErrors: List<Throwable> = listOf()
40 ) {
41     init {
42         for (result in runResults) {
43             require(result.status != RunStatus.UNDEFINED) {
44                 "Can't create FlickerResult from RunResult ${result.traceName} " +
45                         "(${result.assertionTag}) with UNDEFINED status."
46             }
47         }
48     }
49 
50     /** Successful runs on which we can run assertions */
51     val successfulRuns: List<FlickerRunResult> = runResults.filter { it.isSuccessfulRun }
52     /** Failed runs due to execution errors which we shouldn't run assertions on */
53     private val failedRuns: List<FlickerRunResult> = runResults.filter { it.isFailedRun }
54 
55     val combinedExecutionError = CombinedExecutionError(executionErrors)
56 
57     /**
58      * List of failures during assertion
59      */
60     private val failures: MutableList<FlickerAssertionError> = mutableListOf()
61 
62     /**
63      * Run the assertion on the trace
64      *
65      * @throws AssertionError If the assertion fail or the transition crashed
66      */
67     internal fun checkAssertion(assertion: AssertionData): List<FlickerAssertionError> {
68         Truth.assertWithMessage("Expected to have runResults but none were found")
69                 .that(runResults).isNotEmpty()
70         Truth.assertWithMessage("No transitions were not executed successful")
71                 .that(successfulRuns).isNotEmpty()
72 
73         val filteredRuns = successfulRuns.filter { it.assertionTag == assertion.tag }
74         val currFailures = filteredRuns.mapNotNull { run -> run.checkAssertion(assertion) }
75         failures.addAll(currFailures)
76         return currFailures
77     }
78 
79     /**
80      * Asserts if there have been any execution errors while running the transitions
81      */
82     internal fun checkForExecutionErrors() {
83         if (executionErrors.isNotEmpty()) {
84             if (executionErrors.size == 1) {
85                 throw executionErrors[0]
86             }
87             throw combinedExecutionError
88         }
89     }
90 
91     fun isEmpty(): Boolean = executionErrors.isEmpty() && successfulRuns.isEmpty()
92 
93     fun isNotEmpty(): Boolean = !isEmpty()
94 
95     companion object {
96         class CombinedExecutionError(val errors: List<Throwable>?) : Throwable() {
97             override val message: String? get() {
98                 if (errors == null || errors.isEmpty()) {
99                     return null
100                 }
101                 if (errors.size == 1) {
102                     return errors[0].toString()
103                 }
104                 return "Combined Errors Of\n\t- " +
105                         errors.joinToString("\n\t\tAND\n\t- ") { it.toString() } +
106                         "\n[NOTE: any details below are only for the first error]"
107             }
108 
109             override val cause: Throwable?
110                 get() = errors?.get(0)
111         }
112     }
113 }
114