blob: 2494605a98c49ca7de982689209ee5046c32cf7b [file] [log] [blame]
// 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 'package:gardening/src/results/configuration_environment.dart';
import 'package:status_file/canonical_status_file.dart';
class StatusFiles {
Map<String, List<StatusSectionEntry>> _exactEntries = {};
Map<StatusSectionEntry, List<RegExp>> _wildcardEntries = {};
List<StatusSectionWithFile> _sections = [];
final List<StatusFile> statusFiles;
/// Constructs a [StatusFiles] from a list of status file paths.
static StatusFiles read(Iterable<String> files) {
var distinctFiles = new Set.from(files).toList();
return new StatusFiles(distinctFiles.map((file) {
return new StatusFile.read(file);
}).toList());
}
StatusFiles(this.statusFiles) {
for (var file in statusFiles) {
for (var section in file.sections) {
_sections.add(new StatusSectionWithFile(file, section));
for (StatusEntry entry
in section.entries.where((entry) => entry is StatusEntry)) {
var sectionEntry = new StatusSectionEntry(file, section, entry);
if (entry.path.contains("*")) {
_wildcardEntries[sectionEntry] = _processForMatching(entry.path);
} else {
_exactEntries.putIfAbsent(entry.path, () => []).add(sectionEntry);
}
}
}
}
}
/// Gets all section entries with test-expectations for a configuration
/// environment.
List<StatusSectionWithFile> sectionsForConfiguration(
ConfigurationEnvironment environment) {
return _sections.where((s) => s.section.isEnabled(environment)).toList();
}
/// Gets all section entries with test-expectations for a configuration
/// environment.
List<StatusSectionEntry> sectionsWithTestForConfiguration(
ConfigurationEnvironment environment, String testPath) {
return sectionsWithTest(testPath)
.where((entry) => entry.section.isEnabled(environment))
.toList();
}
/// Gets all section entries with test-expectations for a configuration
/// environment.
List<StatusSectionEntry> sectionsWithTest(String testPath) {
List<StatusSectionEntry> matchingEntries = <StatusSectionEntry>[];
if (_exactEntries.containsKey(testPath)) {
matchingEntries.addAll(_exactEntries[testPath]);
}
// Test if it is a multi test by matching finding the name of the test
// (either by the test name ending with _test/ or _t<nr>/ and cutting out
// the remaining, as long as it does not contain the word _test
RegExp isMultiTestMatcher = new RegExp(r"^((.*)_(test|t\d+))\/(.+)$");
Match isMultiTestMatch = isMultiTestMatcher.firstMatch(testPath);
if (isMultiTestMatch != null) {
String testFile = isMultiTestMatch.group(1);
if (_exactEntries.containsKey(testFile)) {
matchingEntries.addAll(_exactEntries[testFile]);
}
var multiTestParts = isMultiTestMatch.group(4).split('/');
for (var part in multiTestParts) {
testFile = "$testFile/$part";
if (_exactEntries.containsKey(testFile)) {
matchingEntries.addAll(_exactEntries[testFile]);
}
}
}
var parts = testPath.split('/');
_wildcardEntries.forEach((entry, regExps) {
if (regExps.length > parts.length) return;
for (var i = 0; i < regExps.length; i++) {
if (!regExps[i].hasMatch(parts[i])) return;
}
matchingEntries.add(entry);
});
return matchingEntries;
}
/// Processes the expectations for matching against filenames. Generates
/// lists of regular expressions once and for all for a key.
List<RegExp> _processForMatching(String key) {
return key
.split('/')
.map((part) => new RegExp("^${part}\$".replaceAll('*', '.*')))
.toList();
}
}
/// [StatusSectionEntry] is a result from looking up a test, and holds
/// information about the status file, the section and the specific entry.
class StatusSectionEntry {
final StatusFile statusFile;
final StatusSection section;
final StatusEntry entry;
StatusSectionEntry(this.statusFile, this.section, this.entry);
}
/// [StatusSectionWithFile] holds information about a section and the status
/// file it belongs to.
class StatusSectionWithFile {
final StatusFile statusFile;
final StatusSection section;
StatusSectionWithFile(this.statusFile, this.section);
}