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 | |
| 10 import "status_expression.dart"; | 11 import "status_expression.dart"; |
| 12 import "utils.dart" show Path; | |
| 11 | 13 |
| 12 class Expectation { | 14 class Expectation { |
| 13 // Possible outcomes of running a test. | 15 // Possible outcomes of running a test. |
| 14 static Expectation PASS = byName('Pass'); | 16 static Expectation PASS = byName('Pass'); |
| 15 static Expectation CRASH = byName('Crash'); | 17 static Expectation CRASH = byName('Crash'); |
| 16 static Expectation TIMEOUT = byName('Timeout'); | 18 static Expectation TIMEOUT = byName('Timeout'); |
| 17 static Expectation FAIL = byName('Fail'); | 19 static Expectation FAIL = byName('Fail'); |
| 18 | 20 |
| 19 // Special 'FAIL' cases | 21 // Special 'FAIL' cases |
| 20 static Expectation RUNTIME_ERROR = byName('RuntimeError'); | 22 static Expectation RUNTIME_ERROR = byName('RuntimeError'); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 String toString() => prettyName; | 105 String toString() => prettyName; |
| 104 } | 106 } |
| 105 | 107 |
| 106 | 108 |
| 107 final RegExp SplitComment = new RegExp("^([^#]*)(#.*)?\$"); | 109 final RegExp SplitComment = new RegExp("^([^#]*)(#.*)?\$"); |
| 108 final RegExp HeaderPattern = new RegExp(r"^\[([^\]]+)\]"); | 110 final RegExp HeaderPattern = new RegExp(r"^\[([^\]]+)\]"); |
| 109 final RegExp RulePattern = new RegExp(r"\s*([^: ]*)\s*:(.*)"); | 111 final RegExp RulePattern = new RegExp(r"\s*([^: ]*)\s*:(.*)"); |
| 110 final RegExp IssueNumberPattern = | 112 final RegExp IssueNumberPattern = |
| 111 new RegExp("Issue ([0-9]+)|dartbug.com/([0-9]+)", caseSensitive: false); | 113 new RegExp("Issue ([0-9]+)|dartbug.com/([0-9]+)", caseSensitive: false); |
| 112 | 114 |
| 115 class StatusFile { | |
| 116 final Path location; | |
| 117 | |
| 118 StatusFile(this.location); | |
| 119 } | |
| 120 | |
| 113 // TODO(whesse): Implement configuration_info library that contains data | 121 // TODO(whesse): Implement configuration_info library that contains data |
| 114 // structures for test configuration, including Section. | 122 // structures for test configuration, including Section. |
| 115 class Section { | 123 class Section { |
| 116 BooleanExpression condition; | 124 final StatusFile statusFile; |
| 117 List<TestRule> testRules; | |
| 118 | 125 |
| 119 Section.always() : condition = null, testRules = new List<TestRule>(); | 126 final BooleanExpression condition; |
| 120 Section(this.condition) : testRules = new List<TestRule>(); | 127 final List<TestRule> testRules; |
| 128 final int lineNr; | |
|
ricow1
2014/02/11 14:33:52
lineNr -> lineNumber
kustermann
2014/02/14 11:52:07
Done.
| |
| 129 | |
| 130 Section.always(this.statusFile, this.lineNr) | |
| 131 : condition = null, testRules = new List<TestRule>(); | |
| 132 Section(this.statusFile, this.condition, this.lineNr) | |
| 133 : testRules = new List<TestRule>(); | |
| 121 | 134 |
| 122 bool isEnabled(environment) => | 135 bool isEnabled(environment) => |
| 123 condition == null || condition.evaluate(environment); | 136 condition == null || condition.evaluate(environment); |
| 124 | 137 |
| 125 String toString() { | 138 String toString() { |
| 126 return "Section: $condition"; | 139 return "Section: $condition"; |
| 127 } | 140 } |
| 128 } | 141 } |
| 129 | 142 |
| 130 Future<TestExpectations> ReadTestExpectations(List<String> statusFilePaths, | 143 Future<TestExpectations> ReadTestExpectations(List<String> statusFilePaths, |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 146 for (Section section in sections) { | 159 for (Section section in sections) { |
| 147 if (section.isEnabled(environment)) { | 160 if (section.isEnabled(environment)) { |
| 148 for (var rule in section.testRules) { | 161 for (var rule in section.testRules) { |
| 149 expectations.addRule(rule, environment); | 162 expectations.addRule(rule, environment); |
| 150 } | 163 } |
| 151 } | 164 } |
| 152 } | 165 } |
| 153 completer.complete(); | 166 completer.complete(); |
| 154 } | 167 } |
| 155 | 168 |
| 156 ReadConfigurationInto(statusFilePath, sections, sectionsRead); | 169 ReadConfigurationInto(new Path(statusFilePath), sections, sectionsRead); |
|
Bill Hesse
2014/02/13 17:05:08
As we've said before, it would be nice to replace
kustermann
2014/02/14 11:52:07
There are *many* places we need to change, yes.
| |
| 157 return completer.future; | 170 return completer.future; |
| 158 } | 171 } |
| 159 | 172 |
| 160 void ReadConfigurationInto(path, sections, onDone) { | 173 void ReadConfigurationInto(Path path, sections, onDone) { |
| 161 File file = new File(path); | 174 StatusFile statusFile = new StatusFile(path); |
| 175 File file = new File(path.toNativePath()); | |
| 162 if (!file.existsSync()) { | 176 if (!file.existsSync()) { |
| 163 throw new Exception('Cannot find test status file $path'); | 177 throw new Exception('Cannot find test status file $path'); |
| 164 } | 178 } |
| 179 int lineNr = 0; | |
|
Bill Hesse
2014/02/13 17:05:08
Should we start this at -1, so we get zero-based l
kustermann
2014/02/14 11:52:07
The reason why I chose 1-based line numbering is t
| |
| 165 Stream<String> lines = | 180 Stream<String> lines = |
| 166 file.openRead() | 181 file.openRead() |
| 167 .transform(UTF8.decoder) | 182 .transform(UTF8.decoder) |
| 168 .transform(new LineSplitter()); | 183 .transform(new LineSplitter()); |
| 169 | 184 |
| 170 Section current = new Section.always(); | 185 Section currentSection = new Section.always(statusFile, -1); |
| 171 sections.add(current); | 186 sections.add(currentSection); |
| 187 | |
| 172 | 188 |
| 173 lines.listen((String line) { | 189 lines.listen((String line) { |
| 190 lineNr++; | |
| 174 Match match = SplitComment.firstMatch(line); | 191 Match match = SplitComment.firstMatch(line); |
| 175 line = (match == null) ? "" : match[1]; | 192 line = (match == null) ? "" : match[1]; |
| 176 line = line.trim(); | 193 line = line.trim(); |
| 177 if (line.isEmpty) return; | 194 if (line.isEmpty) return; |
| 178 | 195 |
| 179 // Extract the comment to get the issue number if needed. | 196 // Extract the comment to get the issue number if needed. |
| 180 String comment = (match == null || match[2] == null) ? "" : match[2]; | 197 String comment = (match == null || match[2] == null) ? "" : match[2]; |
| 181 | 198 |
| 182 match = HeaderPattern.firstMatch(line); | 199 match = HeaderPattern.firstMatch(line); |
| 183 if (match != null) { | 200 if (match != null) { |
| 184 String condition_string = match[1].trim(); | 201 String condition_string = match[1].trim(); |
| 185 List<String> tokens = new Tokenizer(condition_string).tokenize(); | 202 List<String> tokens = new Tokenizer(condition_string).tokenize(); |
| 186 ExpressionParser parser = new ExpressionParser(new Scanner(tokens)); | 203 ExpressionParser parser = new ExpressionParser(new Scanner(tokens)); |
| 187 current = new Section(parser.parseBooleanExpression()); | 204 currentSection = |
| 188 sections.add(current); | 205 new Section(statusFile, parser.parseBooleanExpression(), lineNr); |
| 206 sections.add(currentSection); | |
| 189 return; | 207 return; |
| 190 } | 208 } |
| 191 | 209 |
| 192 match = RulePattern.firstMatch(line); | 210 match = RulePattern.firstMatch(line); |
| 193 if (match != null) { | 211 if (match != null) { |
| 194 String name = match[1].trim(); | 212 String name = match[1].trim(); |
| 195 // TODO(whesse): Handle test names ending in a wildcard (*). | 213 // TODO(whesse): Handle test names ending in a wildcard (*). |
| 196 String expression_string = match[2].trim(); | 214 String expression_string = match[2].trim(); |
| 197 List<String> tokens = new Tokenizer(expression_string).tokenize(); | 215 List<String> tokens = new Tokenizer(expression_string).tokenize(); |
| 198 SetExpression expression = | 216 SetExpression expression = |
| 199 new ExpressionParser(new Scanner(tokens)).parseSetExpression(); | 217 new ExpressionParser(new Scanner(tokens)).parseSetExpression(); |
| 200 | 218 |
| 201 // Look for issue number in comment. | 219 // Look for issue number in comment. |
| 202 String issueString = null; | 220 String issueString = null; |
| 203 match = IssueNumberPattern.firstMatch(comment); | 221 match = IssueNumberPattern.firstMatch(comment); |
| 204 if (match != null) { | 222 if (match != null) { |
| 205 issueString = match[1]; | 223 issueString = match[1]; |
| 206 if (issueString == null) issueString = match[2]; | 224 if (issueString == null) issueString = match[2]; |
| 207 } | 225 } |
| 208 int issue = issueString != null ? int.parse(issueString) : null; | 226 int issue = issueString != null ? int.parse(issueString) : null; |
| 209 current.testRules.add(new TestRule(name, expression, issue)); | 227 currentSection.testRules.add( |
| 228 new TestRule(currentSection, name, expression, issue, lineNr)); | |
| 210 return; | 229 return; |
| 211 } | 230 } |
| 212 | 231 |
| 213 print("unmatched line: $line"); | 232 print("unmatched line: $line"); |
| 214 }, | 233 }, |
| 215 onDone: onDone); | 234 onDone: onDone); |
| 216 } | 235 } |
| 217 | 236 |
| 218 | 237 |
| 219 class TestRule { | 238 class TestRule { |
| 239 final Section section; | |
|
Bill Hesse
2014/02/13 17:05:08
I don't see this property being used in any of the
kustermann
2014/02/14 11:52:07
Good point - removed. I think I used it in an earl
| |
| 240 | |
| 220 String name; | 241 String name; |
| 221 SetExpression expression; | 242 SetExpression expression; |
| 222 int issue; | 243 int issue; |
| 244 int lineNr; | |
| 223 | 245 |
| 224 TestRule(this.name, this.expression, this.issue); | 246 TestRule(this.section, this.name, this.expression, this.issue, this.lineNr); |
| 225 | 247 |
| 226 bool get hasIssue => issue != null; | 248 bool get hasIssue => issue != null; |
| 227 | 249 |
| 228 String toString() => 'TestRule($name, $expression, $issue)'; | 250 String toString() => 'TestRule($name, $expression, $issue)'; |
| 229 } | 251 } |
| 230 | 252 |
| 231 | 253 |
| 232 class TestExpectations { | 254 class TestExpectations { |
| 233 Map _map; | 255 Map _map; |
| 234 bool _preprocessed = false; | 256 bool _preprocessed = false; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 } | 337 } |
| 316 regExps[i] = regExp; | 338 regExps[i] = regExp; |
| 317 } | 339 } |
| 318 _keyToRegExps[key] = regExps; | 340 _keyToRegExps[key] = regExps; |
| 319 }); | 341 }); |
| 320 | 342 |
| 321 _regExpCache = null; | 343 _regExpCache = null; |
| 322 _preprocessed = true; | 344 _preprocessed = true; |
| 323 } | 345 } |
| 324 } | 346 } |
| OLD | NEW |