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

Side by Side Diff: tools/testing/dart/test_suite.dart

Issue 841193003: cleanup to tools/testing/dart (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: one last bit Created 5 years, 11 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/testing/dart/test_runner.dart ('k') | tools/testing/dart/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Classes and methods for enumerating and preparing tests. 6 * Classes and methods for enumerating and preparing tests.
7 * 7 *
8 * This library includes: 8 * This library includes:
9 * 9 *
10 * - Creating tests by listing all the Dart files in certain directories, 10 * - Creating tests by listing all the Dart files in certain directories,
11 * and creating [TestCase]s for those files that meet the relevant criteria. 11 * and creating [TestCase]s for those files that meet the relevant criteria.
12 * - Preparing tests, including copying files and frameworks to temporary 12 * - Preparing tests, including copying files and frameworks to temporary
13 * directories, and computing the command line and arguments to be run. 13 * directories, and computing the command line and arguments to be run.
14 */ 14 */
15 library test_suite; 15 library test_suite;
16 16
17 import "dart:async"; 17 import 'dart:async';
18 import "dart:io"; 18 import 'dart:io';
19 import "drt_updater.dart";
20 import "html_test.dart" as htmlTest;
21 import "path.dart";
22 import "multitest.dart";
23 import "status_file_parser.dart";
24 import "test_runner.dart";
25 import "utils.dart";
26 import "http_server.dart" show PREFIX_BUILDDIR, PREFIX_DARTDIR;
27 19
28 import "compiler_configuration.dart" show 20 import 'compiler_configuration.dart' show CompilerConfiguration;
29 CommandArtifact, 21 import 'lib/browser_test.dart';
30 CompilerConfiguration; 22 import 'lib/command.dart';
31 23 import 'lib/drt_updater.dart';
32 import "runtime_configuration.dart" show 24 import 'lib/html_test.dart' as htmlTest;
33 RuntimeConfiguration; 25 import 'lib/http_server.dart' show PREFIX_BUILDDIR, PREFIX_DARTDIR;
34 26 import 'lib/multitest.dart';
35 import 'browser_test.dart'; 27 import 'lib/path.dart';
28 import 'lib/status_file_parser.dart';
29 import 'lib/summary_report.dart';
30 import 'lib/test_case.dart';
31 import 'lib/test_information.dart';
32 import 'lib/test_utils.dart';
33 import 'lib/utils.dart';
34 import 'runtime_configuration.dart' show CommandArtifact, RuntimeConfiguration;
36 35
37 36
38 RegExp multiHtmlTestGroupRegExp = new RegExp(r"\s*[^/]\s*group\('[^,']*"); 37 RegExp multiHtmlTestGroupRegExp = new RegExp(r"\s*[^/]\s*group\('[^,']*");
39 RegExp multiHtmlTestRegExp = new RegExp(r"useHtmlIndividualConfiguration()"); 38 RegExp multiHtmlTestRegExp = new RegExp(r"useHtmlIndividualConfiguration()");
40 // Require at least one non-space character before '///' 39 // Require at least one non-space character before '///'
41 RegExp multiTestRegExp = new RegExp(r"\S *" 40 RegExp multiTestRegExp = new RegExp(r"\S *"
42 r"/// \w+:(.*)"); 41 r"/// \w+:(.*)");
43 RegExp dartExtension = new RegExp(r'\.dart$');
44 42
45 /** 43 /**
46 * A simple function that tests [arg] and returns `true` or `false`. 44 * A simple function that tests [arg] and returns `true` or `false`.
47 */ 45 */
48 typedef bool Predicate<T>(T arg); 46 typedef bool Predicate<T>(T arg);
49 47
50 typedef void CreateTest(Path filePath,
51 Path originTestPath,
52 bool hasCompileError,
53 bool hasRuntimeError,
54 {bool isNegativeIfChecked,
55 bool hasCompileErrorIfChecked,
56 bool hasStaticWarning,
57 String multitestKey});
58
59 typedef void VoidFunction(); 48 typedef void VoidFunction();
60 49
61 /** 50 /**
62 * Calls [function] asynchronously. Returns a future that completes with the 51 * Calls [function] asynchronously. Returns a future that completes with the
63 * result of the function. If the function is `null`, returns a future that 52 * result of the function. If the function is `null`, returns a future that
64 * completes immediately with `null`. 53 * completes immediately with `null`.
65 */ 54 */
66 Future asynchronously(function()) { 55 Future asynchronously(function()) {
67 if (function == null) return new Future.value(null); 56 if (function == null) return new Future.value(null);
68 57
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 Map buildPubspecDependencyOverrides(Map packageDirectories) { 462 Map buildPubspecDependencyOverrides(Map packageDirectories) {
474 Map overrides = {}; 463 Map overrides = {};
475 packageDirectories.forEach((String packageName, String fullPath) { 464 packageDirectories.forEach((String packageName, String fullPath) {
476 overrides[packageName] = { 'path' : fullPath }; 465 overrides[packageName] = { 'path' : fullPath };
477 }); 466 });
478 return overrides; 467 return overrides;
479 } 468 }
480 469
481 } 470 }
482 471
483
484 Future<Iterable<String>> ccTestLister(String runnerPath) { 472 Future<Iterable<String>> ccTestLister(String runnerPath) {
485 return Process.run(runnerPath, ["--list"]).then((ProcessResult result) { 473 return Process.run(runnerPath, ["--list"]).then((ProcessResult result) {
486 if (result.exitCode != 0) { 474 if (result.exitCode != 0) {
487 throw "Failed to list tests: '$runnerPath --list'. " 475 throw "Failed to list tests: '$runnerPath --list'. "
488 "Process exited with ${result.exitCode}"; 476 "Process exited with ${result.exitCode}";
489 } 477 }
490 return result.stdout 478 return result.stdout
491 .split('\n') 479 .split('\n')
492 .map((line) => line.trim()) 480 .map((line) => line.trim())
493 .where((name) => name.length > 0); 481 .where((name) => name.length > 0);
494 }); 482 });
495 } 483 }
496 484
497
498 /** 485 /**
499 * A specialized [TestSuite] that runs tests written in C to unit test 486 * A specialized [TestSuite] that runs tests written in C to unit test
500 * the Dart virtual machine and its API. 487 * the Dart virtual machine and its API.
501 * 488 *
502 * The tests are compiled into a monolithic executable by the build step. 489 * The tests are compiled into a monolithic executable by the build step.
503 * The executable lists its tests when run with the --list command line flag. 490 * The executable lists its tests when run with the --list command line flag.
504 * Individual tests are run by specifying them on the command line. 491 * Individual tests are run by specifying them on the command line.
505 */ 492 */
506 class CCTestSuite extends TestSuite { 493 class CCTestSuite extends TestSuite {
507 final String testPrefix; 494 final String testPrefix;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 doTest = null; 547 doTest = null;
561 if (onDone != null) onDone(); 548 if (onDone != null) onDone();
562 }).catchError((error) { 549 }).catchError((error) {
563 print("Fatal error occured: $error"); 550 print("Fatal error occured: $error");
564 exit(1); 551 exit(1);
565 }); 552 });
566 }); 553 });
567 } 554 }
568 } 555 }
569 556
570
571 class TestInformation {
572 Path filePath;
573 Path originTestPath;
574 Map optionsFromFile;
575 bool hasCompileError;
576 bool hasRuntimeError;
577 bool isNegativeIfChecked;
578 bool hasCompileErrorIfChecked;
579 bool hasStaticWarning;
580 String multitestKey;
581
582 TestInformation(this.filePath, this.originTestPath, this.optionsFromFile,
583 this.hasCompileError, this.hasRuntimeError,
584 this.isNegativeIfChecked, this.hasCompileErrorIfChecked,
585 this.hasStaticWarning,
586 {this.multitestKey: ''}) {
587 assert(filePath.isAbsolute);
588 }
589 }
590
591
592 class HtmlTestInformation extends TestInformation {
593 List<String> expectedMessages;
594 List<String> scripts;
595
596 HtmlTestInformation(Path filePath, this.expectedMessages, this.scripts)
597 : super(filePath, filePath,
598 {'isMultitest': false, 'isMultiHtmlTest': false},
599 false, false, false, false, false) {}
600 }
601
602
603 /** 557 /**
604 * A standard [TestSuite] implementation that searches for tests in a 558 * A standard [TestSuite] implementation that searches for tests in a
605 * directory, and creates [TestCase]s that compile and/or run them. 559 * directory, and creates [TestCase]s that compile and/or run them.
606 */ 560 */
607 class StandardTestSuite extends TestSuite { 561 class StandardTestSuite extends TestSuite {
608 final Path suiteDir; 562 final Path suiteDir;
609 final List<String> statusFilePaths; 563 final List<String> statusFilePaths;
610 TestExpectations testExpectations; 564 TestExpectations testExpectations;
611 List<TestInformation> cachedTests; 565 List<TestInformation> cachedTests;
612 final Path dartDir; 566 final Path dartDir;
(...skipping 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 ReadTestExpectations(statusFiles, configuration).then((expectations) { 1963 ReadTestExpectations(statusFiles, configuration).then((expectations) {
2010 Future.wait([discoverPackagesInRepository(), 1964 Future.wait([discoverPackagesInRepository(),
2011 discoverSamplesInRepository()]).then((List results) { 1965 discoverSamplesInRepository()]).then((List results) {
2012 Map packageDirectories = results[0]; 1966 Map packageDirectories = results[0];
2013 Map sampleDirectories = results[1]; 1967 Map sampleDirectories = results[1];
2014 enqueueTestCases(packageDirectories, sampleDirectories, expectations); 1968 enqueueTestCases(packageDirectories, sampleDirectories, expectations);
2015 }); 1969 });
2016 }); 1970 });
2017 } 1971 }
2018 } 1972 }
2019
2020
2021 class LastModifiedCache {
2022 Map<String, DateTime> _cache = <String, DateTime>{};
2023
2024 /**
2025 * Returns the last modified date of the given [uri].
2026 *
2027 * The return value will be cached for future queries. If [uri] is a local
2028 * file, it's last modified [Date] will be returned. If the file does not
2029 * exist, null will be returned instead.
2030 * In case [uri] is not a local file, this method will always return
2031 * the current date.
2032 */
2033 DateTime getLastModified(Uri uri) {
2034 if (uri.scheme == "file") {
2035 if (_cache.containsKey(uri.path)) {
2036 return _cache[uri.path];
2037 }
2038 var file = new File(new Path(uri.path).toNativePath());
2039 _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null;
2040 return _cache[uri.path];
2041 }
2042 return new DateTime.now();
2043 }
2044 }
2045
2046
2047 class ExistsCache {
2048 Map<String, bool> _cache = <String, bool>{};
2049
2050 /**
2051 * Returns true if the file in [path] exists, false otherwise.
2052 *
2053 * The information will be cached.
2054 */
2055 bool doesFileExist(String path) {
2056 if (!_cache.containsKey(path)) {
2057 _cache[path] = new File(path).existsSync();
2058 }
2059 return _cache[path];
2060 }
2061 }
2062
2063
2064 class TestUtils {
2065 /**
2066 * Any script using TestUtils must set dartDirUri to a file:// URI
2067 * pointing to the root of the Dart checkout.
2068 */
2069 static setDartDirUri(uri) {
2070 dartDirUri = uri;
2071 dartDir = new Path(uri.toFilePath());
2072 }
2073 static Uri dartDirUri;
2074 static Path dartDir;
2075 static LastModifiedCache lastModifiedCache = new LastModifiedCache();
2076 static ExistsCache existsCache = new ExistsCache();
2077 static Path currentWorkingDirectory =
2078 new Path(Directory.current.path);
2079
2080 /**
2081 * Creates a directory using a [relativePath] to an existing
2082 * [base] directory if that [relativePath] does not already exist.
2083 */
2084 static Directory mkdirRecursive(Path base, Path relativePath) {
2085 if (relativePath.isAbsolute) {
2086 base = new Path('/');
2087 }
2088 Directory dir = new Directory(base.toNativePath());
2089 assert(dir.existsSync());
2090 var segments = relativePath.segments();
2091 for (String segment in segments) {
2092 base = base.append(segment);
2093 if (base.toString() == "/$segment" &&
2094 segment.length == 2 &&
2095 segment.endsWith(':')) {
2096 // Skip the directory creation for a path like "/E:".
2097 continue;
2098 }
2099 dir = new Directory(base.toNativePath());
2100 if (!dir.existsSync()) {
2101 dir.createSync();
2102 }
2103 assert(dir.existsSync());
2104 }
2105 return dir;
2106 }
2107
2108 /**
2109 * Copy a [source] file to a new place.
2110 * Assumes that the directory for [dest] already exists.
2111 */
2112 static Future copyFile(Path source, Path dest) {
2113 return new File(source.toNativePath()).openRead()
2114 .pipe(new File(dest.toNativePath()).openWrite());
2115 }
2116
2117 static Future copyDirectory(String source, String dest) {
2118 source = new Path(source).toNativePath();
2119 dest = new Path(dest).toNativePath();
2120
2121 var executable = 'cp';
2122 var args = ['-Rp', source, dest];
2123 if (Platform.operatingSystem == 'windows') {
2124 executable = 'xcopy';
2125 args = [source, dest, '/e', '/i'];
2126 }
2127 return Process.run(executable, args).then((ProcessResult result) {
2128 if (result.exitCode != 0) {
2129 throw new Exception("Failed to execute '$executable "
2130 "${args.join(' ')}'.");
2131 }
2132 });
2133 }
2134
2135 static Future deleteDirectory(String path) {
2136 // We are seeing issues with long path names on windows when
2137 // deleting them. Use the system tools to delete our long paths.
2138 // See issue 16264.
2139 if (Platform.operatingSystem == 'windows') {
2140 var native_path = new Path(path).toNativePath();
2141 // Running this in a shell sucks, but rmdir is not part of the standard
2142 // path.
2143 return Process.run('rmdir', ['/s', '/q', native_path], runInShell: true)
2144 .then((ProcessResult result) {
2145 if (result.exitCode != 0) {
2146 throw new Exception('Can\'t delete path $native_path. '
2147 'This path might be too long');
2148 }
2149 });
2150 } else {
2151 var dir = new Directory(path);
2152 return dir.delete(recursive: true);
2153 }
2154 }
2155
2156 static Path debugLogfile() {
2157 return new Path(".debug.log");
2158 }
2159
2160 static String flakyFileName() {
2161 // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout)
2162 // will be written to this file. This is useful for the debugging of
2163 // flaky tests.
2164 // When running on a built bot, the file can be made visible in the
2165 // waterfall UI.
2166 return ".flaky.log";
2167 }
2168
2169 static String testOutcomeFileName() {
2170 // If test.py was invoked with '--write-test-outcome-log it will write
2171 // test outcomes to this file.
2172 return ".test-outcome.log";
2173 }
2174
2175 static void ensureExists(String filename, Map configuration) {
2176 if (!configuration['list'] && !existsCache.doesFileExist(filename)) {
2177 throw "'$filename' does not exist";
2178 }
2179 }
2180
2181 static Path absolutePath(Path path) {
2182 if (!path.isAbsolute) {
2183 return currentWorkingDirectory.join(path);
2184 }
2185 return path;
2186 }
2187
2188 static String outputDir(Map configuration) {
2189 var result = '';
2190 var system = configuration['system'];
2191 if (system == 'linux') {
2192 result = 'out/';
2193 } else if (system == 'macos') {
2194 result = 'xcodebuild/';
2195 } else if (system == 'windows') {
2196 result = 'build/';
2197 }
2198 return result;
2199 }
2200
2201 static List<String> standardOptions(Map configuration) {
2202 List args = ["--ignore-unrecognized-flags"];
2203 if (configuration["checked"]) {
2204 args.add('--enable_asserts');
2205 args.add("--enable_type_checks");
2206 }
2207 String compiler = configuration["compiler"];
2208 if (compiler == "dart2js" || compiler == "dart2dart") {
2209 args = [];
2210 if (configuration["checked"]) {
2211 args.add('--enable-checked-mode');
2212 }
2213 // args.add("--verbose");
2214 if (!isBrowserRuntime(configuration['runtime'])) {
2215 args.add("--allow-mock-compilation");
2216 args.add("--categories=all");
2217 }
2218 }
2219 if ((compiler == "dart2js" || compiler == "dart2dart") &&
2220 configuration["minified"]) {
2221 args.add("--minify");
2222 }
2223 if (compiler == "dartanalyzer" || compiler == "dart2analyzer") {
2224 args.add("--show-package-warnings");
2225 args.add("--enable-async");
2226 }
2227 return args;
2228 }
2229
2230 static bool isBrowserRuntime(String runtime) {
2231 const BROWSERS = const [
2232 'drt',
2233 'dartium',
2234 'ie9',
2235 'ie10',
2236 'ie11',
2237 'safari',
2238 'opera',
2239 'chrome',
2240 'ff',
2241 'chromeOnAndroid',
2242 'safarimobilesim',
2243 'ContentShellOnAndroid',
2244 'DartiumOnAndroid'
2245 ];
2246 return BROWSERS.contains(runtime);
2247 }
2248
2249 static bool isJsCommandLineRuntime(String runtime) =>
2250 const ['d8', 'jsshell'].contains(runtime);
2251
2252 static bool isCommandLineAnalyzer(String compiler) =>
2253 compiler == 'dartanalyzer' || compiler == 'dart2analyzer';
2254
2255 static String buildDir(Map configuration) {
2256 // FIXME(kustermann,ricow): Our code assumes that the returned 'buildDir'
2257 // is relative to the current working directory.
2258 // Thus, if we pass in an absolute path (e.g. '--build-directory=/tmp/out')
2259 // we get into trouble.
2260 if (configuration['build_directory'] != '') {
2261 return configuration['build_directory'];
2262 }
2263
2264 return "${outputDir(configuration)}${configurationDir(configuration)}";
2265 }
2266
2267 static getValidOutputDir(Map configuration, String mode, String arch) {
2268 // We allow our code to have been cross compiled, i.e., that there
2269 // is an X in front of the arch. We don't allow both a cross compiled
2270 // and a normal version to be present (except if you specifically pass
2271 // in the build_directory).
2272 var normal = '$mode$arch';
2273 var cross = '${mode}X$arch';
2274 var outDir = outputDir(configuration);
2275 var normalDir = new Directory(new Path('$outDir$normal').toNativePath());
2276 var crossDir = new Directory(new Path('$outDir$cross').toNativePath());
2277 if (normalDir.existsSync() && crossDir.existsSync()) {
2278 throw "You can't have both $normalDir and $crossDir, we don't know which"
2279 " binary to use";
2280 }
2281 if (crossDir.existsSync()) {
2282 return cross;
2283 }
2284 return normal;
2285 }
2286
2287 static String configurationDir(Map configuration) {
2288 // For regular dart checkouts, the configDir by default is mode+arch.
2289 // For Dartium, the configDir by default is mode (as defined by the Chrome
2290 // build setup). We can detect this because in the dartium checkout, the
2291 // "output" directory is a sibling of the dart directory instead of a child.
2292 var mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release';
2293 var arch = configuration['arch'].toUpperCase();
2294 if (currentWorkingDirectory != dartDir) {
2295 return getValidOutputDir(configuration, mode, arch);
2296 } else {
2297 return mode;
2298 }
2299 }
2300
2301 /**
2302 * Returns the path to the dart binary checked into the repo, used for
2303 * bootstrapping test.dart.
2304 */
2305 static Path get dartTestExecutable {
2306 var path = '$dartDir/tools/testing/bin/'
2307 '${Platform.operatingSystem}/dart';
2308 if (Platform.operatingSystem == 'windows') {
2309 path = '$path.exe';
2310 }
2311 return new Path(path);
2312 }
2313
2314 /**
2315 * Gets extra options under [key] passed to the testing script.
2316 */
2317 static List<String> getExtraOptions(Map configuration, String key) {
2318 if (configuration[key] == null) return <String>[];
2319 return configuration[key]
2320 .split(" ")
2321 .map((s) => s.trim())
2322 .where((s) => s.isNotEmpty)
2323 .toList();
2324 }
2325
2326 /**
2327 * Gets extra vm options passed to the testing script.
2328 */
2329 static List<String> getExtraVmOptions(Map configuration) =>
2330 getExtraOptions(configuration, 'vm_options');
2331
2332 static String getShortName(String path) {
2333 final PATH_REPLACEMENTS = const {
2334 "pkg_polymer_e2e_test_bad_import_test": "polymer_bi",
2335 "pkg_polymer_e2e_test_canonicalization_test": "polymer_c16n",
2336 "pkg_polymer_e2e_test_experimental_boot_test": "polymer_boot",
2337 "pkg_polymer_e2e_test_good_import_test": "polymer_gi",
2338 "tests_co19_src_Language_12_Expressions_14_Function_Invocation_":
2339 "co19_fn_invoke_",
2340 "tests_co19_src_LayoutTests_fast_css_getComputedStyle_getComputedStyle-":
2341 "co19_css_getComputedStyle_",
2342 "tests_co19_src_LayoutTests_fast_dom_Document_CaretRangeFromPoint_"
2343 "caretRangeFromPoint-": "co19_caretrangefrompoint_",
2344 "tests_co19_src_LayoutTests_fast_dom_Document_CaretRangeFromPoint_"
2345 "hittest-relative-to-viewport_": "co19_caretrange_hittest_",
2346 "tests_co19_src_LayoutTests_fast_dom_HTMLLinkElement_link-onerror-"
2347 "stylesheet-with-": "co19_dom_link-",
2348 "tests_co19_src_LayoutTests_fast_dom_": "co19_dom",
2349 "tests_co19_src_LayoutTests_fast_canvas_webgl": "co19_canvas_webgl",
2350 "tests_co19_src_LibTest_core_AbstractClassInstantiationError_"
2351 "AbstractClassInstantiationError_": "co19_abstract_class_",
2352 "tests_co19_src_LibTest_core_IntegerDivisionByZeroException_"
2353 "IntegerDivisionByZeroException_": "co19_division_by_zero",
2354 "tests_co19_src_WebPlatformTest_html_dom_documents_dom-tree-accessors_":
2355 "co19_dom_accessors_",
2356 "tests_co19_src_WebPlatformTest_html_semantics_embedded-content_"
2357 "media-elements_": "co19_media_elements",
2358 "tests_co19_src_WebPlatformTest_html_semantics_": "co19_semantics_",
2359
2360 "tests_co19_src_WebPlatformTest_html-templates_additions-to-"
2361 "the-steps-to-clone-a-node_": "co19_htmltemplates_clone_",
2362 "tests_co19_src_WebPlatformTest_html-templates_definitions_"
2363 "template-contents-owner": "co19_htmltemplates_contents",
2364 "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
2365 "templates_additions-to-": "co19_htmltemplates_add_",
2366 "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
2367 "templates_appending-to-a-template_": "co19_htmltemplates_append_",
2368 "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
2369 "templates_clearing-the-stack-back-to-a-given-context_":
2370 "co19_htmltemplates_clearstack_",
2371 "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
2372 "templates_creating-an-element-for-the-token_":
2373 "co19_htmltemplates_create_",
2374 "tests_co19_src_WebPlatformTest_html-templates_template-element"
2375 "_template-": "co19_htmltemplates_element-",
2376 "tests_co19_src_WebPlatformTest_html-templates_": "co19_htmltemplate_",
2377
2378 "tests_co19_src_WebPlatformTest_shadow-dom_shadow-trees_":
2379 "co19_shadow-trees_",
2380 "tests_co19_src_WebPlatformTest_shadow-dom_elements-and-dom-objects_":
2381 "co19_shadowdom_",
2382 "tests_co19_src_WebPlatformTest_shadow-dom_html-elements-in-"
2383 "shadow-trees_": "co19_shadow_html_",
2384 "tests_co19_src_WebPlatformTest_html_webappapis_system-state-and-"
2385 "capabilities_the-navigator-object": "co19_webappapis_navigator_",
2386 "tests_co19_src_WebPlatformTest_DOMEvents_approved_": "co19_dom_approved_"
2387 };
2388
2389 // Some tests are already in [build_dir]/generated_tests.
2390 String GEN_TESTS = 'generated_tests/';
2391 if (path.contains(GEN_TESTS)) {
2392 int index = path.indexOf(GEN_TESTS) + GEN_TESTS.length;
2393 path = 'multitest/${path.substring(index)}';
2394 }
2395 path = path.replaceAll('/', '_');
2396 final int WINDOWS_SHORTEN_PATH_LIMIT = 58;
2397 if (Platform.operatingSystem == 'windows' &&
2398 path.length > WINDOWS_SHORTEN_PATH_LIMIT) {
2399 for (var key in PATH_REPLACEMENTS.keys) {
2400 if (path.startsWith(key)) {
2401 path = path.replaceFirst(key, PATH_REPLACEMENTS[key]);
2402 break;
2403 }
2404 }
2405 }
2406 return path;
2407 }
2408 }
2409
2410
2411 class SummaryReport {
2412 static int total = 0;
2413 static int skipped = 0;
2414 static int skippedByDesign = 0;
2415 static int noCrash = 0;
2416 static int flakyCrash = 0;
2417 static int pass = 0;
2418 static int failOk = 0;
2419 static int fail = 0;
2420 static int crash = 0;
2421 static int timeout = 0;
2422 static int compileErrorSkip = 0;
2423
2424 static List<TestCase> nonStandardTestCases = [];
2425
2426 static void add(TestCase testCase) {
2427 var expectations = testCase.expectedOutcomes;
2428
2429 bool containsFail = expectations.any(
2430 (expectation) => expectation.canBeOutcomeOf(Expectation.FAIL));
2431 bool containsPass = expectations.contains(Expectation.PASS);
2432 bool containsSkip = expectations.contains(Expectation.SKIP);
2433 bool containsSkipByDesign =
2434 expectations.contains(Expectation.SKIP_BY_DESIGN);
2435 bool containsCrash = expectations.contains(Expectation.CRASH);
2436 bool containsOK = expectations.contains(Expectation.OK);
2437 bool containsSlow = expectations.contains(Expectation.SLOW);
2438 bool containsTimeout = expectations.contains(Expectation.TIMEOUT);
2439
2440 ++total;
2441 if (containsSkip) {
2442 ++skipped;
2443 } else if (containsSkipByDesign) {
2444 ++skipped;
2445 ++skippedByDesign;
2446 } else {
2447 // We don't do if-else below because the buckets should be exclusive.
2448 // We keep a count around to guarantee that
2449 int markers = 0;
2450
2451 // Counts the number of flaky tests.
2452 if (containsFail && containsPass && !containsCrash && !containsOK) {
2453 ++noCrash;
2454 ++markers;
2455 }
2456 if (containsCrash && !containsOK && expectations.length > 1) {
2457 ++flakyCrash;
2458 ++markers;
2459 }
2460 if ((containsPass && expectations.length == 1) ||
2461 (containsPass && containsSlow && expectations.length == 2)) {
2462 ++pass;
2463 ++markers;
2464 }
2465 if (containsFail && containsOK) {
2466 ++failOk;
2467 ++markers;
2468 }
2469 if ((containsFail && expectations.length == 1) ||
2470 (containsFail && containsSlow && expectations.length == 2)) {
2471 ++fail;
2472 ++markers;
2473 }
2474 if ((containsCrash && expectations.length == 1) ||
2475 (containsCrash && containsSlow && expectations.length == 2)) {
2476 ++crash;
2477 ++markers;
2478 }
2479 if (containsTimeout && expectations.length == 1) {
2480 ++timeout;
2481 ++markers;
2482 }
2483 if (markers != 1) {
2484 nonStandardTestCases.add(testCase);
2485 }
2486 }
2487 }
2488
2489 static void addCompileErrorSkipTest() {
2490 total++;
2491 compileErrorSkip++;
2492 }
2493
2494 static void printReport() {
2495 if (total == 0) return;
2496 var bogus = nonStandardTestCases.length;
2497 String report = """Total: $total tests
2498 * $skipped tests will be skipped ($skippedByDesign skipped by design)
2499 * $noCrash tests are expected to be flaky but not crash
2500 * $flakyCrash tests are expected to flaky crash
2501 * $pass tests are expected to pass
2502 * $failOk tests are expected to fail that we won't fix
2503 * $fail tests are expected to fail that we should fix
2504 * $crash tests are expected to crash that we should fix
2505 * $timeout tests are allowed to timeout
2506 * $compileErrorSkip tests are skipped on browsers due to compile-time error
2507 * $bogus could not be categorized or are in multiple categories
2508 """;
2509 print(report);
2510 }
2511 }
OLDNEW
« no previous file with comments | « tools/testing/dart/test_runner.dart ('k') | tools/testing/dart/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698