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

Unified Diff: tools/testing/dart/status_file_parser.dart

Issue 2875203005: Refactor and clean up the status file parsing code. (Closed)
Patch Set: Dartfmt. Created 3 years, 7 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
« no previous file with comments | « tools/testing/dart/status_file.dart ('k') | tools/testing/dart/summary_report.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/testing/dart/status_file_parser.dart
diff --git a/tools/testing/dart/status_file_parser.dart b/tools/testing/dart/status_file_parser.dart
deleted file mode 100644
index 49fdc9bf2420589b36a85d69b631d4bf38546e46..0000000000000000000000000000000000000000
--- a/tools/testing/dart/status_file_parser.dart
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library status_file_parser;
-
-import "dart:async";
-import "dart:convert" show LineSplitter, UTF8;
-import "dart:io";
-
-import "path.dart";
-import "status_expression.dart";
-
-typedef void Action();
-
-class Expectation {
- // Possible outcomes of running a test.
- static Expectation PASS = byName('Pass');
- static Expectation CRASH = byName('Crash');
- static Expectation TIMEOUT = byName('Timeout');
- static Expectation FAIL = byName('Fail');
-
- // Special 'FAIL' cases
- static Expectation RUNTIME_ERROR = byName('RuntimeError');
- static Expectation COMPILETIME_ERROR = byName('CompileTimeError');
- static Expectation MISSING_RUNTIME_ERROR = byName('MissingRuntimeError');
- static Expectation MISSING_COMPILETIME_ERROR =
- byName('MissingCompileTimeError');
- static Expectation STATIC_WARNING = byName('StaticWarning');
- static Expectation MISSING_STATIC_WARNING = byName('MissingStaticWarning');
- static Expectation PUB_GET_ERROR = byName('PubGetError');
- static Expectation NON_UTF8_ERROR = byName('NonUtf8Output');
-
- // Special 'CRASH' cases
- static Expectation DARTK_CRASH = byName('DartkCrash');
-
- // Special 'TIMEOUT' cases
- static Expectation DARTK_TIMEOUT = byName('DartkTimeout');
-
- // Special 'COMPILETIME_ERROR'
- static Expectation DARTK_COMPILETIME_ERROR = byName('DartkCompileTimeError');
-
- // "meta expectations"
- static Expectation OK = byName('Ok');
- static Expectation SLOW = byName('Slow');
- static Expectation SKIP = byName('Skip');
- static Expectation SKIP_SLOW = byName('SkipSlow');
- static Expectation SKIP_BY_DESIGN = byName('SkipByDesign');
-
- // Can be returned by the test runner to say the result should be ignored,
- // and assumed to meet the expectations, due to an infrastructure failure.
- // Do not place in status files.
- static Expectation IGNORE = byName('Ignore');
-
- static Expectation byName(String name) {
- _initialize();
- name = name.toLowerCase();
- if (!_AllExpectations.containsKey(name)) {
- throw new Exception("Expectation.byName(name='$name'): Invalid name.");
- }
- return _AllExpectations[name];
- }
-
- // Keep a map of all possible Expectation objects, initialized lazily.
- static Map<String, Expectation> _AllExpectations;
- static void _initialize() {
- if (_AllExpectations == null) {
- _AllExpectations = new Map<String, Expectation>();
-
- Expectation build(String prettyName,
- {Expectation group, bool isMetaExpectation: false}) {
- var expectation = new Expectation._(prettyName,
- group: group, isMetaExpectation: isMetaExpectation);
- assert(!_AllExpectations.containsKey(expectation.name));
- return _AllExpectations[expectation.name] = expectation;
- }
-
- var fail = build("Fail");
- var crash = build("Crash");
- var timeout = build("Timeout");
- build("Pass");
-
- var compileError = build("CompileTimeError", group: fail);
- build("MissingCompileTimeError", group: fail);
- build("MissingRuntimeError", group: fail);
- build("RuntimeError", group: fail);
- build("NonUtf8Output", group: fail);
-
- // Dartk sub expectations
- build("DartkCrash", group: crash);
- build("DartkTimeout", group: timeout);
- build("DartkCompileTimeError", group: compileError);
-
- build("MissingStaticWarning", group: fail);
- build("StaticWarning", group: fail);
-
- build("PubGetError", group: fail);
-
- var skip = build("Skip", isMetaExpectation: true);
- build("SkipByDesign", isMetaExpectation: true);
- build("SkipSlow", group: skip, isMetaExpectation: true);
- build("Ok", isMetaExpectation: true);
- build("Slow", isMetaExpectation: true);
- build("Ignore");
- }
- }
-
- final String prettyName;
- final String name;
- final Expectation group;
- // Indicates whether this expectation cannot be a test outcome (i.e. it is a
- // "meta marker").
- final bool isMetaExpectation;
-
- Expectation._(this.prettyName,
- {Expectation this.group: null, bool this.isMetaExpectation: false})
- : name = prettyName.toLowerCase();
-
- bool canBeOutcomeOf(Expectation expectation) {
- Expectation outcome = this;
- if (outcome == IGNORE) return true;
- while (outcome != null) {
- if (outcome == expectation) {
- return true;
- }
- outcome = outcome.group;
- }
- return false;
- }
-
- String toString() => prettyName;
-}
-
-final RegExp SplitComment = new RegExp("^([^#]*)(#.*)?\$");
-final RegExp HeaderPattern = new RegExp(r"^\[([^\]]+)\]");
-final RegExp RulePattern = new RegExp(r"\s*([^: ]*)\s*:(.*)");
-final RegExp IssueNumberPattern = new RegExp("[Ii]ssue ([0-9]+)");
-
-class StatusFile {
- final Path location;
-
- StatusFile(this.location);
-}
-
-// TODO(whesse): Implement configuration_info library that contains data
-// structures for test configuration, including Section.
-class Section {
- final StatusFile statusFile;
-
- final BooleanExpression condition;
- final List<TestRule> testRules;
- final int lineNumber;
-
- Section.always(this.statusFile, this.lineNumber)
- : condition = null,
- testRules = new List<TestRule>();
- Section(this.statusFile, this.condition, this.lineNumber)
- : testRules = new List<TestRule>();
-
- bool isEnabled(environment) =>
- condition == null || condition.evaluate(environment);
-
- String toString() {
- return "Section: $condition";
- }
-}
-
-Future<TestExpectations> ReadTestExpectations(
- List<String> statusFilePaths, Map<String, String> environment) {
- var testExpectations = new TestExpectations();
- return Future.wait(statusFilePaths.map((String statusFile) {
- return ReadTestExpectationsInto(testExpectations, statusFile, environment);
- })).then((_) => testExpectations);
-}
-
-Future ReadTestExpectationsInto(TestExpectations expectations,
- String statusFilePath, Map<String, String> environment) {
- var completer = new Completer<Null>();
- var sections = <Section>[];
-
- void sectionsRead() {
- for (Section section in sections) {
- if (section.isEnabled(environment)) {
- for (var rule in section.testRules) {
- expectations.addRule(rule, environment);
- }
- }
- }
- completer.complete();
- }
-
- ReadConfigurationInto(new Path(statusFilePath), sections, sectionsRead);
- return completer.future;
-}
-
-void ReadConfigurationInto(Path path, List<Section> sections, Action onDone) {
- StatusFile statusFile = new StatusFile(path);
- File file = new File(path.toNativePath());
- if (!file.existsSync()) {
- throw new Exception('Cannot find test status file $path');
- }
- int lineNumber = 0;
- Stream<String> lines =
- file.openRead().transform(UTF8.decoder).transform(new LineSplitter());
-
- Section currentSection = new Section.always(statusFile, -1);
- sections.add(currentSection);
-
- lines.listen((String line) {
- lineNumber++;
- Match match = SplitComment.firstMatch(line);
- line = (match == null) ? "" : match[1];
- line = line.trim();
- if (line.isEmpty) return;
-
- // Extract the comment to get the issue number if needed.
- String comment = (match == null || match[2] == null) ? "" : match[2];
-
- match = HeaderPattern.firstMatch(line);
- if (match != null) {
- String condition_string = match[1].trim();
- List<String> tokens = new Tokenizer(condition_string).tokenize();
- ExpressionParser parser = new ExpressionParser(new Scanner(tokens));
- currentSection =
- new Section(statusFile, parser.parseBooleanExpression(), lineNumber);
- sections.add(currentSection);
- return;
- }
-
- match = RulePattern.firstMatch(line);
- if (match != null) {
- String name = match[1].trim();
- // TODO(whesse): Handle test names ending in a wildcard (*).
- String expression_string = match[2].trim();
- List<String> tokens = new Tokenizer(expression_string).tokenize();
- SetExpression expression =
- new ExpressionParser(new Scanner(tokens)).parseSetExpression();
-
- // Look for issue number in comment.
- String issueString = null;
- match = IssueNumberPattern.firstMatch(comment);
- if (match != null) {
- issueString = match[1];
- if (issueString == null) issueString = match[2];
- }
- int issue = issueString != null ? int.parse(issueString) : null;
- currentSection.testRules
- .add(new TestRule(name, expression, issue, lineNumber));
- return;
- }
-
- print("unmatched line: $line");
- }, onDone: onDone);
-}
-
-class TestRule {
- String name;
- SetExpression expression;
- int issue;
- int lineNumber;
-
- TestRule(this.name, this.expression, this.issue, this.lineNumber);
-
- bool get hasIssue => issue != null;
-
- String toString() => 'TestRule($name, $expression, $issue)';
-}
-
-class TestExpectations {
- // Only create one copy of each Set<Expectation>.
- // We just use .toString as a key, so we may make a few
- // sets that only differ in their toString element order.
- static Map<String, Set<Expectation>> _cachedSets = {};
-
- Map<String, Set<Expectation>> _map;
- bool _preprocessed = false;
- Map<String, RegExp> _regExpCache;
- Map<String, List<RegExp>> _keyToRegExps;
-
- /**
- * Create a TestExpectations object. See the [expectations] method
- * for an explanation of matching.
- */
- TestExpectations() : _map = {};
-
- /**
- * Add a rule to the expectations.
- */
- void addRule(TestRule testRule, environment) {
- // Once we have started using the expectations we cannot add more
- // rules.
- if (_preprocessed) {
- throw "TestExpectations.addRule: cannot add more rules";
- }
- var names = testRule.expression.evaluate(environment);
- var expectations = names.map((name) => Expectation.byName(name));
- _map
- .putIfAbsent(testRule.name, () => new Set<Expectation>())
- .addAll(expectations);
- }
-
- /**
- * Compute the expectations for a test based on the filename.
- *
- * For every (key, expectation) pair. Match the key with the file
- * name. Return the union of the expectations for all the keys
- * that match.
- *
- * Normal matching splits the key and the filename into path
- * components and checks that the anchored regular expression
- * "^$keyComponent\$" matches the corresponding filename component.
- */
- Set<Expectation> expectations(String filename) {
- var result = new Set<Expectation>();
- var splitFilename = filename.split('/');
-
- // Create mapping from keys to list of RegExps once and for all.
- _preprocessForMatching();
-
- _map.forEach((key, Set<Expectation> expectations) {
- List<RegExp> regExps = _keyToRegExps[key];
- if (regExps.length > splitFilename.length) return;
- for (var i = 0; i < regExps.length; i++) {
- if (!regExps[i].hasMatch(splitFilename[i])) return;
- }
- // If all components of the status file key matches the filename
- // add the expectations to the result.
- result.addAll(expectations);
- });
-
- // If no expectations were found the expectation is that the test
- // passes.
- if (result.isEmpty) {
- result.add(Expectation.PASS);
- }
- return _cachedSets.putIfAbsent(result.toString(), () => result);
- }
-
- // Preprocess the expectations for matching against
- // filenames. Generate lists of regular expressions once and for all
- // for each key.
- void _preprocessForMatching() {
- if (_preprocessed) return;
-
- _keyToRegExps = {};
- _regExpCache = {};
-
- _map.forEach((key, expectations) {
- if (_keyToRegExps[key] != null) return;
- var splitKey = key.split('/');
- var regExps = new List<RegExp>(splitKey.length);
- for (var i = 0; i < splitKey.length; i++) {
- var component = splitKey[i];
- var regExp = _regExpCache[component];
- if (regExp == null) {
- var pattern = "^${splitKey[i]}\$".replaceAll('*', '.*');
- regExp = new RegExp(pattern);
- _regExpCache[component] = regExp;
- }
- regExps[i] = regExp;
- }
- _keyToRegExps[key] = regExps;
- });
-
- _regExpCache = null;
- _preprocessed = true;
- }
-}
« no previous file with comments | « tools/testing/dart/status_file.dart ('k') | tools/testing/dart/summary_report.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698