Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 library status_file_parser; | 5 library status_file_parser; |
| 6 | 6 |
| 7 import "dart:async"; | 7 import "dart:async"; |
| 8 import "dart:convert" show LineSplitter, UTF8; | 8 import "dart:convert" show LineSplitter, UTF8; |
| 9 import "dart:io"; | 9 import "dart:io"; |
| 10 import "status_expression.dart"; | 10 import "status_expression.dart"; |
| 11 | 11 |
| 12 /** Possible outcomes of running a test. */ | 12 class Expectation { |
| 13 const CRASH = "crash"; | 13 // Possible outcomes of running a test. |
| 14 const TIMEOUT = "timeout"; | 14 static Expectation PASS = byName('Pass'); |
| 15 const FAIL = "fail"; | 15 static Expectation CRASH = byName('Crash'); |
| 16 const PASS = "pass"; | 16 static Expectation TIMEOUT = byName('Timeout'); |
| 17 /** | 17 static Expectation FAIL = byName('Fail'); |
| 18 * An indication to skip the test. The caller is responsible for skipping it. | 18 |
| 19 */ | 19 // Special 'FAIL' cases |
| 20 const SKIP = "skip"; | 20 static Expectation RUNTIME_ERROR = byName('RuntimeError'); |
| 21 const SKIP_BY_DESIGN = "skipbydesign"; | 21 static Expectation COMPILETIME_ERROR = byName('CompileTimeError'); |
|
ricow1
2013/09/23 12:07:32
nit, but there seems to be some difference in how
kustermann
2013/09/23 15:31:34
Changed it to *CompileTime*
| |
| 22 const OK = "ok"; | 22 static Expectation MISSING_RUNTIME_ERROR = byName('MissingRuntimeError'); |
| 23 /** | 23 static Expectation MISSING_COMPILETIME_ERROR = |
| 24 * An indication that a test is slow and we should allow extra time for | 24 byName('MissingCompiletimeError'); |
| 25 * completion. | 25 |
| 26 */ | 26 // "meta expectations" |
| 27 const SLOW = "slow"; | 27 static Expectation OK = byName('Ok'); |
| 28 static Expectation SLOW = byName('Slow'); | |
| 29 static Expectation SKIP = byName('Skip'); | |
| 30 static Expectation SKIP_BY_DESIGN = byName('SkipByDesign'); | |
| 31 | |
| 32 static Expectation byName(String name) { | |
| 33 _initialize(); | |
| 34 name = name.toLowerCase(); | |
| 35 if (!_AllExpectations.containsKey(name)) { | |
| 36 throw new Exception("Expectation.byName(name='$name'): Invalid name."); | |
| 37 } | |
| 38 return _AllExpectations[name]; | |
| 39 } | |
| 40 | |
| 41 // Keep a map of all possible Expectation objects, initialized lazily. | |
| 42 static bool _initialized = false; | |
| 43 static final _AllExpectations = new Map<String, Expectation>(); | |
|
ricow1
2013/09/23 12:07:32
just let this be null and branch on that in _initi
kustermann
2013/09/23 15:31:34
Done.
| |
| 44 static void _initialize() { | |
| 45 if (!_initialized) { | |
| 46 _initialized = true; | |
| 47 | |
| 48 Expectation build(prettyName, {group: null, isMetaExpectation: false}) { | |
| 49 var expectation = new Expectation._(prettyName, | |
| 50 group: group, isMetaExpectation: isMetaExpectation); | |
| 51 assert(!_AllExpectations.containsKey(expectation.name)); | |
| 52 return _AllExpectations[expectation.name] = expectation; | |
| 53 } | |
| 54 | |
| 55 var fail = build("Fail"); | |
| 56 build("Pass"); | |
| 57 build("Crash"); | |
| 58 build("Timeout"); | |
| 59 | |
| 60 build("MissingCompiletimeError", group: fail); | |
| 61 build("MissingRuntimeError", group: fail); | |
| 62 build("CompiletimeError", group: fail); | |
| 63 build("RuntimeError", group: fail); | |
| 64 | |
| 65 build("Skip", isMetaExpectation: true); | |
| 66 build("SkipByDesign", isMetaExpectation: true); | |
| 67 build("Ok", isMetaExpectation: true); | |
| 68 build("Slow", isMetaExpectation: true); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 final String prettyName; | |
| 73 final String name; | |
| 74 final Expectation group; | |
| 75 // Indicates whether this expectation can actually be the outcome of a test. | |
|
ricow1
2013/09/23 12:07:32
well it actually indicates the opposite
kustermann
2013/09/23 15:31:34
I clarified it a bit.
| |
| 76 final bool isMetaExpectation; | |
| 77 | |
| 78 Expectation._(prettyName, | |
| 79 {Expectation this.group: null, | |
| 80 bool this.isMetaExpectation: false}) | |
| 81 : prettyName = prettyName, name = prettyName.toLowerCase(); | |
| 82 | |
| 83 bool canBeOutcomeOf(Expectation expectation) { | |
| 84 Expectation outcome = this; | |
| 85 while (outcome != null) { | |
| 86 if (outcome == expectation) { | |
| 87 return true; | |
| 88 } | |
| 89 outcome = outcome.group; | |
| 90 } | |
| 91 return false; | |
| 92 } | |
| 93 | |
| 94 String toString() => prettyName; | |
| 95 } | |
| 96 | |
| 28 | 97 |
| 29 final RegExp SplitComment = new RegExp("^([^#]*)(#.*)?\$"); | 98 final RegExp SplitComment = new RegExp("^([^#]*)(#.*)?\$"); |
| 30 final RegExp HeaderPattern = new RegExp(r"^\[([^\]]+)\]"); | 99 final RegExp HeaderPattern = new RegExp(r"^\[([^\]]+)\]"); |
| 31 final RegExp RulePattern = new RegExp(r"\s*([^: ]*)\s*:(.*)"); | 100 final RegExp RulePattern = new RegExp(r"\s*([^: ]*)\s*:(.*)"); |
| 32 final RegExp IssueNumberPattern = | 101 final RegExp IssueNumberPattern = |
| 33 new RegExp("Issue ([0-9]+)|dartbug.com/([0-9]+)", caseSensitive: false); | 102 new RegExp("Issue ([0-9]+)|dartbug.com/([0-9]+)", caseSensitive: false); |
| 34 | 103 |
| 35 // TODO(whesse): Implement configuration_info library that contains data | 104 // TODO(whesse): Implement configuration_info library that contains data |
| 36 // structures for test configuration, including Section. | 105 // structures for test configuration, including Section. |
| 37 class Section { | 106 class Section { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 | 224 |
| 156 /** | 225 /** |
| 157 * Add a rule to the expectations. | 226 * Add a rule to the expectations. |
| 158 */ | 227 */ |
| 159 void addRule(testRule, environment) { | 228 void addRule(testRule, environment) { |
| 160 // Once we have started using the expectations we cannot add more | 229 // Once we have started using the expectations we cannot add more |
| 161 // rules. | 230 // rules. |
| 162 if (_preprocessed) { | 231 if (_preprocessed) { |
| 163 throw "TestExpectations.addRule: cannot add more rules"; | 232 throw "TestExpectations.addRule: cannot add more rules"; |
| 164 } | 233 } |
| 165 var values = testRule.expression.evaluate(environment); | 234 var names = testRule.expression.evaluate(environment); |
| 166 _map.putIfAbsent(testRule.name, () => new Set()).addAll(values); | 235 var expectations = names.map((name) => Expectation.byName(name)); |
| 236 _map.putIfAbsent(testRule.name, () => new Set()).addAll(expectations); | |
| 167 } | 237 } |
| 168 | 238 |
| 169 /** | 239 /** |
| 170 * Compute the expectations for a test based on the filename. | 240 * Compute the expectations for a test based on the filename. |
| 171 * | 241 * |
| 172 * For every (key, expectation) pair. Match the key with the file | 242 * For every (key, expectation) pair. Match the key with the file |
| 173 * name. Return the union of the expectations for all the keys | 243 * name. Return the union of the expectations for all the keys |
| 174 * that match. | 244 * that match. |
| 175 * | 245 * |
| 176 * Normal matching splits the key and the filename into path | 246 * Normal matching splits the key and the filename into path |
| 177 * components and checks that the anchored regular expression | 247 * components and checks that the anchored regular expression |
| 178 * "^$keyComponent\$" matches the corresponding filename component. | 248 * "^$keyComponent\$" matches the corresponding filename component. |
| 179 */ | 249 */ |
| 180 Set<String> expectations(String filename) { | 250 Set<Expectation> expectations(String filename) { |
| 181 var result = new Set(); | 251 var result = new Set(); |
| 182 var splitFilename = filename.split('/'); | 252 var splitFilename = filename.split('/'); |
| 183 | 253 |
| 184 // Create mapping from keys to list of RegExps once and for all. | 254 // Create mapping from keys to list of RegExps once and for all. |
| 185 _preprocessForMatching(); | 255 _preprocessForMatching(); |
| 186 | 256 |
| 187 _map.forEach((key, expectation) { | 257 _map.forEach((key, expectation) { |
| 188 List regExps = _keyToRegExps[key]; | 258 List regExps = _keyToRegExps[key]; |
| 189 if (regExps.length > splitFilename.length) return; | 259 if (regExps.length > splitFilename.length) return; |
| 190 for (var i = 0; i < regExps.length; i++) { | 260 for (var i = 0; i < regExps.length; i++) { |
| 191 if (!regExps[i].hasMatch(splitFilename[i])) return; | 261 if (!regExps[i].hasMatch(splitFilename[i])) return; |
| 192 } | 262 } |
| 193 // If all components of the status file key matches the filename | 263 // If all components of the status file key matches the filename |
| 194 // add the expectations to the result. | 264 // add the expectations to the result. |
| 195 result.addAll(expectation); | 265 result.addAll(expectation); |
| 196 }); | 266 }); |
| 197 | 267 |
| 198 // If no expectations were found the expectation is that the test | 268 // If no expectations were found the expectation is that the test |
| 199 // passes. | 269 // passes. |
| 200 if (result.isEmpty) { | 270 if (result.isEmpty) { |
| 201 result.add(PASS); | 271 result.add(Expectation.PASS); |
| 202 } | 272 } |
| 203 return result; | 273 return result; |
| 204 } | 274 } |
| 205 | 275 |
| 206 // Preprocess the expectations for matching against | 276 // Preprocess the expectations for matching against |
| 207 // filenames. Generate lists of regular expressions once and for all | 277 // filenames. Generate lists of regular expressions once and for all |
| 208 // for each key. | 278 // for each key. |
| 209 void _preprocessForMatching() { | 279 void _preprocessForMatching() { |
| 210 if (_preprocessed) return; | 280 if (_preprocessed) return; |
| 211 | 281 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 226 } | 296 } |
| 227 regExps[i] = regExp; | 297 regExps[i] = regExp; |
| 228 } | 298 } |
| 229 _keyToRegExps[key] = regExps; | 299 _keyToRegExps[key] = regExps; |
| 230 }); | 300 }); |
| 231 | 301 |
| 232 _regExpCache = null; | 302 _regExpCache = null; |
| 233 _preprocessed = true; | 303 _preprocessed = true; |
| 234 } | 304 } |
| 235 } | 305 } |
| OLD | NEW |