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

Unified Diff: tools/testing/dart/lib/test_utils.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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/testing/dart/lib/test_progress.dart ('k') | tools/testing/dart/lib/utils.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/testing/dart/lib/test_utils.dart
diff --git a/tools/testing/dart/lib/test_utils.dart b/tools/testing/dart/lib/test_utils.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0a1108342b13f2a8df6d16edd4b48552dc53ef22
--- /dev/null
+++ b/tools/testing/dart/lib/test_utils.dart
@@ -0,0 +1,395 @@
+library test_utils;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'path.dart';
+
+class TestUtils {
+ /**
+ * Any script using TestUtils must set dartDirUri to a file:// URI
+ * pointing to the root of the Dart checkout.
+ */
+ static setDartDirUri(uri) {
+ dartDirUri = uri;
+ dartDir = new Path(uri.toFilePath());
+ }
+ static Uri dartDirUri;
+ static Path dartDir;
+ static LastModifiedCache lastModifiedCache = new LastModifiedCache();
+ static ExistsCache existsCache = new ExistsCache();
+ static Path currentWorkingDirectory =
+ new Path(Directory.current.path);
+
+ /**
+ * Creates a directory using a [relativePath] to an existing
+ * [base] directory if that [relativePath] does not already exist.
+ */
+ static Directory mkdirRecursive(Path base, Path relativePath) {
+ if (relativePath.isAbsolute) {
+ base = new Path('/');
+ }
+ Directory dir = new Directory(base.toNativePath());
+ assert(dir.existsSync());
+ var segments = relativePath.segments();
+ for (String segment in segments) {
+ base = base.append(segment);
+ if (base.toString() == "/$segment" &&
+ segment.length == 2 &&
+ segment.endsWith(':')) {
+ // Skip the directory creation for a path like "/E:".
+ continue;
+ }
+ dir = new Directory(base.toNativePath());
+ if (!dir.existsSync()) {
+ dir.createSync();
+ }
+ assert(dir.existsSync());
+ }
+ return dir;
+ }
+
+ /**
+ * Copy a [source] file to a new place.
+ * Assumes that the directory for [dest] already exists.
+ */
+ static Future copyFile(Path source, Path dest) {
+ return new File(source.toNativePath()).openRead()
+ .pipe(new File(dest.toNativePath()).openWrite());
+ }
+
+ static Future copyDirectory(String source, String dest) {
+ source = new Path(source).toNativePath();
+ dest = new Path(dest).toNativePath();
+
+ var executable = 'cp';
+ var args = ['-Rp', source, dest];
+ if (Platform.operatingSystem == 'windows') {
+ executable = 'xcopy';
+ args = [source, dest, '/e', '/i'];
+ }
+ return Process.run(executable, args).then((ProcessResult result) {
+ if (result.exitCode != 0) {
+ throw new Exception("Failed to execute '$executable "
+ "${args.join(' ')}'.");
+ }
+ });
+ }
+
+ static Future deleteDirectory(String path) {
+ // We are seeing issues with long path names on windows when
+ // deleting them. Use the system tools to delete our long paths.
+ // See issue 16264.
+ if (Platform.operatingSystem == 'windows') {
+ var native_path = new Path(path).toNativePath();
+ // Running this in a shell sucks, but rmdir is not part of the standard
+ // path.
+ return Process.run('rmdir', ['/s', '/q', native_path], runInShell: true)
+ .then((ProcessResult result) {
+ if (result.exitCode != 0) {
+ throw new Exception('Can\'t delete path $native_path. '
+ 'This path might be too long');
+ }
+ });
+ } else {
+ var dir = new Directory(path);
+ return dir.delete(recursive: true);
+ }
+ }
+
+ static Path debugLogfile() {
+ return new Path(".debug.log");
+ }
+
+ static String flakyFileName() {
+ // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout)
+ // will be written to this file. This is useful for the debugging of
+ // flaky tests.
+ // When running on a built bot, the file can be made visible in the
+ // waterfall UI.
+ return ".flaky.log";
+ }
+
+ static String testOutcomeFileName() {
+ // If test.py was invoked with '--write-test-outcome-log it will write
+ // test outcomes to this file.
+ return ".test-outcome.log";
+ }
+
+ static void ensureExists(String filename, Map configuration) {
+ if (!configuration['list'] && !existsCache.doesFileExist(filename)) {
+ throw "'$filename' does not exist";
+ }
+ }
+
+ static Path absolutePath(Path path) {
+ if (!path.isAbsolute) {
+ return currentWorkingDirectory.join(path);
+ }
+ return path;
+ }
+
+ static String outputDir(Map configuration) {
+ var result = '';
+ var system = configuration['system'];
+ if (system == 'linux') {
+ result = 'out/';
+ } else if (system == 'macos') {
+ result = 'xcodebuild/';
+ } else if (system == 'windows') {
+ result = 'build/';
+ }
+ return result;
+ }
+
+ static List<String> standardOptions(Map configuration) {
+ List args = ["--ignore-unrecognized-flags"];
+ if (configuration["checked"]) {
+ args.add('--enable_asserts');
+ args.add("--enable_type_checks");
+ }
+ String compiler = configuration["compiler"];
+ if (compiler == "dart2js" || compiler == "dart2dart") {
+ args = [];
+ if (configuration["checked"]) {
+ args.add('--enable-checked-mode');
+ }
+ // args.add("--verbose");
+ if (!isBrowserRuntime(configuration['runtime'])) {
+ args.add("--allow-mock-compilation");
+ args.add("--categories=all");
+ }
+ }
+ if ((compiler == "dart2js" || compiler == "dart2dart") &&
+ configuration["minified"]) {
+ args.add("--minify");
+ }
+ if (compiler == "dartanalyzer" || compiler == "dart2analyzer") {
+ args.add("--show-package-warnings");
+ args.add("--enable-async");
+ }
+ return args;
+ }
+
+ static bool isBrowserRuntime(String runtime) {
+ const BROWSERS = const [
+ 'drt',
+ 'dartium',
+ 'ie9',
+ 'ie10',
+ 'ie11',
+ 'safari',
+ 'opera',
+ 'chrome',
+ 'ff',
+ 'chromeOnAndroid',
+ 'safarimobilesim',
+ 'ContentShellOnAndroid',
+ 'DartiumOnAndroid'
+ ];
+ return BROWSERS.contains(runtime);
+ }
+
+ static bool isJsCommandLineRuntime(String runtime) =>
+ const ['d8', 'jsshell'].contains(runtime);
+
+ static bool isCommandLineAnalyzer(String compiler) =>
+ compiler == 'dartanalyzer' || compiler == 'dart2analyzer';
+
+ static String buildDir(Map configuration) {
+ // FIXME(kustermann,ricow): Our code assumes that the returned 'buildDir'
+ // is relative to the current working directory.
+ // Thus, if we pass in an absolute path (e.g. '--build-directory=/tmp/out')
+ // we get into trouble.
+ if (configuration['build_directory'] != '') {
+ return configuration['build_directory'];
+ }
+
+ return "${outputDir(configuration)}${configurationDir(configuration)}";
+ }
+
+ static getValidOutputDir(Map configuration, String mode, String arch) {
+ // We allow our code to have been cross compiled, i.e., that there
+ // is an X in front of the arch. We don't allow both a cross compiled
+ // and a normal version to be present (except if you specifically pass
+ // in the build_directory).
+ var normal = '$mode$arch';
+ var cross = '${mode}X$arch';
+ var outDir = outputDir(configuration);
+ var normalDir = new Directory(new Path('$outDir$normal').toNativePath());
+ var crossDir = new Directory(new Path('$outDir$cross').toNativePath());
+ if (normalDir.existsSync() && crossDir.existsSync()) {
+ throw "You can't have both $normalDir and $crossDir, we don't know which"
+ " binary to use";
+ }
+ if (crossDir.existsSync()) {
+ return cross;
+ }
+ return normal;
+ }
+
+ static String configurationDir(Map configuration) {
+ // For regular dart checkouts, the configDir by default is mode+arch.
+ // For Dartium, the configDir by default is mode (as defined by the Chrome
+ // build setup). We can detect this because in the dartium checkout, the
+ // "output" directory is a sibling of the dart directory instead of a child.
+ var mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release';
+ var arch = configuration['arch'].toUpperCase();
+ if (currentWorkingDirectory != dartDir) {
+ return getValidOutputDir(configuration, mode, arch);
+ } else {
+ return mode;
+ }
+ }
+
+ /**
+ * Returns the path to the dart binary checked into the repo, used for
+ * bootstrapping test.dart.
+ */
+ static Path get dartTestExecutable {
+ var path = '$dartDir/tools/testing/bin/'
+ '${Platform.operatingSystem}/dart';
+ if (Platform.operatingSystem == 'windows') {
+ path = '$path.exe';
+ }
+ return new Path(path);
+ }
+
+ /**
+ * Gets extra options under [key] passed to the testing script.
+ */
+ static List<String> getExtraOptions(Map configuration, String key) {
+ if (configuration[key] == null) return <String>[];
+ return configuration[key]
+ .split(" ")
+ .map((s) => s.trim())
+ .where((s) => s.isNotEmpty)
+ .toList();
+ }
+
+ /**
+ * Gets extra vm options passed to the testing script.
+ */
+ static List<String> getExtraVmOptions(Map configuration) =>
+ getExtraOptions(configuration, 'vm_options');
+
+ static String getShortName(String path) {
+ final PATH_REPLACEMENTS = const {
+ "pkg_polymer_e2e_test_bad_import_test": "polymer_bi",
+ "pkg_polymer_e2e_test_canonicalization_test": "polymer_c16n",
+ "pkg_polymer_e2e_test_experimental_boot_test": "polymer_boot",
+ "pkg_polymer_e2e_test_good_import_test": "polymer_gi",
+ "tests_co19_src_Language_12_Expressions_14_Function_Invocation_":
+ "co19_fn_invoke_",
+ "tests_co19_src_LayoutTests_fast_css_getComputedStyle_getComputedStyle-":
+ "co19_css_getComputedStyle_",
+ "tests_co19_src_LayoutTests_fast_dom_Document_CaretRangeFromPoint_"
+ "caretRangeFromPoint-": "co19_caretrangefrompoint_",
+ "tests_co19_src_LayoutTests_fast_dom_Document_CaretRangeFromPoint_"
+ "hittest-relative-to-viewport_": "co19_caretrange_hittest_",
+ "tests_co19_src_LayoutTests_fast_dom_HTMLLinkElement_link-onerror-"
+ "stylesheet-with-": "co19_dom_link-",
+ "tests_co19_src_LayoutTests_fast_dom_": "co19_dom",
+ "tests_co19_src_LayoutTests_fast_canvas_webgl": "co19_canvas_webgl",
+ "tests_co19_src_LibTest_core_AbstractClassInstantiationError_"
+ "AbstractClassInstantiationError_": "co19_abstract_class_",
+ "tests_co19_src_LibTest_core_IntegerDivisionByZeroException_"
+ "IntegerDivisionByZeroException_": "co19_division_by_zero",
+ "tests_co19_src_WebPlatformTest_html_dom_documents_dom-tree-accessors_":
+ "co19_dom_accessors_",
+ "tests_co19_src_WebPlatformTest_html_semantics_embedded-content_"
+ "media-elements_": "co19_media_elements",
+ "tests_co19_src_WebPlatformTest_html_semantics_": "co19_semantics_",
+
+ "tests_co19_src_WebPlatformTest_html-templates_additions-to-"
+ "the-steps-to-clone-a-node_": "co19_htmltemplates_clone_",
+ "tests_co19_src_WebPlatformTest_html-templates_definitions_"
+ "template-contents-owner": "co19_htmltemplates_contents",
+ "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
+ "templates_additions-to-": "co19_htmltemplates_add_",
+ "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
+ "templates_appending-to-a-template_": "co19_htmltemplates_append_",
+ "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
+ "templates_clearing-the-stack-back-to-a-given-context_":
+ "co19_htmltemplates_clearstack_",
+ "tests_co19_src_WebPlatformTest_html-templates_parsing-html-"
+ "templates_creating-an-element-for-the-token_":
+ "co19_htmltemplates_create_",
+ "tests_co19_src_WebPlatformTest_html-templates_template-element"
+ "_template-": "co19_htmltemplates_element-",
+ "tests_co19_src_WebPlatformTest_html-templates_": "co19_htmltemplate_",
+
+ "tests_co19_src_WebPlatformTest_shadow-dom_shadow-trees_":
+ "co19_shadow-trees_",
+ "tests_co19_src_WebPlatformTest_shadow-dom_elements-and-dom-objects_":
+ "co19_shadowdom_",
+ "tests_co19_src_WebPlatformTest_shadow-dom_html-elements-in-"
+ "shadow-trees_": "co19_shadow_html_",
+ "tests_co19_src_WebPlatformTest_html_webappapis_system-state-and-"
+ "capabilities_the-navigator-object": "co19_webappapis_navigator_",
+ "tests_co19_src_WebPlatformTest_DOMEvents_approved_": "co19_dom_approved_"
+ };
+
+ // Some tests are already in [build_dir]/generated_tests.
+ String GEN_TESTS = 'generated_tests/';
+ if (path.contains(GEN_TESTS)) {
+ int index = path.indexOf(GEN_TESTS) + GEN_TESTS.length;
+ path = 'multitest/${path.substring(index)}';
+ }
+ path = path.replaceAll('/', '_');
+ final int WINDOWS_SHORTEN_PATH_LIMIT = 58;
+ if (Platform.operatingSystem == 'windows' &&
+ path.length > WINDOWS_SHORTEN_PATH_LIMIT) {
+ for (var key in PATH_REPLACEMENTS.keys) {
+ if (path.startsWith(key)) {
+ path = path.replaceFirst(key, PATH_REPLACEMENTS[key]);
+ break;
+ }
+ }
+ }
+ return path;
+ }
+}
+
+
+class LastModifiedCache {
+ final Map<String, DateTime> _cache = <String, DateTime>{};
+
+ /**
+ * Returns the last modified date of the given [uri].
+ *
+ * The return value will be cached for future queries. If [uri] is a local
+ * file, it's last modified [Date] will be returned. If the file does not
+ * exist, null will be returned instead.
+ * In case [uri] is not a local file, this method will always return
+ * the current date.
+ */
+ DateTime getLastModified(Uri uri) {
+ if (uri.scheme == "file") {
+ if (_cache.containsKey(uri.path)) {
+ return _cache[uri.path];
+ }
+ var file = new File(new Path(uri.path).toNativePath());
+ _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null;
+ return _cache[uri.path];
+ }
+ return new DateTime.now();
+ }
+}
+
+
+class ExistsCache {
+ final Map<String, bool> _cache = <String, bool>{};
+
+ /**
+ * Returns true if the file in [path] exists, false otherwise.
+ *
+ * The information will be cached.
+ */
+ bool doesFileExist(String path) {
+ if (!_cache.containsKey(path)) {
+ _cache[path] = new File(path).existsSync();
+ }
+ return _cache[path];
+ }
+}
« no previous file with comments | « tools/testing/dart/lib/test_progress.dart ('k') | tools/testing/dart/lib/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698