in pkg/summarizer/flakiness.go [86:178]
func parseGrid(grid *statepb.Grid, startTime int, endTime int) ([]*common.GridMetrics, map[string][]analyzers.StatusCategory) {
// Get the relevant data for flakiness from each Grid (which represents
// a dashboard tab) as a list of GridMetrics structs
// TODO (itsazhuhere@): consider refactoring/using summary.go's gridMetrics function
// as it does very similar data collection.
// Multiply by 1000 because currently Column.Started is in milliseconds; this is used
// for comparisons later. startTime and endTime will be used in a Timestamp later that
// requires seconds, so we would like to impact that at little as possible.
startTime *= 1000
endTime *= 1000
// We create maps because result.Map returns a map where we can access each result
// through the test name, and at each instance we can increment our types.Result
// using the same key. At the end we can filter out those types.Result that had
// 0 of all counts.
gridMetricsMap := make(map[string]*common.GridMetrics, 0)
gridRows := make(map[string]*statepb.Row)
// For each filtered test, status of non-infra-failure tests
rowStatuses := make(map[string][]analyzers.StatusCategory)
for i, row := range grid.Rows {
gridRows[row.Name] = grid.Rows[i]
gridMetricsMap[row.Name] = common.NewGridMetrics(row.Name)
rowStatuses[row.Name] = []analyzers.StatusCategory{}
}
// result.Map is written in a way that assumes each test/row name is unique
rowResults := result.Map(grid.Rows)
failingColumns := failingColumns(len(grid.Columns), grid.Rows)
for key, f := range rowResults {
if !isValidTestName(key) {
continue
}
rowToMessageIndex := 0
i := -1
for {
nextRowResult, more := f()
if !more {
break
}
i++
if i >= len(grid.Columns) {
break
}
rowResult := result.Coalesce(nextRowResult, result.ShowRunning)
// We still need to increment rowToMessageIndex even if we want to skip counting
// this column.
if !isWithinTimeFrame(grid.Columns[i], startTime, endTime) {
switch rowResult {
case statuspb.TestStatus_NO_RESULT:
// Ignore NO_RESULT (e.g. blank cell)
default:
rowToMessageIndex++
}
continue
}
switch rowResult {
case statuspb.TestStatus_NO_RESULT:
continue
case statuspb.TestStatus_FAIL:
message := gridRows[key].Messages[rowToMessageIndex]
if isInfraFailure(message) {
gridMetricsMap[key].FailedInfraCount++
gridMetricsMap[key].InfraFailures[message]++
} else {
gridMetricsMap[key].Failed++
if !failingColumns[i] {
rowStatuses[key] = append(rowStatuses[key], analyzers.StatusFail)
}
}
case statuspb.TestStatus_PASS:
gridMetricsMap[key].Passed++
rowStatuses[key] = append(rowStatuses[key], analyzers.StatusPass)
case statuspb.TestStatus_FLAKY:
rowStatuses[key] = append(rowStatuses[key], analyzers.StatusFlaky)
getValueOfFlakyMetric(gridMetricsMap[key])
}
rowToMessageIndex++
}
}
gridMetrics := make([]*common.GridMetrics, 0)
for _, metric := range gridMetricsMap {
if metric.Failed > 0 || metric.Passed > 0 || metric.FlakyCount > 0 {
gridMetrics = append(gridMetrics, metric)
}
}
return gridMetrics, rowStatuses
}