Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 package model | |
|
martiniss
2016/08/12 00:14:24
I don't see the need for a merge.go file; why don'
nishanths
2016/08/12 02:37:39
As discussed offline, will move the contents of me
nishanths
2016/08/16 01:01:53
Done in patch set 7.
| |
| 2 | |
| 3 import "errors" | |
| 4 | |
| 5 var ( | |
| 6 // ErrBuildNumberConflict is returned when the build numbers | |
| 7 // are the same when merging. | |
| 8 ErrBuildNumberConflict = errors.New("build number conflict") | |
|
martiniss
2016/08/12 00:14:24
It's not obvious to me from reading this file why
nishanths
2016/08/12 02:37:39
Done.
| |
| 9 | |
| 10 // ErrBuilderNameConflict is returned when the builder names | |
| 11 // do not match when merging. | |
| 12 ErrBuilderNameConflict = errors.New("builder name conflict") | |
| 13 ) | |
| 14 | |
| 15 // Merge merges x into ar. After merging, ar's fields may reference the same | |
| 16 // objects referenced by x. | |
| 17 func (ar *AggregateResult) Merge(x *AggregateResult) error { | |
|
martiniss
2016/08/12 00:14:24
nit: "other" is a bit more descriptive than "x".
nishanths
2016/08/12 02:37:39
Done, thanks.
| |
| 18 if ar == nil { | |
| 19 return errors.New("model: Merge: nil *AggregateResult") | |
| 20 } | |
| 21 if ar.Builder != x.Builder { | |
| 22 return ErrBuilderNameConflict | |
| 23 } | |
| 24 if ar.BuilderInfo == nil { | |
| 25 ar.BuilderInfo = &BuilderInfo{} | |
| 26 } | |
| 27 ar.Version = ResultsVersion | |
| 28 return ar.BuilderInfo.Merge(x.BuilderInfo) | |
| 29 } | |
| 30 | |
| 31 // Merge merges x into info. After merging, info's fields may reference the same | |
|
martiniss
2016/08/12 00:14:24
Does the reference comment matter? Would that ever
nishanths
2016/08/12 02:37:39
Removed, thanks.
| |
| 32 // objects referenced by x. | |
| 33 func (info *BuilderInfo) Merge(x *BuilderInfo) error { | |
|
martiniss
2016/08/12 00:14:24
nit: "x" variable name.
nishanths
2016/08/12 02:37:39
Done: used "other".
| |
| 34 if info == nil { | |
|
martiniss
2016/08/12 00:14:24
Why would info ever be nil?
nishanths
2016/08/12 02:37:39
Removed the check (also removed at similar locatio
| |
| 35 return errors.New("model: Merge: nil *BuilderInfo") | |
| 36 } | |
| 37 | |
| 38 if len(info.BuildNumbers) > 0 && len(x.BuildNumbers) > 0 { | |
| 39 if info.BuildNumbers[0] == x.BuildNumbers[0] { | |
| 40 return ErrBuildNumberConflict | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 info.SecondsEpoch = append(x.SecondsEpoch, info.SecondsEpoch...) | |
| 45 info.BlinkRevs = append(x.BlinkRevs, info.BlinkRevs...) | |
| 46 info.BuildNumbers = append(x.BuildNumbers, info.BuildNumbers...) | |
| 47 info.ChromeRevs = append(x.ChromeRevs, info.ChromeRevs...) | |
| 48 | |
| 49 for k, v := range x.FailuresByType { | |
| 50 if info.FailuresByType == nil { | |
|
martiniss
2016/08/12 00:14:24
Move outside for loop.
nishanths
2016/08/12 02:37:39
Done.
| |
| 51 info.FailuresByType = make(map[string][]int) | |
| 52 } | |
| 53 info.FailuresByType[k] = append(v, info.FailuresByType[k]...) | |
| 54 } | |
| 55 | |
| 56 info.FailureMap = FailureLongNames | |
| 57 | |
| 58 if info.Tests == nil { | |
| 59 info.Tests = AggregateTest{} | |
| 60 } | |
| 61 | |
| 62 info.Tests.WalkLeaves(func(_ string, leaf *AggregateTestLeaf) { | |
| 63 leaf.Expected = nil | |
| 64 leaf.Bugs = nil | |
| 65 }) | |
| 66 | |
| 67 return info.Tests.Merge(x.Tests) | |
| 68 } | |
| 69 | |
| 70 // Merge merges x into at. After merging, at's fields may reference the same | |
| 71 // objects referenced by x. | |
| 72 func (at *AggregateTest) Merge(x AggregateTest) error { | |
| 73 if at == nil { | |
| 74 return errors.New("model: Merge: nil *AggregateTest") | |
| 75 } | |
| 76 | |
| 77 // Shallow copy but OK. We take care to not modify xcopy | |
| 78 // values; instead always create new objects | |
| 79 // and assign to xcopy[key]. | |
| 80 xcopy := make(AggregateTest, len(x)) | |
|
martiniss
2016/08/12 00:14:24
shouldn't this be make([]AggregateTest, len(x)) ?
nishanths
2016/08/12 02:37:39
AggregateTest is a map[string]Node.
| |
| 81 for k, v := range x { | |
| 82 xcopy[k] = v | |
| 83 } | |
| 84 | |
| 85 for k, v := range *at { | |
| 86 if _, ok := xcopy[k]; !ok { | |
| 87 switch v.(type) { | |
| 88 case *AggregateTestLeaf: | |
| 89 l := &AggregateTestLeaf{} | |
| 90 l.defaultFields() | |
| 91 xcopy[k] = l | |
| 92 case AggregateTest: | |
| 93 xcopy[k] = AggregateTest{} | |
| 94 } | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 for k, v := range xcopy { | |
| 99 // Key does not exist: assign entire subtree. | |
| 100 if _, ok := (*at)[k]; !ok { | |
| 101 if *at == nil { | |
| 102 *at = AggregateTest{} | |
| 103 } | |
| 104 (*at)[k] = v | |
| 105 continue | |
| 106 } | |
| 107 | |
| 108 // Leaf node. | |
| 109 if leaf1, ok := (*at)[k].(*AggregateTestLeaf); ok { | |
| 110 leaf2, ok := v.(*AggregateTestLeaf) | |
| 111 if !ok { | |
| 112 return errors.New("model: Merge: expected *Aggre gateTestLeaf") | |
| 113 } | |
| 114 if err := leaf1.Merge(leaf2); err != nil { | |
| 115 return err | |
| 116 } | |
| 117 continue | |
| 118 } | |
| 119 | |
| 120 // Not leaf node: merge subtree recursively. | |
| 121 at1, ok := (*at)[k].(AggregateTest) | |
| 122 if !ok { | |
| 123 return errors.New("model: Merge: expected AggregateTest" ) | |
| 124 } | |
| 125 at2, ok := v.(AggregateTest) | |
| 126 if !ok { | |
| 127 return errors.New("model: Merge: expected AggregateTest" ) | |
| 128 } | |
| 129 if err := at1.Merge(at2); err != nil { | |
| 130 return err | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 return nil | |
| 135 } | |
| 136 | |
| 137 // Merge merges x into leaf. After merging, leaf's fields may reference the same | |
| 138 // objects referenced by x. | |
| 139 func (leaf *AggregateTestLeaf) Merge(x *AggregateTestLeaf) error { | |
| 140 if leaf == nil { | |
|
martiniss
2016/08/12 00:14:24
Same comment; seems unnecessary
nishanths
2016/08/12 02:37:39
Done, removed check.
| |
| 141 return errors.New("model: Merge: nil *AggregateTestLeaf") | |
| 142 } | |
| 143 | |
| 144 // Bugs and Expected should come from from x only. | |
| 145 leaf.Bugs = x.Bugs | |
| 146 if len(x.Expected) == 1 && x.Expected[0] != "PASS" { | |
| 147 leaf.Expected = x.Expected | |
| 148 } | |
| 149 | |
| 150 for _, r := range x.Results { | |
| 151 if len(leaf.Results) > 0 && r.Type == leaf.Results[0].Type { | |
| 152 leaf.Results[0].Count += r.Count | |
| 153 } else { | |
| 154 leaf.Results = append([]ResultSummary{r}, leaf.Results.. .) | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 for _, r := range x.Runtimes { | |
| 159 if len(leaf.Runtimes) > 0 && r.Runtime == leaf.Runtimes[0].Runti me { | |
| 160 leaf.Runtimes[0].Count += r.Count | |
| 161 } else { | |
| 162 leaf.Runtimes = append([]RuntimeSummary{r}, leaf.Runtime s...) | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 return nil | |
| 167 } | |
| OLD | NEW |