Chromium Code Reviews| Index: tools/gardening/lib/status_summary.dart |
| diff --git a/tools/gardening/lib/status_summary.dart b/tools/gardening/lib/status_summary.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..97c6bcd8e484aba64e33579e49bf53058454d207 |
| --- /dev/null |
| +++ b/tools/gardening/lib/status_summary.dart |
| @@ -0,0 +1,110 @@ |
| +// 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. |
| + |
| +/// Collects the configurations for all status files in the 'tests' folder that |
| +/// mention one of the test names given as argument. |
| + |
| +import 'dart:async'; |
| +import 'dart:math' hide log; |
| +import 'dart:io'; |
| + |
| +import 'src/util.dart'; |
| + |
| +main(List<String> args) async { |
| + if (args.length == 0) { |
| + print('Usage: status_summary <test-name1> [<test-name2> ...]'); |
| + exit(1); |
| + } |
| + int maxStatusWidth = 0; |
| + int maxConfigWidth = 0; |
| + |
| + List<Uri> statusFiles = await findStatusFiles('tests'); |
| + Map<String, List<StatusFile>> statusMap = <String, List<StatusFile>>{}; |
| + for (Uri uri in statusFiles) { |
| + Map<String, StatusFile> currentMap = <String, StatusFile>{}; |
| + log('Scanning $uri'); |
| + String currentConfig = ''; |
| + for (String line in new File.fromUri(uri).readAsLinesSync()) { |
| + if (line.startsWith('[')) { |
| + currentConfig = line; |
| + } else { |
| + int colonIndex = line.indexOf(':'); |
| + if (colonIndex != -1) { |
| + String testName = line.substring(0, colonIndex).trim(); |
| + int hashIndex = line.indexOf('#', colonIndex + 1); |
| + String status; |
| + String comment; |
| + if (hashIndex != -1) { |
| + status = line.substring(colonIndex + 1, hashIndex).trim(); |
| + comment = line.substring(hashIndex + 1).trim(); |
| + } else { |
| + status = line.substring(colonIndex + 1).trim(); |
| + comment = ''; |
| + } |
| + |
| + for (String arg in args) { |
| + if (testName.contains(arg) || arg.contains(testName)) { |
|
karlklose
2017/03/15 14:06:25
Use startsWith like above?
Johnni Winther
2017/03/15 14:32:17
That wouldn't support test names that include the
|
| + StatusFile statusFile = |
| + currentMap.putIfAbsent(testName, () => new StatusFile(uri)); |
| + statusFile.entries |
| + .add(new StatusEntry(currentConfig, status, comment)); |
| + |
| + maxStatusWidth = max(maxStatusWidth, status.length); |
| + maxConfigWidth = max(maxConfigWidth, currentConfig.length); |
| + } |
| + } |
| + } |
| + } |
| + } |
| + currentMap.forEach((String testName, StatusFile configFile) { |
| + statusMap.putIfAbsent(testName, () => <StatusFile>[]).add(configFile); |
| + }); |
| + } |
| + statusMap.forEach((String arg, List<StatusFile> statusFiles) { |
| + print('$arg'); |
| + for (StatusFile statusFile in statusFiles) { |
| + print(' ${statusFile.uri}'); |
| + statusFile.entries.forEach((StatusEntry entry) { |
| + print(' ${padRight(entry.status, maxStatusWidth)}' |
| + ' ${padRight(entry.config, maxConfigWidth)} ${entry.comment}'); |
| + }); |
| + } |
| + }); |
| +} |
| + |
| +/// Returns the [Uri]s for all `.status` files in [path] and subdirectories. |
| +Future<List<Uri>> findStatusFiles(String path) async { |
| + List<Uri> statusFiles = <Uri>[]; |
| + await for (FileSystemEntity entity |
| + in new Directory(path).list(recursive: true)) { |
| + if (entity.path.endsWith('.status')) { |
| + statusFiles.add(entity.uri); |
| + } |
| + } |
| + return statusFiles; |
| +} |
| + |
| +/// The entries collected for a single status file. |
| +class StatusFile { |
| + final Uri uri; |
| + final List<StatusEntry> entries = <StatusEntry>[]; |
| + |
| + StatusFile(this.uri); |
| +} |
| + |
| +/// A single entry in a status file. |
| +class StatusEntry { |
| + /// The preceding config line, i.e. `[...]` line that contained this entry. |
|
karlklose
2017/03/15 14:06:25
Add that it can be null (if it did not encounter a
Johnni Winther
2017/03/15 14:32:17
It's will empty in that case. Added.
|
| + final String config; |
| + |
| + /// The status of the entry, e.g. `Pass, Slow`. |
| + final String status; |
| + |
| + /// The comment after the status, if any. |
| + final String comment; |
| + |
| + StatusEntry(this.config, this.status, this.comment); |
| + |
| + String toString() => '$status $config $comment'; |
| +} |