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