OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'util.dart'; | 5 import 'util.dart'; |
6 | 6 |
7 /// The [Uri] of a build step stdio log split into its subparts. | 7 /// The [Uri] of a build step stdio log split into its subparts. |
8 class BuildUri { | 8 class BuildUri { |
9 final String scheme; | 9 final String scheme; |
10 final String host; | 10 final String host; |
(...skipping 13 matching lines...) Expand all Loading... |
24 } | 24 } |
25 | 25 |
26 factory BuildUri.fromData(String botName, int buildNumber, String stepName) { | 26 factory BuildUri.fromData(String botName, int buildNumber, String stepName) { |
27 return new BuildUri.internal('https', 'build.chromium.org', | 27 return new BuildUri.internal('https', 'build.chromium.org', |
28 '/p/client.dart', botName, buildNumber, stepName, 'stdio/text'); | 28 '/p/client.dart', botName, buildNumber, stepName, 'stdio/text'); |
29 } | 29 } |
30 | 30 |
31 BuildUri.internal(this.scheme, this.host, this.prefix, this.botName, | 31 BuildUri.internal(this.scheme, this.host, this.prefix, this.botName, |
32 this.buildNumber, this.stepName, this.suffix); | 32 this.buildNumber, this.stepName, this.suffix); |
33 | 33 |
| 34 BuildUri withBuildNumber(int buildNumber) { |
| 35 return new BuildUri.fromData(botName, buildNumber, stepName); |
| 36 } |
| 37 |
34 String get shortBuildName => '$botName/$stepName'; | 38 String get shortBuildName => '$botName/$stepName'; |
35 | 39 |
36 String get buildName => | 40 String get buildName => |
37 '/builders/$botName/builds/$buildNumber/steps/$stepName'; | 41 '/builders/$botName/builds/$buildNumber/steps/$stepName'; |
38 | 42 |
39 String get path => '$prefix$buildName/logs/$suffix'; | 43 String get path => '$prefix$buildName/logs/$suffix'; |
40 | 44 |
| 45 /// Returns the path used in logdog for this build uri. |
| 46 /// |
| 47 /// Since logdog only supports absolute build numbers, [buildNumber] must be |
| 48 /// non-negative. A [StateError] is thrown, otherwise. |
| 49 String get logdogPath { |
| 50 if (buildNumber < 0) |
| 51 throw new StateError('BuildUri $buildName must have a non-negative build ' |
| 52 'number to a valid logdog path.'); |
| 53 return 'chromium/bb/client.dart/$botName/$buildNumber/+/recipes/steps/' |
| 54 '${stepName.replaceAll(' ', '_')}/0/stdout'; |
| 55 } |
| 56 |
41 /// Creates the [Uri] for this build step stdio log. | 57 /// Creates the [Uri] for this build step stdio log. |
42 Uri toUri() { | 58 Uri toUri() { |
43 return new Uri(scheme: scheme, host: host, path: path); | 59 return new Uri(scheme: scheme, host: host, path: path); |
44 } | 60 } |
45 | 61 |
46 /// Returns the [BuildUri] the previous build of this build step. | 62 /// Returns the [BuildUri] the previous build of this build step. |
47 BuildUri prev() { | 63 BuildUri prev() { |
48 return new BuildUri.internal( | 64 return new BuildUri.internal( |
49 scheme, host, prefix, botName, buildNumber - 1, stepName, suffix); | 65 scheme, host, prefix, botName, buildNumber - 1, stepName, suffix); |
50 } | 66 } |
(...skipping 22 matching lines...) Expand all Loading... |
73 testName.hashCode * 19; | 89 testName.hashCode * 19; |
74 | 90 |
75 bool operator ==(other) { | 91 bool operator ==(other) { |
76 if (identical(this, other)) return true; | 92 if (identical(this, other)) return true; |
77 if (other is! TestConfiguration) return false; | 93 if (other is! TestConfiguration) return false; |
78 return configName == other.configName && | 94 return configName == other.configName && |
79 archName == other.archName && | 95 archName == other.archName && |
80 testName == other.testName; | 96 testName == other.testName; |
81 } | 97 } |
82 } | 98 } |
| 99 |
| 100 /// The results of a build step. |
| 101 class BuildResult { |
| 102 final BuildUri _buildUri; |
| 103 |
| 104 /// The absolute build number, if found. |
| 105 /// |
| 106 /// The [buildUri] can be created with a relative build number, such as `-2` |
| 107 /// which means the second-to-last build. The absolute build number, a |
| 108 /// positive number, is read from the build results. |
| 109 final int buildNumber; |
| 110 |
| 111 final List<TestStatus> _results; |
| 112 final List<TestFailure> _failures; |
| 113 final List<Timing> _timings; |
| 114 |
| 115 BuildResult(this._buildUri, this.buildNumber, this._results, this._failures, |
| 116 this._timings); |
| 117 |
| 118 BuildUri get buildUri => |
| 119 buildNumber != null ? _buildUri.withBuildNumber(buildNumber) : _buildUri; |
| 120 |
| 121 /// `true` of the build result has test failures. |
| 122 bool get hasFailures => _failures.isNotEmpty; |
| 123 |
| 124 /// Returns the top-20 timings found in the build log. |
| 125 Iterable<Timing> get timings => _timings; |
| 126 |
| 127 /// Returns the [TestStatus] for all tests. |
| 128 Iterable<TestStatus> get results => _results; |
| 129 |
| 130 /// Returns the [TestFailure]s for tests that timed out. |
| 131 Iterable<TestFailure> get timeouts { |
| 132 return _failures |
| 133 .where((TestFailure failure) => failure.actual == 'Timeout'); |
| 134 } |
| 135 |
| 136 /// Returns the [TestFailure]s for failing tests that did not time out. |
| 137 Iterable<TestFailure> get errors { |
| 138 return _failures |
| 139 .where((TestFailure failure) => failure.actual != 'Timeout'); |
| 140 } |
| 141 |
| 142 String toString() { |
| 143 StringBuffer sb = new StringBuffer(); |
| 144 sb.write('$buildUri\n'); |
| 145 sb.write('Failures:\n${_failures.join('\n-----\n')}\n'); |
| 146 sb.write('\nTimings:\n${_timings.join('\n')}'); |
| 147 return sb.toString(); |
| 148 } |
| 149 } |
| 150 |
| 151 /// Test failure data derived from the test failure summary in the build step |
| 152 /// stdio log. |
| 153 class TestFailure { |
| 154 final BuildUri uri; |
| 155 final TestConfiguration id; |
| 156 final String expected; |
| 157 final String actual; |
| 158 final String text; |
| 159 |
| 160 factory TestFailure(BuildUri uri, List<String> lines) { |
| 161 List<String> parts = split(lines.first, ['FAILED: ', ' ', ' ']); |
| 162 String configName = parts[1]; |
| 163 String archName = parts[2]; |
| 164 String testName = parts[3]; |
| 165 TestConfiguration id = |
| 166 new TestConfiguration(configName, archName, testName); |
| 167 String expected = split(lines[1], ['Expected: '])[1]; |
| 168 String actual = split(lines[2], ['Actual: '])[1]; |
| 169 return new TestFailure.internal( |
| 170 uri, id, expected, actual, lines.skip(3).join('\n')); |
| 171 } |
| 172 |
| 173 TestFailure.internal( |
| 174 this.uri, this.id, this.expected, this.actual, this.text); |
| 175 |
| 176 String toString() { |
| 177 StringBuffer sb = new StringBuffer(); |
| 178 sb.write('FAILED: $id\n'); |
| 179 sb.write('Expected: $expected\n'); |
| 180 sb.write('Actual: $actual\n'); |
| 181 sb.write(text); |
| 182 return sb.toString(); |
| 183 } |
| 184 } |
| 185 |
| 186 /// Id for a single test step, for instance the compilation and run steps of |
| 187 /// a test. |
| 188 class TestStep { |
| 189 final String stepName; |
| 190 final TestConfiguration id; |
| 191 |
| 192 TestStep(this.stepName, this.id); |
| 193 |
| 194 String toString() { |
| 195 return '$stepName - $id'; |
| 196 } |
| 197 |
| 198 int get hashCode => stepName.hashCode * 13 + id.hashCode * 17; |
| 199 |
| 200 bool operator ==(other) { |
| 201 if (identical(this, other)) return true; |
| 202 if (other is! TestStep) return false; |
| 203 return stepName == other.stepName && id == other.id; |
| 204 } |
| 205 } |
| 206 |
| 207 /// The timing result for a single test step. |
| 208 class Timing { |
| 209 final BuildUri uri; |
| 210 final String time; |
| 211 final TestStep step; |
| 212 |
| 213 Timing(this.uri, this.time, this.step); |
| 214 |
| 215 String toString() { |
| 216 return '$time - $step'; |
| 217 } |
| 218 } |
| 219 |
| 220 /// The result of a single test for a single test step. |
| 221 class TestStatus { |
| 222 final TestConfiguration config; |
| 223 final String status; |
| 224 |
| 225 TestStatus(this.config, this.status); |
| 226 |
| 227 String toString() => '$config: $status'; |
| 228 } |
OLD | NEW |