Index: go/src/infra/appengine/test-results/model/trim.go |
diff --git a/go/src/infra/appengine/test-results/model/trim.go b/go/src/infra/appengine/test-results/model/trim.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..03bd251e60f99af9b706021bce7917f37868cd1c |
--- /dev/null |
+++ b/go/src/infra/appengine/test-results/model/trim.go |
@@ -0,0 +1,117 @@ |
+package model |
+ |
+import ( |
+ "errors" |
+ "strings" |
+) |
+ |
+const ( |
+ // ResultsSize is the size that "results.json" should be trimmed to. |
+ ResultsSize = 500 |
+ |
+ // ResultsSmallSize is the size that "results_small.json" should |
+ // be trimmed to. |
+ ResultsSmallSize = 100 |
+ |
+ runtimeThresholdNormal float64 = 3 |
+ runtimeThresholdDebug float64 = 9 |
+) |
+ |
+func isDebugBuilder(builder string) bool { |
+ for _, s := range []string{"debug", "dbg"} { |
+ if strings.Contains(strings.ToLower(builder), s) { |
+ return true |
+ } |
+ } |
+ return false |
+} |
+ |
+// Trim trims the leaves of Tests in ar to the specified size. |
+func (ar *AggregateResult) Trim(size int) error { |
+ t := runtimeThresholdNormal |
+ |
+ if isDebugBuilder(ar.Builder) { |
+ t = runtimeThresholdDebug |
+ } |
+ |
+ return ar.Tests.trim(size, t) |
+} |
+ |
+func (at AggregateTest) trim(size int, threshold float64) error { |
+ for k, v := range at { |
+ if leaf, ok := v.(*AggregateTestLeaf); ok { |
+ leaf.trim(size) |
+ if leaf.shouldDelete(threshold) { |
+ delete(at, k) |
+ } |
+ continue |
+ } |
+ |
+ child, ok := v.(AggregateTest) |
+ if !ok { |
+ return errors.New("model: trim: expected AggregateTest") |
+ } |
+ if err := child.trim(size, threshold); err != nil { |
+ return err |
+ } |
+ if len(child) == 0 { |
+ delete(at, k) |
+ } |
+ } |
+ return nil |
+} |
+ |
+func (leaf *AggregateTestLeaf) trim(size int) { |
martiniss
2016/08/12 00:14:24
why is size an int here, but threshold is declared
nishanths
2016/08/12 02:37:40
threshold is a float because it is used to compare
|
+ n := 0 |
+ |
+ for i, r := range leaf.Results { |
+ leaf.Results[i].Count = min(r.Count, size) |
+ n += r.Count |
+ if n >= size { |
+ leaf.Results = leaf.Results[:i+1] |
+ break |
+ } |
+ } |
+ |
+ n = 0 |
+ |
+ for i, r := range leaf.Runtimes { |
+ leaf.Runtimes[i].Count = min(r.Count, size) |
+ n += r.Count |
+ if n >= size { |
+ leaf.Runtimes = leaf.Runtimes[:i+1] |
+ break |
+ } |
+ } |
+} |
+ |
+func min(a, b int) int { |
+ if a < b { |
+ return a |
+ } |
+ return b |
+} |
+ |
+var deletableTypes = map[string]bool{"P": true, "N": true, "Y": true} |
+ |
+func (leaf *AggregateTestLeaf) shouldDelete(threshold float64) bool { |
+ if len(leaf.Expected) == 1 && leaf.Expected[0] != "PASS" { |
+ return false |
+ } |
+ if leaf.Bugs != nil { |
+ return false |
+ } |
+ |
+ for _, r := range leaf.Results { |
+ if !deletableTypes[r.Type] { |
+ return false |
+ } |
+ } |
+ for _, r := range leaf.Runtimes { |
+ if r.Runtime >= threshold { |
+ return false |
+ } |
+ } |
+ |
+ return true |
+} |