| Index: tools/testing/dart/expectation_set.dart
|
| diff --git a/tools/testing/dart/expectation_set.dart b/tools/testing/dart/expectation_set.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f7d135f98beceabc9b03ced89e93080ddea90282
|
| --- /dev/null
|
| +++ b/tools/testing/dart/expectation_set.dart
|
| @@ -0,0 +1,118 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +import 'expectation.dart';
|
| +import 'status_file.dart';
|
| +
|
| +/// Tracks the [Expectation]s associated with a set of file paths.
|
| +///
|
| +/// For any given file path, returns the expected test results for that file.
|
| +/// A set can be loaded from a collection of status files. A file path may
|
| +/// exist in multiple files (or even multiple sections within the file). When
|
| +/// that happens, all of the expectations of every entry are combined.
|
| +class ExpectationSet {
|
| + /// Reads the expectations defined by the status files at [statusFilePaths]
|
| + /// given [environment].
|
| + static ExpectationSet read(
|
| + List<String> statusFilePaths, Map<String, dynamic> environment) {
|
| + var expectations = new ExpectationSet._();
|
| + for (var path in statusFilePaths) {
|
| + var file = new StatusFile.read(path);
|
| + for (var section in file.sections) {
|
| + if (section.isEnabled(environment)) {
|
| + for (var entry in section.entries) {
|
| + expectations.addEntry(entry);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return expectations;
|
| + }
|
| +
|
| + // 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 = {};
|
| + Map<String, List<RegExp>> _keyToRegExps;
|
| +
|
| + /// Create a TestExpectations object. See the [expectations] method
|
| + /// for an explanation of matching.
|
| + ExpectationSet._();
|
| +
|
| + /// Add [entry] to the set of expectations.
|
| + void addEntry(StatusEntry entry) {
|
| + // Once we have started using the expectations we cannot add more
|
| + // rules.
|
| + if (_keyToRegExps != null) {
|
| + throw new StateError("Cannot add entries after it is already in use.");
|
| + }
|
| +
|
| + _map
|
| + .putIfAbsent(entry.path, () => new Set<Expectation>())
|
| + .addAll(entry.expectations);
|
| + }
|
| +
|
| + /// Get the expectations for the test at [path].
|
| + ///
|
| + /// For every (key, expectation) pair, matches the key with the file name.
|
| + /// Returns 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 path) {
|
| + var result = new Set<Expectation>();
|
| + var parts = path.split('/');
|
| +
|
| + // Create mapping from keys to list of RegExps once and for all.
|
| + _preprocessForMatching();
|
| +
|
| + _map.forEach((key, expectations) {
|
| + var regExps = _keyToRegExps[key];
|
| + if (regExps.length > parts.length) return;
|
| +
|
| + for (var i = 0; i < regExps.length; i++) {
|
| + if (!regExps[i].hasMatch(parts[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);
|
| + }
|
| +
|
| + /// Preprocesses the expectations for matching against filenames. Generates
|
| + /// lists of regular expressions once and for all for each key.
|
| + void _preprocessForMatching() {
|
| + if (_keyToRegExps != null) return;
|
| +
|
| + _keyToRegExps = {};
|
| + var regExpCache = <String, RegExp>{};
|
| +
|
| + _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.putIfAbsent(component,
|
| + () => new RegExp("^${splitKey[i]}\$".replaceAll('*', '.*')));
|
| + regExps[i] = regExp;
|
| + }
|
| +
|
| + _keyToRegExps[key] = regExps;
|
| + });
|
| + }
|
| +}
|
|
|