Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Unified Diff: go/src/infra/appengine/test-results/model/aggregate_result.go

Issue 2234353002: test-results: package model: Add full_result.go and tests (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Improve coverage Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: go/src/infra/appengine/test-results/model/aggregate_result.go
diff --git a/go/src/infra/appengine/test-results/model/aggregate_result.go b/go/src/infra/appengine/test-results/model/aggregate_result.go
index 8888733a27e2414c8d405cf72456456d7ae2eaee..4eccfaaac90859bcd90f08e81e1efd23eb2bf82d 100644
--- a/go/src/infra/appengine/test-results/model/aggregate_result.go
+++ b/go/src/infra/appengine/test-results/model/aggregate_result.go
@@ -15,24 +15,26 @@ import (
// and "results-small.json" files are using.
const ResultsVersion = 4
-var _ TestNode = (AggregateTest)(nil)
-var _ TestNode = (*AggregateTestLeaf)(nil)
-
-// CleanTestResultsJSON returns the result of removing a known prefix
-// and suffix from the contents in r. If the prefix or suffix do not exist,
-// the returned io.Reader has the same contents as r.
-func CleanTestResultsJSON(r io.Reader) (io.Reader, error) {
- pre := []byte("ADD_RESULTS(")
- suf := []byte(");")
+var (
+ // CleanPrefix is the prefix that CleanJSON removes.
+ CleanPrefix = []byte("ADD_RESULTS(")
+ // CleanSuffix is the suffix that CleanJSON removes.
+ CleanSuffix = []byte(");")
+)
+// CleanJSON returns the result of removing CleanPrefix
+// and CleanSuffix from the contents in r. If either
+// CleanPrefix or CleanSuffix does not exist, the returned
+// io.Reader has the same contents as r.
+func CleanJSON(r io.Reader) (io.Reader, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
- if bytes.HasPrefix(b, pre) && bytes.HasSuffix(b, suf) {
- result := bytes.TrimPrefix(b, pre)
- result = bytes.TrimSuffix(result, suf)
+ if bytes.HasPrefix(b, CleanPrefix) && bytes.HasSuffix(b, CleanSuffix) {
+ result := bytes.TrimPrefix(b, CleanPrefix)
+ result = bytes.TrimSuffix(result, CleanSuffix)
return bytes.NewReader(result), nil
}
@@ -47,14 +49,17 @@ type AggregateResult struct {
*BuilderInfo
}
-// BuilderInfo represents aggregate information about a builder.
+// BuilderInfo represents aggregate information for a builder.
type BuilderInfo struct {
// SecondsEpoch is the start time of tests expressed in seconds from
// the Unix epoch.
SecondsEpoch []int64 `json:"secondsSinceEpoch"`
- BlinkRevs []number `json:"blinkRevision"`
- BuildNumbers []number `json:"buildNumbers"`
+ // BlinkRevs is list of Blink revisions.
+ BlinkRevs []Number `json:"blinkRevision"`
+
+ // BuildNumbers is list of build numbers.
+ BuildNumbers []Number `json:"buildNumbers"`
// ChromeRevs is a list of Chrome/Chromium revisions.
// The elements are strings because they can either be revision
@@ -81,6 +86,7 @@ type BuilderInfo struct {
FixableCounts []map[string]int `json:"fixableCounts,omitempty"`
}
+// MarshalJSON marshal ag into JSON.
func (ag *AggregateResult) MarshalJSON() ([]byte, error) {
v, err := json.Marshal(ag.Version)
if err != nil {
@@ -92,7 +98,7 @@ func (ag *AggregateResult) MarshalJSON() ([]byte, error) {
// If FailuresByType exists, do not include FixableCounts
// because it is deprecated.
- if ag.FailuresByType != nil {
+ if info.FailuresByType != nil {
info.FixableCounts = nil
}
@@ -133,7 +139,7 @@ func (ag *AggregateResult) UnmarshalJSON(data []byte) error {
raw, ok := m[ag.Builder]
if !ok {
- return fmt.Errorf("model: missing builder: %s", ag.Builder)
+ return fmt.Errorf("model: missing builder %q", ag.Builder)
}
var info *BuilderInfo
@@ -170,41 +176,23 @@ type fieldError struct {
Value interface{} // Invalid value in the field that caused error.
}
-func (f fieldError) Error() string {
- return fmt.Sprintf("model: field %s has invalid value: %v", f.Name, f.Value)
+func (f *fieldError) Error() string {
+ return fmt.Sprintf("model: field %q has invalid value: %v", f.Name, f.Value)
}
func (ag *AggregateResult) checkFields() error {
if ag.Version > ResultsVersion {
- return fieldError{"Version", ag.Version}
+ return &fieldError{"Version", ag.Version}
}
if ag.BuilderInfo == nil {
- return fieldError{"BuilderInfo", ag.BuilderInfo}
+ return &fieldError{"BuilderInfo", ag.BuilderInfo}
}
return nil
}
func (info *BuilderInfo) checkFields() error {
- if info.SecondsEpoch == nil {
- return fieldError{"SecondsEpoch", info.SecondsEpoch}
- }
- if info.BlinkRevs == nil {
- return fieldError{"BlinkRevs", info.BlinkRevs}
- }
if info.BuildNumbers == nil {
- return fieldError{"BuildNumbers", info.BuildNumbers}
- }
- if info.ChromeRevs == nil {
- return fieldError{"ChromeRevs", info.ChromeRevs}
- }
- if info.Tests == nil {
- return fieldError{"Tests", info.Tests}
- }
- if info.FailureMap == nil {
- return fieldError{"FailureMap", info.FailureMap}
- }
- if info.FailuresByType == nil && info.FixableCounts == nil {
- return fieldError{"FailuresByType", info.FailuresByType}
+ return &fieldError{"BuildNumbers", info.BuildNumbers}
}
return nil
}
@@ -226,7 +214,7 @@ func (info *BuilderInfo) computeFailuresByType() error {
for short, count := range fc {
long, ok := FailureLongNames[short]
if !ok {
- return fmt.Errorf("model: unknown key: %s", short)
+ return fmt.Errorf("model: unknown key %q", short)
}
res[long] = append(res[long], count)
}
@@ -237,38 +225,40 @@ func (info *BuilderInfo) computeFailuresByType() error {
}
// AggregateTest represents Tests in a AggregateResult.
-type AggregateTest map[string]TestNode
-
-func (at AggregateTest) Walk(fn func(key string, node TestNode) error) {
- for k, v := range at {
- if leaf, ok := v.(*AggregateTestLeaf); ok {
- if err := fn(k, leaf); err != nil {
- return
- }
- continue
- }
-
- if child, ok := v.(AggregateTest); ok {
- if err := fn(k, child); err != nil {
- return
- }
- child.Walk(fn)
+type AggregateTest map[string]Node
+
+var _ Node = (AggregateTest)(nil)
+
+func (at AggregateTest) node() {}
+
+// Walk performs a depth-first traversal of the Nodes reachable
+// from the receiver, calling fn each time. The Node in fn
+// is guaranteed to be either AggregateTest or *AggregateTestLeaf.
+// The traversal order may vary across different runs.
+func (at AggregateTest) Walk(fn func(key string, node Node)) {
+ for key, node := range at {
+ switch val := node.(type) {
+ case *AggregateTestLeaf:
+ fn(key, val)
+ case AggregateTest:
+ fn(key, val)
+ val.Walk(fn)
}
}
}
+// WalkLeaves is similar to Walk but only calls fn for
+// *AggregateTestLeaf.
func (at AggregateTest) WalkLeaves(fn func(key string, leaf *AggregateTestLeaf)) {
- at.Walk(func(k string, node TestNode) error {
+ at.Walk(func(key string, node Node) {
if leaf, ok := node.(*AggregateTestLeaf); ok {
- fn(k, leaf)
+ fn(key, leaf)
}
- return nil
})
}
-func (at AggregateTest) Children() map[string]TestNode { return at }
-func (at AggregateTest) testnode() {}
-
+// ToTestList set the Results and Runtimes fields of all the
+// AggregateTestLeaf under the receiver AggregateTest to nil.
func (at AggregateTest) ToTestList() {
at.WalkLeaves(func(_ string, leaf *AggregateTestLeaf) {
leaf.Results = nil
@@ -276,6 +266,7 @@ func (at AggregateTest) ToTestList() {
})
}
+// MarshalJSON marshals at into JSON.
func (at *AggregateTest) MarshalJSON() ([]byte, error) {
if at == nil {
return json.Marshal(nil)
@@ -295,13 +286,14 @@ func (at *AggregateTest) MarshalJSON() ([]byte, error) {
return json.Marshal(m)
}
+// UnmarshalJSON unmarshals the supplied data into at.
func (at *AggregateTest) UnmarshalJSON(data []byte) error {
var m map[string]interface{}
if err := json.Unmarshal(data, &m); err != nil {
return err
}
if at == nil {
- return errors.New("model: UnmarshalJSON on nil *AggregateTest")
+ return errors.New("model: UnmarshalJSON: nil *AggregateTest")
}
if *at == nil {
*at = AggregateTest{}
@@ -309,7 +301,7 @@ func (at *AggregateTest) UnmarshalJSON(data []byte) error {
return at.constructTree(m)
}
-// constructTree constructs the tree of test nodes from the supplied map.
+// constructTree constructs the tree of Nodes from the supplied map.
func (at *AggregateTest) constructTree(m map[string]interface{}) error {
for k, v := range m {
mm, ok := v.(map[string]interface{})
@@ -374,6 +366,8 @@ type AggregateTestLeaf struct {
Bugs []string
}
+func (l *AggregateTestLeaf) node() {}
+
// aggregateTestLeafAux is used to marshal and unmarshal AggregateTestLeaf.
type aggregateTestLeafAux struct {
Results []ResultSummary `json:"results,omitempty"`
@@ -382,9 +376,7 @@ type aggregateTestLeafAux struct {
Bugs []string `json:"bugs,omitempty"`
}
-func (l *AggregateTestLeaf) Children() map[string]TestNode { return nil }
-func (l *AggregateTestLeaf) testnode() {}
-
+// MarshalJSON marshal l into JSON.
func (l *AggregateTestLeaf) MarshalJSON() ([]byte, error) {
aux := aggregateTestLeafAux{
Results: l.Results,
@@ -397,6 +389,7 @@ func (l *AggregateTestLeaf) MarshalJSON() ([]byte, error) {
return json.Marshal(&aux)
}
+// UnmarshalJSON unmarshal the supplied data into l.
func (l *AggregateTestLeaf) UnmarshalJSON(data []byte) error {
var aux aggregateTestLeafAux
if err := json.Unmarshal(data, &aux); err != nil {
@@ -423,11 +416,14 @@ func (l *AggregateTestLeaf) defaultFields() {
}
}
+// ResultSummary is the type of test failure and count of how many
+// times the running time occured.
type ResultSummary struct {
Count int
Type string
}
+// MarshalJSON marshals rs into JSON.
func (rs *ResultSummary) MarshalJSON() ([]byte, error) {
return json.Marshal([]interface{}{
rs.Count,
@@ -435,34 +431,38 @@ func (rs *ResultSummary) MarshalJSON() ([]byte, error) {
})
}
+// UnmarshalJSON unmarshals the provided data into rs.
func (rs *ResultSummary) UnmarshalJSON(data []byte) error {
var tmp []interface{}
if err := json.Unmarshal(data, &tmp); err != nil {
return err
}
if len(tmp) != 2 {
- return fmt.Errorf("ResultSummary: wrong length: %d, expect: %d", len(tmp), 2)
+ return fmt.Errorf("model: UnmarshalJSON: ResultSummary wrong length: %d, expect: %d", len(tmp), 2)
}
count, ok := tmp[0].(float64)
if !ok {
- return fmt.Errorf("ResultSummary: wrong format: %v", tmp)
+ return fmt.Errorf("model: UnmarshalJSON: ResultSummary wrong type: %v", tmp)
}
rs.Count = int(count)
rs.Type, ok = tmp[1].(string)
if !ok {
- return fmt.Errorf("ResultSummary: wrong format: %v", tmp)
+ return fmt.Errorf("model: UnmarshalJSON: ResultSummary wrong type: %v", tmp)
}
return nil
}
+// RuntimeSummary is the running time of a test and count of how many
+// times the running time occured.
type RuntimeSummary struct {
Count int
Runtime float64
}
+// MarshalJSON marshals rs into JSON.
func (rs *RuntimeSummary) MarshalJSON() ([]byte, error) {
return json.Marshal([]float64{
float64(rs.Count),
@@ -470,13 +470,14 @@ func (rs *RuntimeSummary) MarshalJSON() ([]byte, error) {
})
}
+// UnmarshalJSON unmarshals the provided data into rs.
func (rs *RuntimeSummary) UnmarshalJSON(data []byte) error {
var tmp []float64
if err := json.Unmarshal(data, &tmp); err != nil {
return err
}
if len(tmp) != 2 {
- return fmt.Errorf("RuntimeSummary: wrong length: %d, expect: %d", len(tmp), 2)
+ return fmt.Errorf("model: UnmarshalJSON: RuntimeSummary wrong length: %d, expect: %d", len(tmp), 2)
}
rs.Count = int(tmp[0])

Powered by Google App Engine
This is Rietveld 408576698