blob: be43919fc8ea986222f4c1bb041b4d8395b303ac [file]
/**
* @license
* Copyright 2023 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
import {TagColor} from '@gerritcodereview/typescript-api/checks';
import {Attempt, Build} from './checks-fetcher';
import {FaultAttribute, FaultAttributeProperties} from './failure-analysis';
import {TestVariant} from './resultdb-client';
/**
* assignFaultAttributesToVariants assigns fault attributes to corresponding test variants.
* @param tvsByBuilds mapping of build IDs to test variants
* @param attemptsByBuilder mapping of builder names to build attempts
*/
export function assignFaultAttributesToVariants(
tvsByBuilds: {[key: string]: {variants: TestVariant[]; errorMessage: string}},
attemptsByBuilder: {[key: string]: Attempt[]}
) {
const cqOrchestratorBuilds = attemptsByBuilder['cq-orchestrator']?.map(
(attempt: Attempt) => attempt.build
);
if (!cqOrchestratorBuilds) {
return;
}
const faultAttributeEntries = getFaultAttributeEntries(cqOrchestratorBuilds);
for (const orchBuild of cqOrchestratorBuilds) {
for (const testVariant of tvsByBuilds[orchBuild.id]?.variants ?? []) {
const key = getFaultAttributeEntryKey(
orchBuild.id,
testVariant.variant?.def.build_target,
testVariant.variant?.def.model,
testVariant.testId ?? ''
);
if (!key) {
continue;
}
testVariant.faultAttribute = faultAttributeEntries[key];
}
}
}
/**
* getFaultAttributeEntryKey returns an object key using the provided build ID & test variant properties.
* @param buildId ID of the relevant orch build the test is contained in
* @param buildTarget the build target the test variant was executed on
* @param modelName the model (may be empty) that the test variant was executed on
* @param testName the relevant test name of the test variant (aka test ID)
*/
export function getFaultAttributeEntryKey(
buildId: string,
buildTarget: string,
modelName: string,
testName: string
) {
modelName = modelName ? `-${modelName}` : '';
return `${buildId}-${buildTarget}${modelName}-${testName}`;
}
/**
* getFaultAttributeEntries maps a build ID & fault attribute properties to a particular fault attribute. The build ID & fault attribute properties are combined into a key defined by getFaultAttributeEntryKey
* @param builds list of builds to map fault attributes for
*/
function getFaultAttributeEntries(builds: Build[]) {
// Create map by the getFaultAttributeEntryKey function to an entry
const faultAttributeEntries: {[key: string]: FaultAttributeProperties} = {};
for (const build of builds) {
const faultAttributes =
build.output?.properties?.cq_fault_attributions?.testFailureAttributions;
if (!faultAttributes) {
continue;
}
for (const faultAttributedBuildTarget of faultAttributes) {
const buildTarget = faultAttributedBuildTarget.buildTarget;
const model = faultAttributedBuildTarget.model ?? '';
for (const faultAttribute of faultAttributedBuildTarget.faultAttributes) {
const key = getFaultAttributeEntryKey(
build.id,
buildTarget,
model,
faultAttribute.testName
);
faultAttributeEntries[key] = faultAttribute;
}
}
}
return faultAttributeEntries;
}
/**
* getFaultAttributeTagDisplayName returns the display name for the fault attribute tag
* @param faultAttribute the fault attribute to retrieve a display name for
*/
export function getFaultAttributeTagDisplayName(
faultAttribute: FaultAttributeProperties
) {
if (faultAttribute.likelyFlaky) {
return 'Likely flaky';
}
switch (faultAttribute.snapshotComparisonFaultAttribution) {
case FaultAttribute.MATCHING_FAILURE_FOUND:
return 'Pre-existing identical failure';
case FaultAttribute.DIFFERING_FAILURE_FOUND:
return 'Pre-existing differing failure';
case FaultAttribute.SUCCESS_FOUND:
return 'New failure';
case FaultAttribute.NO_COMPARISON:
default:
return null;
}
}
/**
* getFaultAttributeTagColor returns a tag color for relevant types of fault attributes.
* @param faultAttribute the fault attribute to retrieve a tag color for
*/
export function getFaultAttributeTagColor(
faultAttribute: FaultAttributeProperties
) {
if (faultAttribute.likelyFlaky) {
return TagColor.YELLOW;
}
switch (faultAttribute.snapshotComparisonFaultAttribution) {
case FaultAttribute.DIFFERING_FAILURE_FOUND:
return TagColor.YELLOW;
case FaultAttribute.SUCCESS_FOUND:
return TagColor.PINK;
case FaultAttribute.MATCHING_FAILURE_FOUND:
return TagColor.GRAY;
case FaultAttribute.NO_COMPARISON:
default:
return null;
}
}
/**
* getFaultAttributeTagTooltip returns tooltip text for relevant types of fault attributes.
* @param faultAttribute the fault attribute to retrieve a tooltip for
*/
export function getFaultAttributeTagTooltip(
faultAttribute: FaultAttributeProperties
) {
if (faultAttribute.likelyFlaky) {
return 'This test failure is likely flaky';
}
switch (faultAttribute.snapshotComparisonFaultAttribution) {
case FaultAttribute.MATCHING_FAILURE_FOUND:
return 'This test failure occurred in an earlier snapshot build with an identical failure reason';
case FaultAttribute.DIFFERING_FAILURE_FOUND:
return 'This test failure occurred in an earlier snapshot build with a different failure reason';
case FaultAttribute.SUCCESS_FOUND:
return 'This test failure is not present in ToT and may need some additional debugging';
case FaultAttribute.NO_COMPARISON:
default:
return null;
}
}