[perf] CABE checks whether completed swarming tasks have failure

CABE tries to load results from swarming tasks with the state COMPLETED.
However, the state can be COMPLETED (FAILURE), and the task will not
have results.

The change here checks the Failure value of the task and load results
only when the task is completed without failures.

Bug: 476120295
Change-Id: I0a80c05d9df709ba7b23cafef4208080bef06cae
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/1142744
Reviewed-by: Farid (Mojtaba) Faridzad <faridzad@google.com>
Reviewed-by: John Chen <zhanliang@google.com>
Commit-Queue: Wenbin Zhang <wenbinzhang@google.com>
diff --git a/cabe/go/analyzer/analyzer.go b/cabe/go/analyzer/analyzer.go
index 675fbbd..ba469f7 100644
--- a/cabe/go/analyzer/analyzer.go
+++ b/cabe/go/analyzer/analyzer.go
@@ -416,6 +416,10 @@
 	return experimentSpec, nil
 }
 
+func isSwarmingTaskCompletedSuccessfully(task *apipb.TaskRequestMetadataResponse) bool {
+	return task.TaskResult.State == apipb.TaskState_COMPLETED && !task.TaskResult.Failure
+}
+
 func (a *Analyzer) extractTaskOutputs(ctx context.Context, processedArms *processedExperimentTasks) error {
 	// This is currently un-sliced. As in, it lumps all runconfigs together. This is fine if you only
 	// have one runconfig (say, you only asked to analyze Mac results).
@@ -429,7 +433,7 @@
 
 		controlDigests := map[int]*apipb.CASReference{}
 		for n, t := range processedArms.control.tasks {
-			if t.taskInfo.TaskResult.State != apipb.TaskState_COMPLETED {
+			if !isSwarmingTaskCompletedSuccessfully(t.taskInfo) {
 				continue
 			}
 			controlDigests[n] = t.taskInfo.TaskResult.CasOutputRoot
@@ -450,7 +454,7 @@
 
 		treatmentDigests := map[int]*apipb.CASReference{}
 		for n, t := range processedArms.treatment.tasks {
-			if t.taskInfo.TaskResult.State != apipb.TaskState_COMPLETED {
+			if !isSwarmingTaskCompletedSuccessfully(t.taskInfo) {
 				continue
 			}
 			treatmentDigests[n] = t.taskInfo.TaskResult.CasOutputRoot
@@ -556,8 +560,8 @@
 			a.diagnostics.excludeSwarmingTask(task, msg)
 		}
 
-		if task.TaskResult.State != apipb.TaskState_COMPLETED {
-			msg := fmt.Sprintf("task result is in state %q, not %q", task.TaskResult.State, taskCompletedState)
+		if !isSwarmingTaskCompletedSuccessfully(task) {
+			msg := fmt.Sprintf("excluding task result is in state: %q, failure: %v", task.TaskResult.State, task.TaskResult.Failure)
 			a.diagnostics.excludeSwarmingTask(task, msg)
 		} else {
 			a.diagnostics.includeSwarmingTask(task)