| 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
|
| index 5f6d8bbd7cac34271179f35500f96cf7ce328fd8..bd8e9f7287559ed5001cb15f78fc1c351bf4d185 100644
|
| --- a/tools/testing/dart/status_file_parser.dart
|
| +++ b/tools/testing/dart/status_file_parser.dart
|
| @@ -42,19 +42,19 @@ String getFilename(String path) =>
|
| String getDirname(String path) =>
|
| new Directory(path).existsSync() ? path : '../$path';
|
|
|
| -TestExpectationsMap ReadTestExpectations(String statusFilePath, environment) {
|
| +void ReadTestExpectationsInto(TestExpectations expectations,
|
| + String statusFilePath,
|
| + environment) {
|
| List<Section> sections = new List<Section>();
|
| ReadConfigurationInto(statusFilePath, sections);
|
|
|
| - TestExpectationsMap map = new TestExpectationsMap();
|
| for (Section section in sections) {
|
| if (section.isEnabled(environment)) {
|
| for (var rule in section.testRules) {
|
| - map.addTest(rule, environment);
|
| + expectations.addRule(rule, environment);
|
| }
|
| }
|
| }
|
| - return map;
|
| }
|
|
|
| void ReadConfigurationInto(path, sections) {
|
| @@ -72,7 +72,7 @@ void ReadConfigurationInto(path, sections) {
|
| Match match = StripComment.firstMatch(line);
|
| line = (match == null) ? "" : match[0];
|
| line = line.trim();
|
| - if (line == "") continue;
|
| + if (line.isEmpty()) continue;
|
|
|
| match = HeaderPattern.firstMatch(line);
|
| if (match != null) {
|
| @@ -117,17 +117,126 @@ class TestRule {
|
| }
|
|
|
|
|
| -class TestExpectationsMap {
|
| - Map<String, Set<String>> map;
|
| +class TestExpectations {
|
| + bool _complexMatching;
|
| + Map _map;
|
| + bool _preprocessed = false;
|
| + Map _regExpCache;
|
| + Map _keyToRegExps;
|
| +
|
| + /**
|
| + * Create a TestExpectations object. Optionally specify
|
| + * complexMatching behavior. See the [expectations] method
|
| + * for an explanation of matching.
|
| + */
|
| + TestExpectations([bool complexMatching = false])
|
| + : _complexMatching = complexMatching,
|
| + _map = new Map();
|
| +
|
| + /**
|
| + * Add a rule to the expectations.
|
| + */
|
| + void addRule(testRule, environment) {
|
| + // Once we have started using the expectations we cannot add more
|
| + // rules.
|
| + if (_preprocessed) {
|
| + throw "TestExpectations.addRule: cannot add more rules";
|
| + }
|
| + var values = testRule.expression.evaluate(environment);
|
| + _map.putIfAbsent(testRule.name, () => new Set()).addAll(values);
|
| + }
|
| +
|
| + /**
|
| + * 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.
|
| + *
|
| + * If Complex matching is required the last filename component is
|
| + * translated into multiple components. If the last filename
|
| + * component starts with the second-to-last filename component that
|
| + * part is removed from the last filename component. Then the last
|
| + * component is split into more components at '_'s.
|
| + *
|
| + * Examples of complext filename component splits:
|
| + *
|
| + * a/b/c/d_e_f/d_e_f_A01_t01 -> ['a', 'b', 'c', 'd_e_f', 'A01', 't01']
|
| + * a/b/c/d_e_f_A01_t01 -> ['a', 'b', 'c', 'd', 'e', 'f', 'A01', 't01']
|
| + */
|
| + Set<String> expectations(String filename) {
|
| + var result = new Set();
|
| + var splitFilename = filename.split(new Platform().pathSeparator());
|
| +
|
| + // If complex matching is required split the last filename
|
| + // component at '_'. Additionally, remove the prefix of the last
|
| + // component if it is identical to the second-to-last component.
|
| + if (_complexMatching && splitFilename.length >= 2) {
|
| + var last = splitFilename.removeLast();
|
| + var secondToLast = splitFilename.last();
|
| + if (last.startsWith(secondToLast)) {
|
| + last = last.substring(secondToLast.length);
|
| + }
|
| + last.split('_').forEach((component) {
|
| + if (!component.isEmpty()) {
|
| + splitFilename.add(component);
|
| + }
|
| + });
|
| + }
|
|
|
| - TestExpectationsMap() : map = new Map<String, Set<String>>();
|
| + // Create mapping from keys to list of RegExps once and for all.
|
| + _preprocessForMatching();
|
|
|
| - void addTest(testRule, environment) {
|
| - map[testRule.name] = testRule.expression.evaluate(environment);
|
| + _map.forEach((key, expectation) {
|
| + List 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(expectation);
|
| + });
|
| +
|
| + // If no expectations were found the expectation is that the test
|
| + // passes.
|
| + if (result.isEmpty()) {
|
| + result.add(PASS);
|
| + }
|
| + return result;
|
| }
|
|
|
| - Set<String> expectations(String filename) {
|
| - var result = map[filename];
|
| - return result != null ? result : new Set.from([PASS]);
|
| + // 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 = new Map();
|
| + _regExpCache = new Map();
|
| +
|
| + _map.forEach((key, expectations) {
|
| + if (_keyToRegExps[key] != null) return;
|
| + var splitKey = key.split('/');
|
| + var regExps = new List(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;
|
| }
|
| }
|
|
|