[gold] /json/v2/search RPC: Exclude digests with optional key disallow_triaging=true from BulkTriageDeltaInfos.
For CLs, this change adds the overhead of looking up the optional keys for each extendedBulkTriageDeltaInfo. I don't expect this to add significant latency to the RPC because it uses the options cache[1], and because the query for cache misses should be fast.
For the primary branch, we have the additional step of fetching the optionIDs for each digest. This is done via a single query against the TraceValues table (inspired in [2]). I expect this query to be pretty fast because the WHERE clause leverages the table's index.
[1] https://skia.googlesource.com/buildbot/+/264f3ee077677f5eddf47808a3f33987322f05a6/golden/go/search/search.go#1627
[2] https://skia.googlesource.com/buildbot/+/264f3ee077677f5eddf47808a3f33987322f05a6/golden/go/search/search.go#1818
Bug: skia:14033
Change-Id: I55765b64308e826b949e87e06ecc9b5fc3297d42
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/658056
Commit-Queue: Leandro Lovisolo <lovisolo@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/golden/go/search/search.go b/golden/go/search/search.go
index 265b291..6602261 100644
--- a/golden/go/search/search.go
+++ b/golden/go/search/search.go
@@ -743,15 +743,20 @@
}
}
- bulkTriageDeltaInfos := make([]frontend.BulkTriageDeltaInfo, len(extendedBulkTriageDeltaInfos))
- for i, triageDeltaInfo := range extendedBulkTriageDeltaInfos {
- bulkTriageDeltaInfos[i] = triageDeltaInfo.BulkTriageDeltaInfo
+ // Populate the optionsIDs fields of each extendedBulkTriageDeltaInfo.
+ if err := s.populateExtendedBulkTriageDeltaInfosOptionsIDs(ctx, extendedBulkTriageDeltaInfos); err != nil {
+ return nil, skerr.Wrap(err)
+ }
+
+ bulkTriageDeltaInfos, err := s.prepareExtendedBulkTriageDeltaInfosForFrontend(ctx, extendedBulkTriageDeltaInfos)
+ if err != nil {
+ return nil, skerr.Wrap(err)
}
return &frontend.SearchResponse{
Results: results,
Offset: q.Offset,
- Size: len(bulkTriageDeltaInfos),
+ Size: len(extendedBulkTriageDeltaInfos),
BulkTriageDeltaInfos: bulkTriageDeltaInfos,
Commits: commits,
}, nil
@@ -1153,8 +1158,10 @@
type extendedBulkTriageDeltaInfo struct {
frontend.BulkTriageDeltaInfo
+ traceIDs []schema.TraceID
groupingID schema.GroupingID
digest schema.DigestBytes
+ optionsIDs []schema.OptionsID // Will be set for CL data only.
}
// getClosestDiffs returns information about the closest triaged digests for each result in the
@@ -1266,8 +1273,10 @@
Grouping: grouping,
Digest: types.Digest(hex.EncodeToString(s2.leftDigest)),
},
+ traceIDs: s2.traceIDs,
groupingID: s2.groupingID,
digest: s2.leftDigest,
+ optionsIDs: s2.optionsIDs,
}
if s2.closestDigest != nil {
// Apply RGBA Filter here - if the closest digest isn't within range, we remove it.
@@ -2110,6 +2119,78 @@
return nil
}
+type traceDigestKey struct {
+ traceID schema.MD5Hash
+ digest schema.MD5Hash
+}
+
+// populateExtendedBulkTriageDeltaInfosOptionsIDs populates the optionsIDs field of the given
+// extendedBulkTriageDeltaInfos.
+func (s *Impl) populateExtendedBulkTriageDeltaInfosOptionsIDs(ctx context.Context, triageDeltaInfos []extendedBulkTriageDeltaInfo) error {
+ // Map triageDeltaInfos by trace ID and digest for faster querying, and gather all trace IDs.
+ var allTraceIDs []schema.TraceID
+ triageDeltaInfosByTraceAndDigest := map[traceDigestKey]*extendedBulkTriageDeltaInfo{}
+ for i := range triageDeltaInfos {
+ allTraceIDs = append(allTraceIDs, triageDeltaInfos[i].traceIDs...)
+ for _, traceID := range triageDeltaInfos[i].traceIDs {
+ key := traceDigestKey{
+ traceID: sql.AsMD5Hash(traceID),
+ digest: sql.AsMD5Hash(triageDeltaInfos[i].digest),
+ }
+ triageDeltaInfosByTraceAndDigest[key] = &triageDeltaInfos[i]
+ }
+ }
+
+ const statement = `SELECT trace_id, digest, options_id FROM TraceValues
+ WHERE trace_id = ANY($1) AND commit_id >= $2`
+ rows, err := s.db.Query(ctx, statement, allTraceIDs, getFirstCommitID(ctx))
+ if err != nil {
+ return skerr.Wrap(err)
+ }
+ defer rows.Close()
+
+ var traceID schema.TraceID
+ var digest schema.DigestBytes
+ var optionsID schema.OptionsID
+ for rows.Next() {
+ if err := rows.Scan(&traceID, &digest, &optionsID); err != nil {
+ return skerr.Wrap(err)
+ }
+ key := traceDigestKey{
+ traceID: sql.AsMD5Hash(traceID),
+ digest: sql.AsMD5Hash(digest),
+ }
+ if triageDeltaInfo, ok := triageDeltaInfosByTraceAndDigest[key]; ok {
+ triageDeltaInfo.optionsIDs = append(triageDeltaInfo.optionsIDs, optionsID)
+ }
+ }
+ return nil
+}
+
+// prepareExtendedBulkTriageDeltaInfosForFrontend turns extendedBulkTriageDeltaInfo structs into
+// frontend.BulkTriageDeltaInfo structs, and filters out those with disallow_triaging=true.
+func (s *Impl) prepareExtendedBulkTriageDeltaInfosForFrontend(ctx context.Context, extendedBulkTriageDeltaInfos []extendedBulkTriageDeltaInfo) ([]frontend.BulkTriageDeltaInfo, error) {
+ // The frontend expects a non-null array.
+ bulkTriageDeltaInfos := []frontend.BulkTriageDeltaInfo{}
+ for _, triageDeltaInfo := range extendedBulkTriageDeltaInfos {
+ disallowTriaging := false
+ for _, optionsID := range triageDeltaInfo.optionsIDs {
+ options, err := s.expandOptionsToParams(ctx, optionsID)
+ if err != nil {
+ return nil, skerr.Wrap(err)
+ }
+ if options["disallow_triaging"] == "true" {
+ disallowTriaging = true
+ break
+ }
+ }
+ if !disallowTriaging {
+ bulkTriageDeltaInfos = append(bulkTriageDeltaInfos, triageDeltaInfo.BulkTriageDeltaInfo)
+ }
+ }
+ return bulkTriageDeltaInfos, nil
+}
+
// expandGrouping returns the params associated with the grouping id. It will use the cache - if
// there is a cache miss, it will look it up, add it to the cache and return it.
func (s *Impl) expandGrouping(ctx context.Context, groupingID schema.MD5Hash) (paramtools.Params, error) {
@@ -2233,15 +2314,15 @@
}
}
- bulkTriageDeltaInfos := make([]frontend.BulkTriageDeltaInfo, len(extendedBulkTriageDeltaInfos))
- for i, triageDeltaInfo := range extendedBulkTriageDeltaInfos {
- bulkTriageDeltaInfos[i] = triageDeltaInfo.BulkTriageDeltaInfo
+ bulkTriageDeltaInfos, err := s.prepareExtendedBulkTriageDeltaInfosForFrontend(ctx, extendedBulkTriageDeltaInfos)
+ if err != nil {
+ return nil, skerr.Wrap(err)
}
return &frontend.SearchResponse{
Results: results,
Offset: getQuery(ctx).Offset,
- Size: len(bulkTriageDeltaInfos),
+ Size: len(extendedBulkTriageDeltaInfos),
BulkTriageDeltaInfos: bulkTriageDeltaInfos,
Commits: commits,
}, nil
diff --git a/golden/go/search/search_test.go b/golden/go/search/search_test.go
index daae996..d1bd220 100644
--- a/golden/go/search/search_test.go
+++ b/golden/go/search/search_test.go
@@ -1311,20 +1311,12 @@
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
},
- Digest: dks.DigestB01Pos,
- LabelBefore: expectations.Positive,
- ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
- InCurrentSearchResultsPage: true,
- }, {
- Grouping: paramtools.Params{
- types.CorpusField: dks.CornersCorpus,
- types.PrimaryKeyField: dks.TriangleTest,
- },
Digest: dks.DigestB02Pos,
LabelBefore: expectations.Positive,
ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
InCurrentSearchResultsPage: false,
},
+ // dks.DigestB01Pos is excluded because it has optional key disallow_triaging=true.
},
}, res)
}
@@ -3206,6 +3198,384 @@
}, res)
}
+func TestSearch_DisallowTriagingOnPrimaryBranch_DigestExcludedFromBulkTriageInfos(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ db := useKitchenSinkData(ctx, t)
+
+ s := New(db, 100)
+ require.NoError(t, s.StartCacheProcess(ctx, time.Minute, 100))
+ res, err := s.Search(ctx, &query.Search{
+ IncludePositiveDigests: true,
+ IncludeNegativeDigests: true,
+ IncludeUntriagedDigests: true,
+ IncludeIgnoredTraces: true,
+ Sort: query.SortDescending,
+ TraceValues: paramtools.ParamSet{
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.OSKey: []string{dks.AndroidOS},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ },
+ RGBAMinFilter: 0,
+ RGBAMaxFilter: 255,
+ })
+ require.NoError(t, err)
+
+ assert.Equal(t, &frontend.SearchResponse{
+ Results: []*frontend.SearchResult{{
+ Digest: dks.DigestA09Neg,
+ Test: dks.SquareTest,
+ Status: expectations.Negative,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.SquareTest},
+ "ext": []string{"png"},
+ },
+ TriageHistory: []frontend.TriageHistory{
+ {
+ User: dks.UserFour,
+ TS: time.Date(2020, time.December, 11, 13, 0, 0, 0, time.UTC),
+ },
+ },
+ TraceGroup: frontend.TraceGroup{
+ Traces: []frontend.Trace{{
+ ID: "0e87221433a6de545e32d846fd7c3e6c",
+ DigestIndices: []int{-1, -1, -1, -1, -1, -1, 0, 0, 1, 0},
+ Params: paramtools.Params{
+ dks.ColorModeKey: dks.RGBColorMode,
+ types.CorpusField: dks.CornersCorpus,
+ dks.DeviceKey: dks.TaimenDevice,
+ dks.OSKey: dks.AndroidOS,
+ types.PrimaryKeyField: dks.SquareTest,
+ "ext": "png",
+ },
+ }},
+ Digests: []frontend.DigestStatus{
+ {Digest: dks.DigestA09Neg, Status: expectations.Negative},
+ {Digest: dks.DigestA01Pos, Status: expectations.Positive},
+ },
+ TotalDigests: 2,
+ },
+ RefDiffs: map[frontend.RefClosest]*frontend.SRDiffDigest{
+ frontend.PositiveRef: {
+ CombinedMetric: 10, QueryMetric: 10, PixelDiffPercent: 100, NumDiffPixels: 64,
+ MaxRGBADiffs: [4]int{255, 255, 255, 255},
+ DimDiffer: false,
+ Digest: dks.DigestA01Pos,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.QuadroDevice, dks.IPadDevice, dks.IPhoneDevice, dks.TaimenDevice, dks.WalleyeDevice},
+ dks.OSKey: []string{dks.AndroidOS, dks.Windows10dot2OS, dks.Windows10dot3OS, dks.IOS},
+ types.PrimaryKeyField: []string{dks.SquareTest},
+ "ext": []string{"png"},
+ "image_matching_algorithm": []string{"fuzzy"},
+ "fuzzy_max_different_pixels": []string{"2"},
+ },
+ },
+ frontend.NegativeRef: nil,
+ },
+ ClosestRef: frontend.PositiveRef,
+ }, {
+ Digest: dks.DigestB01Pos,
+ Test: dks.TriangleTest,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ "image_matching_algorithm": []string{"positive_if_only_image"},
+ "disallow_triaging": []string{"true"},
+ },
+ TriageHistory: []frontend.TriageHistory{
+ {
+ User: dks.UserOne,
+ TS: time.Date(2020, time.June, 7, 8, 9, 43, 0, time.UTC),
+ },
+ },
+ TraceGroup: frontend.TraceGroup{
+ Traces: []frontend.Trace{{
+ ID: "1a16cbc8805378f0a6ef654a035d86c4",
+ DigestIndices: []int{-1, -1, -1, -1, -1, -1, 0, 0, 0, 0},
+ Params: paramtools.Params{
+ dks.ColorModeKey: dks.RGBColorMode,
+ types.CorpusField: dks.CornersCorpus,
+ dks.DeviceKey: dks.TaimenDevice,
+ dks.OSKey: dks.AndroidOS,
+ types.PrimaryKeyField: dks.TriangleTest,
+ "ext": "png",
+ "image_matching_algorithm": "positive_if_only_image",
+ "disallow_triaging": "true",
+ },
+ }},
+ Digests: []frontend.DigestStatus{
+ {Digest: dks.DigestB01Pos, Status: expectations.Positive},
+ },
+ TotalDigests: 1,
+ },
+ RefDiffs: map[frontend.RefClosest]*frontend.SRDiffDigest{
+ frontend.PositiveRef: {
+ CombinedMetric: 1.9362538, QueryMetric: 1.9362538, PixelDiffPercent: 43.75, NumDiffPixels: 28,
+ MaxRGBADiffs: [4]int{11, 5, 42, 0},
+ DimDiffer: false,
+ Digest: dks.DigestB02Pos,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.GreyColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.QuadroDevice, dks.IPadDevice, dks.IPhoneDevice, dks.WalleyeDevice},
+ dks.OSKey: []string{dks.AndroidOS, dks.Windows10dot2OS, dks.Windows10dot3OS, dks.IOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ },
+ },
+ frontend.NegativeRef: {
+ CombinedMetric: 2.9445405, QueryMetric: 2.9445405, PixelDiffPercent: 10.9375, NumDiffPixels: 7,
+ MaxRGBADiffs: [4]int{250, 244, 197, 51},
+ DimDiffer: false,
+ Digest: dks.DigestB03Neg,
+ Status: expectations.Negative,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.IPadDevice, dks.IPhoneDevice},
+ dks.OSKey: []string{dks.IOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ },
+ },
+ },
+ ClosestRef: frontend.PositiveRef,
+ }, {
+ Digest: dks.DigestA01Pos,
+ Test: dks.SquareTest,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.SquareTest},
+ "ext": []string{"png"},
+ },
+ TriageHistory: []frontend.TriageHistory{
+ {
+ User: dks.UserOne,
+ TS: time.Date(2020, time.June, 7, 8, 23, 8, 0, time.UTC),
+ },
+ },
+ TraceGroup: frontend.TraceGroup{
+ Traces: []frontend.Trace{{
+ ID: "0e87221433a6de545e32d846fd7c3e6c",
+ DigestIndices: []int{-1, -1, -1, -1, -1, -1, 1, 1, 0, 1},
+ Params: paramtools.Params{
+ dks.ColorModeKey: dks.RGBColorMode,
+ types.CorpusField: dks.CornersCorpus,
+ dks.DeviceKey: dks.TaimenDevice,
+ dks.OSKey: dks.AndroidOS,
+ types.PrimaryKeyField: dks.SquareTest,
+ "ext": "png",
+ },
+ }},
+ Digests: []frontend.DigestStatus{
+ {Digest: dks.DigestA01Pos, Status: expectations.Positive},
+ {Digest: dks.DigestA09Neg, Status: expectations.Negative},
+ },
+ TotalDigests: 2,
+ },
+ RefDiffs: map[frontend.RefClosest]*frontend.SRDiffDigest{
+ frontend.PositiveRef: {
+ CombinedMetric: 0.15655607, QueryMetric: 0.15655607, PixelDiffPercent: 3.125, NumDiffPixels: 2,
+ MaxRGBADiffs: [4]int{4, 0, 0, 0},
+ DimDiffer: false,
+ Digest: dks.DigestA08Pos,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.WalleyeDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.SquareTest},
+ "ext": []string{"png"},
+ "image_matching_algorithm": []string{"fuzzy"},
+ "fuzzy_max_different_pixels": []string{"2"},
+ },
+ },
+ frontend.NegativeRef: {
+ CombinedMetric: 10, QueryMetric: 10, PixelDiffPercent: 100, NumDiffPixels: 64,
+ MaxRGBADiffs: [4]int{255, 255, 255, 255},
+ DimDiffer: false,
+ Digest: dks.DigestA09Neg,
+ Status: expectations.Negative,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.SquareTest},
+ "ext": []string{"png"},
+ },
+ },
+ },
+ ClosestRef: frontend.PositiveRef,
+ }},
+ Offset: 0,
+ Size: 3,
+ Commits: kitchenSinkCommits,
+ BulkTriageDeltaInfos: []frontend.BulkTriageDeltaInfo{
+ {
+ Grouping: paramtools.Params{
+ "name": "square",
+ "source_type": "corners",
+ },
+ Digest: dks.DigestA01Pos,
+ LabelBefore: expectations.Positive,
+ ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
+ InCurrentSearchResultsPage: true,
+ }, {
+ Grouping: paramtools.Params{
+ "name": "square",
+ "source_type": "corners",
+ },
+ Digest: dks.DigestA09Neg,
+ LabelBefore: expectations.Negative,
+ ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
+ InCurrentSearchResultsPage: true,
+ },
+ // dks.DigestB01Pos is excluded because it has optional key disallow_triaging=true.
+ },
+ }, res)
+}
+
+func TestSearch_DisallowTriagingOnCL_DigestExcludedFromBulkTriageInfos(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ db := useKitchenSinkData(ctx, t)
+
+ s := New(db, 100)
+ s.SetReviewSystemTemplates(map[string]string{
+ dks.GerritCRS: "http://example.com/public/%s",
+ dks.GerritInternalCRS: "http://example.com/internal/%s",
+ })
+ require.NoError(t, s.StartCacheProcess(ctx, time.Minute, 100))
+ res, err := s.Search(ctx, &query.Search{
+ IncludePositiveDigests: true,
+ IncludeNegativeDigests: true,
+ IncludeUntriagedDigests: true,
+ Sort: query.SortDescending,
+ IncludeIgnoredTraces: false,
+ TraceValues: paramtools.ParamSet{
+ types.CorpusField: []string{dks.CornersCorpus},
+ },
+ RGBAMinFilter: 0,
+ RGBAMaxFilter: 255,
+ ChangelistID: dks.ChangelistIDWithDisallowTriagingTest,
+ CodeReviewSystemID: dks.GerritCRS,
+ Patchsets: []int64{1},
+ IncludeDigestsProducedOnMaster: false,
+ })
+ require.NoError(t, err)
+ clCommits := append([]frontend.Commit{}, kitchenSinkCommits...)
+ clCommits = append(clCommits, frontend.Commit{
+ CommitTime: time.Date(2020, time.December, 12, 16, 0, 0, 0, time.UTC).Unix(),
+ Hash: dks.ChangelistIDWithDisallowTriagingTest,
+ Author: dks.UserOne,
+ Subject: "add test with disallow triaging",
+ ChangelistURL: "http://example.com/public/CLdisallowtriaging",
+ })
+
+ assert.Equal(t, &frontend.SearchResponse{
+ Results: []*frontend.SearchResult{{
+ Digest: dks.DigestB05Pos_CL,
+ Test: dks.TriangleTest,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.GreyColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.TaimenDevice},
+ dks.OSKey: []string{dks.AndroidOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ "disallow_triaging": []string{"true"},
+ "image_matching_algorithm": []string{"positive_if_only_image"},
+ },
+ TriageHistory: []frontend.TriageHistory{
+ {
+ User: dks.UserOne,
+ TS: time.Date(2020, time.December, 12, 17, 0, 0, 0, time.UTC),
+ },
+ },
+ TraceGroup: frontend.TraceGroup{
+ Traces: []frontend.Trace{{
+ ID: "668120894a9cfd4d028dbed05c245838",
+ DigestIndices: []int{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0},
+ Params: paramtools.Params{
+ dks.ColorModeKey: dks.GreyColorMode,
+ types.CorpusField: dks.CornersCorpus,
+ dks.DeviceKey: dks.TaimenDevice,
+ dks.OSKey: dks.AndroidOS,
+ types.PrimaryKeyField: dks.TriangleTest,
+ "ext": "png",
+ "disallow_triaging": "true",
+ "image_matching_algorithm": "positive_if_only_image",
+ },
+ }},
+ Digests: []frontend.DigestStatus{
+ {Digest: dks.DigestB05Pos_CL, Status: expectations.Positive},
+ },
+ TotalDigests: 1,
+ },
+ RefDiffs: map[frontend.RefClosest]*frontend.SRDiffDigest{
+ frontend.PositiveRef: {
+ CombinedMetric: 0.73570776, QueryMetric: 0.73570776, PixelDiffPercent: 9.375, NumDiffPixels: 6,
+ MaxRGBADiffs: [4]int{17, 17, 17, 0},
+ DimDiffer: false,
+ Digest: dks.DigestB02Pos,
+ Status: expectations.Positive,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.GreyColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.QuadroDevice, dks.IPadDevice, dks.IPhoneDevice, dks.WalleyeDevice},
+ dks.OSKey: []string{dks.AndroidOS, dks.Windows10dot2OS, dks.Windows10dot3OS, dks.IOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ },
+ },
+ frontend.NegativeRef: {
+ CombinedMetric: 6.2521544, QueryMetric: 6.2521544, PixelDiffPercent: 53.125, NumDiffPixels: 34,
+ MaxRGBADiffs: [4]int{233, 227, 180, 51},
+ DimDiffer: false,
+ Digest: dks.DigestB03Neg,
+ Status: expectations.Negative,
+ ParamSet: paramtools.ParamSet{
+ dks.ColorModeKey: []string{dks.RGBColorMode},
+ types.CorpusField: []string{dks.CornersCorpus},
+ dks.DeviceKey: []string{dks.IPadDevice, dks.IPhoneDevice},
+ dks.OSKey: []string{dks.IOS},
+ types.PrimaryKeyField: []string{dks.TriangleTest},
+ "ext": []string{"png"},
+ },
+ },
+ },
+ ClosestRef: frontend.PositiveRef,
+ }},
+ Offset: 0,
+ Size: 1,
+ Commits: clCommits,
+ BulkTriageDeltaInfos: []frontend.BulkTriageDeltaInfo{
+ // dks.DigestB05Pos_CL is excluded because it has optional key disallow_triaging=true.
+ },
+ }, res)
+}
+
func TestSearch_CLAndPatchsetWithMultipleDatapointsOnSameTrace_ReturnsAllDatapoints(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
@@ -3791,16 +4161,8 @@
LabelBefore: expectations.Positive,
ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
InCurrentSearchResultsPage: true,
- }, {
- Grouping: paramtools.Params{
- types.CorpusField: dks.CornersCorpus,
- types.PrimaryKeyField: dks.TriangleTest,
- },
- Digest: dks.DigestB01Pos,
- LabelBefore: expectations.Untriaged,
- ClosestDiffLabel: frontend.ClosestDiffLabelPositive,
- InCurrentSearchResultsPage: true,
},
+ // dks.DigestB01Pos is excluded because it has optional key disallow_triaging=true.
},
}, res)
}