| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import {RoutineProperties} from './diagnostics_types.js'; |
| import {ExecutionProgress, ResultStatusItem} from './routine_list_executor.js'; |
| import {getSimpleResult} from './routine_result_entry.js'; |
| import {RoutineResult, RoutineType, StandardRoutineResult} from './system_routine_controller.mojom-webui.js'; |
| |
| function isBlockingRoutine(routineProp: RoutineProperties): boolean { |
| return routineProp.blocking; |
| } |
| |
| function getNonBlockingRoutines(routines: RoutineProperties[]): RoutineType[] { |
| return routines.filter(r => !isBlockingRoutine(r)).map(getRoutine); |
| } |
| |
| function getRoutine(routineProp: RoutineProperties): RoutineType { |
| return routineProp.routine; |
| } |
| |
| /** |
| * @fileoverview |
| * Used to aggregate individual tests into a shared category (Wi-Fi). |
| */ |
| export class RoutineGroup { |
| routineProperties: RoutineProperties[]; |
| private nonBlockingRoutines: Set<RoutineType>; |
| routines: RoutineType[]; |
| groupName: string; |
| progress: ExecutionProgress; |
| failedTest: RoutineType|null = null; |
| inWarningState: boolean = false; |
| constructor(routines: RoutineProperties[], groupName: string) { |
| /** |
| * Store routine properties array for calls to |clone|. |
| */ |
| this.routineProperties = this.routineProperties || routines; |
| this.nonBlockingRoutines = new Set(getNonBlockingRoutines(routines)); |
| this.routines = routines.map(getRoutine); |
| this.groupName = groupName; |
| this.progress = ExecutionProgress.NOT_STARTED; |
| /** |
| * Used to track the first test failure in the group of tests. |
| */ |
| this.failedTest = null; |
| this.inWarningState = false; |
| } |
| |
| /** |
| * Determine overall status of routine group. Report test status as "running" |
| * as long as the current routine is not the last routine in the group. |
| */ |
| setStatus(status: ResultStatusItem): void { |
| if (status.progress !== ExecutionProgress.COMPLETED) { |
| // Prevent 'WARNING' badge from being overwritten by a subsequent routine. |
| this.progress = this.inWarningState ? this.progress : status.progress; |
| return; |
| } |
| |
| const isLastRoutine = this.isLastRoutine(status.routine); |
| if (status.result && this.testFailed(status.result)) { |
| // Prevent 1st failed test from being overwritten. |
| this.failedTest = this.failedTest || status.routine; |
| |
| const isBlocking = !this.nonBlockingRoutines.has(status.routine); |
| this.inWarningState = this.inWarningState || !isBlocking; |
| |
| // We've encountered a blocking failure. |
| if (this.failedTest && isBlocking) { |
| this.progress = ExecutionProgress.COMPLETED; |
| return; |
| } |
| } |
| |
| // Set status to "completed" only when all routines in this group are |
| // finished running. Otherwise, check if we're in the warning state |
| // before setting the progress to running. |
| this.progress = isLastRoutine ? ExecutionProgress.COMPLETED : |
| this.inWarningState ? ExecutionProgress.WARNING : |
| ExecutionProgress.RUNNING; |
| |
| return; |
| } |
| |
| private testFailed(result: RoutineResult): boolean { |
| return getSimpleResult(result) === StandardRoutineResult.kTestFailed; |
| } |
| |
| private isLastRoutine(routine: RoutineType): boolean { |
| return routine === this.routines[this.routines.length - 1]; |
| } |
| |
| /** |
| * Used to add new routines after initialization for this instance is done. |
| * Ex: Routines that are added only when a flag is enabled. |
| * */ |
| addRoutine(routineProps: RoutineProperties): void { |
| this.routines.push(routineProps.routine); |
| if (!isBlockingRoutine(routineProps)) { |
| this.nonBlockingRoutines.add(routineProps.routine); |
| } |
| this.routineProperties = [...this.routineProperties, routineProps]; |
| } |
| |
| /** |
| * Whether we should skip the remaining routines (true when a blocking |
| * routine fails) or not. |
| */ |
| hasBlockingFailure(): boolean { |
| if (!this.failedTest) { |
| return false; |
| } |
| |
| // Skip remaining tests if this is a blocking test failure and we're not |
| // in a warning state. |
| return !this.nonBlockingRoutines.has(this.failedTest) && |
| !this.inWarningState; |
| } |
| |
| /** |
| * Clones properties of RoutineGroup and returns new RoutineGroup |
| */ |
| clone(): RoutineGroup { |
| const clonedRoutineGroup = |
| new RoutineGroup(this.routineProperties, this.groupName); |
| clonedRoutineGroup.progress = this.progress; |
| clonedRoutineGroup.failedTest = this.failedTest; |
| clonedRoutineGroup.inWarningState = this.inWarningState; |
| return clonedRoutineGroup; |
| } |
| } |