From 182d55dfda5b8d7c9919b747ccb703c684100c67 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 29 May 2019 08:39:44 +0000 Subject: [PATCH] [dart2js] Add support for BabelJS to test.py This adds support for BabelJS to test.py's dart2js compiler configuration. When --babel is specified directly or through a named configuration, test.py will run an additional step after dart2js that post-processes the javascript output by running it through BabelJS with the specified Babel configuration. BabelJS is added to the DEPS in its standalone form. d8 is used to run BabelJS standalone to avoid adding a dependency on NodeJS. d8 can only write to stdout but not to files or stderr, which makes it necessary to change the test_runner to handle commands that expect their output to be piped to a file. Changes: * Add --babel option to test.py. * Add babel option to pkg/smith. * Switch IE11 builder to use babel transformation. * Fix option list comparison bugs in pkg/smith. * Change dart2js compiler configuration to generate files using the test name rather than just "out.js" (update test that relied on this). * Remove runtime_configuration dependency on test_suite. * Remove obsolete blocks adding --preview-dart-2 dart2js arguments. * Make dart2js' compiler configuration more like DDC's. * Remove createCommand method that is no longer used. * Remove support for "OtherResources" which was only used for dart:isolate tests on dart2js and DDC. * Skip co19_2 tests that are slow to transform with babel. * Simplify the timeout handling in the test runner with Future.timeout. Change-Id: I32e4917b2a57ecbe684538e40d744f0101c552a0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/90402 Commit-Queue: Alexander Thomas Reviewed-by: Sigmund Cherem --- DEPS | 10 +- pkg/smith/lib/configuration.dart | 56 +++-- tests/co19_2/co19_2-dart2js.status | 11 + .../compute_this_script_test.dart | 2 +- tests/lib_2/html/async_spawnuri_test.dart | 37 ---- .../isolate/browser/issue_12474_test.dart | 5 - .../lib_2/isolate/error_at_spawnuri_test.dart | 2 - .../isolate/error_exit_at_spawnuri_test.dart | 2 - .../lib_2/isolate/exit_at_spawnuri_test.dart | 2 - .../issue_21398_parent_isolate1_test.dart | 6 - .../issue_21398_parent_isolate2_test.dart | 5 - .../issue_21398_parent_isolate_test.dart | 5 - .../issue_24243_parent_isolate_test.dart | 6 - tests/lib_2/isolate/spawn_uri_multi_test.dart | 3 - .../isolate/spawn_uri_nested_vm_test.dart | 3 - tests/lib_2/isolate/spawn_uri_test.dart | 3 - tests/lib_2/isolate/spawn_uri_vm_test.dart | 3 - tests/lib_2/lib_2_dart2js.status | 3 - tests/lib_2/lib_2_dartdevc.status | 1 - third_party/babel/update.sh | 29 +++ tools/bots/test_matrix.json | 8 +- tools/testing/dart/babel_transform.js | 12 ++ tools/testing/dart/command.dart | 19 +- .../testing/dart/compiler_configuration.dart | 61 ++++-- tools/testing/dart/configuration.dart | 27 ++- tools/testing/dart/options.dart | 12 +- tools/testing/dart/runtime_configuration.dart | 102 ++++++--- tools/testing/dart/test_runner.dart | 159 +++++++------- tools/testing/dart/test_suite.dart | 200 ++---------------- 29 files changed, 362 insertions(+), 432 deletions(-) delete mode 100644 tests/lib_2/html/async_spawnuri_test.dart create mode 100755 third_party/babel/update.sh create mode 100644 tools/testing/dart/babel_transform.js diff --git a/DEPS b/DEPS index 3d0c0bbdffe..1de6d516834 100644 --- a/DEPS +++ b/DEPS @@ -168,7 +168,6 @@ deps = { }], "dep_type": "cipd", }, - Var("dart_root") + "/tests/co19_2/src": { "packages": [{ "package": "dart/third_party/co19", @@ -176,11 +175,16 @@ deps = { }], "dep_type": "cipd", }, - Var("dart_root") + "/third_party/markupsafe": Var("chromium_git") + "/chromium/src/third_party/markupsafe.git" + "@" + Var("markupsafe_rev"), - + Var("dart_root") + "/third_party/babel": { + "packages": [{ + "package": "dart/third_party/babel", + "version": "version:7.4.5", + }], + "dep_type": "cipd", + }, Var("dart_root") + "/third_party/zlib": Var("chromium_git") + "/chromium/src/third_party/zlib.git" + "@" + Var("zlib_rev"), diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart index 656b7e6f37e..62dbee42aed 100644 --- a/pkg/smith/lib/configuration.dart +++ b/pkg/smith/lib/configuration.dart @@ -8,7 +8,7 @@ import 'dart:io'; // - "windows" -> "win". // - "macos" -> "mac". // - toString() on enum classes is just name. -// - builderTag defaults to empty string, not null. +// - builderTag and babel default to empty string, not null. // Need to migrate test.dart to not expect the above before it can use this. // READ ME! If you add a new field to this, make sure to add it to @@ -247,6 +247,7 @@ class Configuration { var configuration = Configuration( name, architecture, compiler, mode, runtime, system, + babel: stringOption("babel"), builderTag: stringOption("builder-tag"), vmOptions: stringListOption("vm-options"), dart2jsOptions: stringListOption("dart2js-options"), @@ -285,13 +286,15 @@ class Configuration { final System system; + final String babel; + final String builderTag; final List vmOptions; final List dart2jsOptions; - int timeout; + final int timeout; final bool enableAsserts; @@ -323,7 +326,8 @@ class Configuration { Configuration(this.name, this.architecture, this.compiler, this.mode, this.runtime, this.system, - {String builderTag, + {String babel, + String builderTag, List vmOptions, List dart2jsOptions, int timeout, @@ -340,10 +344,11 @@ class Configuration { bool useHotReload, bool useHotReloadRollback, bool useSdk}) - : builderTag = builderTag ?? "", + : babel = babel ?? "", + builderTag = builderTag ?? "", vmOptions = vmOptions ?? [], dart2jsOptions = dart2jsOptions ?? [], - timeout = timeout, + timeout = timeout ?? -1, enableAsserts = enableAsserts ?? false, isChecked = isChecked ?? false, isCsp = isCsp ?? false, @@ -366,6 +371,7 @@ class Configuration { mode == other.mode && runtime == other.runtime && system == other.system && + babel == other.babel && builderTag == other.builderTag && vmOptions.join(" & ") == other.vmOptions.join(" & ") && dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") && @@ -397,6 +403,7 @@ class Configuration { mode.hashCode ^ runtime.hashCode ^ system.hashCode ^ + babel.hashCode ^ builderTag.hashCode ^ vmOptions.join(" & ").hashCode ^ dart2jsOptions.join(" & ").hashCode ^ @@ -429,11 +436,13 @@ class Configuration { fields.add("runtime: $runtime"); fields.add("system: $system"); - if (builderTag != "") fields.add("builder-tag: $builderTag"); - if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]"); - if (dart2jsOptions != "") + if (babel.isNotEmpty) fields.add("babel: $babel"); + if (builderTag.isNotEmpty) fields.add("builder-tag: $builderTag"); + if (vmOptions.isNotEmpty) + fields.add("vm-options: [${vmOptions.join(", ")}]"); + if (dart2jsOptions.isNotEmpty) fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]"); - if (timeout != 0) fields.add("timeout: $timeout"); + if (timeout > 0) fields.add("timeout: $timeout"); if (enableAsserts) fields.add("enable-asserts"); if (isChecked) fields.add("checked"); if (isCsp) fields.add("csp"); @@ -464,20 +473,25 @@ class Configuration { fields.add("runtime: $runtime ${other.runtime}"); fields.add("system: $system ${other.system}"); - if (builderTag != "" || other.builderTag != "") { - var tag = builderTag == "" ? "(none)" : builderTag; - var otherTag = other.builderTag == "" ? "(none)" : other.builderTag; - fields.add("builder-tag: $tag $otherTag"); + if (babel.isNotEmpty || other.babel.isNotEmpty) { + var ours = babel == "" ? "(none)" : babel; + var theirs = other.babel == "" ? "(none)" : other.babel; + fields.add("babel: $ours $theirs"); } - if (vmOptions != "" || other.vmOptions != "") { - var tag = "[${vmOptions.join(", ")}]"; - var otherTag = "[${other.vmOptions.join(", ")}]"; - fields.add("vm-options: $tag $otherTag"); + if (builderTag.isNotEmpty || other.builderTag.isNotEmpty) { + var ours = builderTag == "" ? "(none)" : builderTag; + var theirs = other.builderTag == "" ? "(none)" : other.builderTag; + fields.add("builder-tag: $ours $theirs"); } - if (dart2jsOptions != "" || other.dart2jsOptions != "") { - var tag = "[${dart2jsOptions.join(", ")}]"; - var otherTag = "[${other.dart2jsOptions.join(", ")}]"; - fields.add("dart2js-options: $tag $otherTag"); + if (vmOptions.isNotEmpty || other.vmOptions.isNotEmpty) { + var ours = "[${vmOptions.join(", ")}]"; + var theirs = "[${other.vmOptions.join(", ")}]"; + fields.add("vm-options: $ours $theirs"); + } + if (dart2jsOptions.isNotEmpty || other.dart2jsOptions.isNotEmpty) { + var ours = "[${dart2jsOptions.join(", ")}]"; + var theirs = "[${other.dart2jsOptions.join(", ")}]"; + fields.add("dart2js-options: $ours $theirs"); } fields.add("timeout: $timeout ${other.timeout}"); if (enableAsserts || other.enableAsserts) { diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status index c4f26922bb2..5321ddf38ef 100644 --- a/tests/co19_2/co19_2-dart2js.status +++ b/tests/co19_2/co19_2-dart2js.status @@ -10,6 +10,17 @@ LayoutTests/*: SkipByDesign # d8 is not a browser LibTest/html/*: SkipByDesign # d8 is not a browser WebPlatformTest/*: SkipByDesign # d8 is not a browser +[ $compiler == dart2js && $runtime == ie11 ] +LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # slow babeljs transformation +LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # slow babeljs transformation +LibTest/collection/ListBase/ListBase_class_A01_t06: SkipSlow # slow babeljs transformation +LibTest/collection/ListMixin/ListMixin_class_A01_t04: SkipSlow # slow babeljs transformation +LibTest/collection/ListMixin/ListMixin_class_A01_t05: SkipSlow # slow babeljs transformation +LibTest/collection/ListMixin/ListMixin_class_A01_t06: SkipSlow # slow babeljs transformation +LibTest/core/List/List_class_A01_t04: SkipSlow # slow babeljs transformation +LibTest/core/List/List_class_A01_t05: SkipSlow # slow babeljs transformation +LibTest/core/List/List_class_A01_t06: SkipSlow # slow babeljs transformation + [ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ] Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign LibTest/io/*: SkipByDesign # dart:io not supported. diff --git a/tests/compiler/dart2js_native/compute_this_script_test.dart b/tests/compiler/dart2js_native/compute_this_script_test.dart index 8519bc4e8f1..ee5c855dbe9 100644 --- a/tests/compiler/dart2js_native/compute_this_script_test.dart +++ b/tests/compiler/dart2js_native/compute_this_script_test.dart @@ -10,7 +10,7 @@ main() { // This is somewhat brittle and relies on an implementation detail // of our test runner, but I can think of no other way to test this. // -- ahe - if (!thisScript.endsWith('/out.js')) { + if (!thisScript.endsWith('/compute_this_script_test.js')) { throw 'Unexpected script: "$thisScript"'; } } diff --git a/tests/lib_2/html/async_spawnuri_test.dart b/tests/lib_2/html/async_spawnuri_test.dart deleted file mode 100644 index 1175a3ed920..00000000000 --- a/tests/lib_2/html/async_spawnuri_test.dart +++ /dev/null @@ -1,37 +0,0 @@ -library async_spawnuri_test; - -import 'package:unittest/unittest.dart'; -import 'package:unittest/html_config.dart'; - -import 'dart:async'; -import 'dart:isolate'; -import 'dart:html'; - -// OtherScripts=async_oneshot.dart async_periodictimer.dart async_cancellingisolate.dart -main() { - useHtmlConfiguration(); - - test('one shot timer in pure isolate', () { - var response = new ReceivePort(); - var remote = Isolate.spawnUri( - Uri.parse('async_oneshot.dart'), ['START'], response.sendPort); - remote.catchError((x) => expect("Error in oneshot isolate", x)); - expect(remote.then((_) => response.first), completion('DONE')); - }); - - test('periodic timer in pure isolate', () { - var response = new ReceivePort(); - var remote = Isolate.spawnUri( - Uri.parse('async_periodictimer.dart'), ['START'], response.sendPort); - remote.catchError((x) => expect("Error in periodic timer isolate", x)); - expect(remote.then((_) => response.first), completion('DONE')); - }); - - test('cancellation in pure isolate', () { - var response = new ReceivePort(); - var remote = Isolate.spawnUri(Uri.parse('async_cancellingisolate.dart'), - ['START'], response.sendPort); - remote.catchError((x) => expect("Error in cancelling isolate", x)); - expect(remote.then((_) => response.first), completion('DONE')); - }); -} diff --git a/tests/lib_2/isolate/browser/issue_12474_test.dart b/tests/lib_2/isolate/browser/issue_12474_test.dart index aca9741d8c5..b1cfe7066cc 100644 --- a/tests/lib_2/isolate/browser/issue_12474_test.dart +++ b/tests/lib_2/isolate/browser/issue_12474_test.dart @@ -2,11 +2,6 @@ // 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. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=issue_12474_child.dart -// OtherScripts=package/issue_12474_lib.dart - import 'dart:isolate'; final SPAWN_PACKAGE_ROOT = Uri.parse("."); diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart index d33ac09f596..5c428b93102 100644 --- a/tests/lib_2/isolate/error_at_spawnuri_test.dart +++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart @@ -1,8 +1,6 @@ // Copyright (c) 2015, 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. -// -// OtherScripts=error_at_spawnuri_iso.dart library error_at_spawnuri; diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart index 96437702c3e..6e9a5a8b3ee 100644 --- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart +++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart @@ -1,8 +1,6 @@ // Copyright (c) 2015, 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. -// -// OtherScripts=error_exit_at_spawning_shared.dart library error_exit_at_spawnuri; diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart index fd2287bea48..f415c663ccd 100644 --- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart +++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart @@ -1,8 +1,6 @@ // Copyright (c) 2015, 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. -// -// OtherScripts=exit_at_spawnuri_iso.dart library exit_at_spawn; diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart index 9da96783261..74b6cc6fd34 100644 --- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart +++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart @@ -2,13 +2,7 @@ // 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. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=issue_21398_child_isolate1.dart -// OtherScripts=issue_21398_child_isolate11.dart - import 'dart:isolate'; -import 'dart:async'; import "package:expect/expect.dart"; import 'package:async_helper/async_helper.dart'; diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart index 27d49b9856d..0fe1043ca9c 100644 --- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart +++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart @@ -2,12 +2,7 @@ // 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. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=deferred_loaded_lib.dart - import 'dart:isolate'; -import 'dart:async'; import "package:expect/expect.dart"; import 'package:async_helper/async_helper.dart'; diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart index 967d25fda32..ab413e9bb47 100644 --- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart +++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart @@ -2,12 +2,7 @@ // 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. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=issue_21398_child_isolate.dart - import 'dart:isolate'; -import 'dart:async'; import "package:expect/expect.dart"; import 'package:async_helper/async_helper.dart'; diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart index 62947679a79..2c1dc545c05 100644 --- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart +++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart @@ -2,12 +2,6 @@ // 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. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=issue_24243_child1_isolate.dart -// OtherScripts=issue_24243_child2_isolate.dart -// OtherScripts=issue_24243_child3_isolate.dart - import 'dart:collection'; import 'dart:isolate'; diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart index 60766177ace..2984fcab10c 100644 --- a/tests/lib_2/isolate/spawn_uri_multi_test.dart +++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart @@ -3,9 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // Negative test to make sure that we are reaching all assertions. -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=spawn_uri_child_isolate.dart library spawn_tests; import 'dart:isolate'; diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart index 6d37e262e51..f558df5eadd 100644 --- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart +++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart @@ -3,9 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // Example of nested spawning of isolates from a URI -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=spawn_uri_nested_child1_vm_isolate.dart spawn_uri_nested_child2_vm_isolate.dart library NestedSpawnUriLibrary; import 'dart:isolate'; diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart index 3f522154bd4..e71fed7660b 100644 --- a/tests/lib_2/isolate/spawn_uri_test.dart +++ b/tests/lib_2/isolate/spawn_uri_test.dart @@ -3,9 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // Example of spawning an isolate from a URI -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=spawn_uri_child_isolate.dart library spawn_tests; import 'dart:isolate'; diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart index 6bc2e6e3670..a3b8f614b97 100644 --- a/tests/lib_2/isolate/spawn_uri_vm_test.dart +++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart @@ -3,9 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // Example of spawning an isolate from a URI -// Note: the following comment is used by test.dart to additionally compile the -// other isolate's code. -// OtherScripts=spawn_uri_child_isolate.dart library spawn_tests; import 'dart:isolate'; diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status index 6cd2ce38c75..b96429f2a95 100644 --- a/tests/lib_2/lib_2_dart2js.status +++ b/tests/lib_2/lib_2_dart2js.status @@ -10,7 +10,6 @@ collection/list_test: RuntimeError convert/chunked_conversion_utf88_test: Slow convert/utf85_test: Slow developer/timeline_test: Skip # Not supported -html/async_spawnuri_test: SkipByDesign html/async_test: SkipByDesign html/custom/document_register_basic_test: Slow html/custom/document_register_type_extensions_test/construction: Slow @@ -82,7 +81,6 @@ typed_data/setRange_3_test: RuntimeError # TODO(dart2js-team): Please triage thi [ $compiler == dart2js && $runtime == d8 ] async/dart2js_uncaught_error_test: RuntimeError -html/async_spawnuri_test: RuntimeError html/async_test: RuntimeError html/audiobuffersourcenode_test: RuntimeError html/audiocontext_test: RuntimeError @@ -494,7 +492,6 @@ html/mirrors_js_typed_interop_test: SkipByDesign html/postmessage_structured_test: SkipByDesign [ $compiler == dart2js && !$csp && $minified ] -html/async_spawnuri_test: RuntimeError html/async_test: RuntimeError html/audiobuffersourcenode_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'. html/audiocontext_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'. diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status index 0532e642b0e..4b47ff631e4 100644 --- a/tests/lib_2/lib_2_dartdevc.status +++ b/tests/lib_2/lib_2_dartdevc.status @@ -41,7 +41,6 @@ convert/json_utf8_chunk_test: Slow, Pass convert/streamed_conversion_json_utf8_encode_test: Pass, Timeout # Issue 29922 convert/streamed_conversion_utf8_decode_test: Slow, Pass, Timeout # Issue 29922 convert/utf85_test: Slow, Pass -html/async_spawnuri_test: RuntimeError # Issue 29922 html/async_test: RuntimeError # Issue 29922 html/callback_list_test: Skip # Test requires user interaction to accept permissions. html/custom/attribute_changed_callback_test: Skip # Issue 31577 diff --git a/third_party/babel/update.sh b/third_party/babel/update.sh new file mode 100755 index 00000000000..6b9ca5a76b4 --- /dev/null +++ b/third_party/babel/update.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Uploads a new version of d8 CIPD package +set -e +set -x + +if [ -z "$1" ]; then + echo "Usage: update.sh version" + exit 1 +fi + +version=$1 + +tmpdir=$(mktemp -d) +cleanup() { + rm -rf "$tmpdir" +} +trap cleanup EXIT HUP INT QUIT TERM PIPE +cd "$tmpdir" + +for file in "babel.js" "babel.min.js" "LICENSE" +do + curl -o $file "https://unpkg.com/@babel/standalone@$version/$file" +done + +cipd create \ + -name dart/third_party/babel \ + -in . \ + -install-mode copy \ + -tag version:$version diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index 5af18d9f212..0f6de4ee573 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -43,6 +43,7 @@ "tests/standalone/", "tests/standalone_2/", "tests/ffi/", + "third_party/babel/babel.min.js", "third_party/d8/", "third_party/observatory_pub_packages/packages/web_components/", "third_party/pkg/", @@ -245,7 +246,12 @@ "options": { "use-sdk": true }}, - "dart2js-win-(ie11|edge)": { + "dart2js-win-ie11": { + "options": { + "use-sdk": true, + "babel": "{\"presets\":[\"es2015\"]}" + }}, + "dart2js-win-edge": { "options": { "use-sdk": true }}, diff --git a/tools/testing/dart/babel_transform.js b/tools/testing/dart/babel_transform.js new file mode 100644 index 00000000000..5229e8a4b84 --- /dev/null +++ b/tools/testing/dart/babel_transform.js @@ -0,0 +1,12 @@ +// Copyright (c) 2019, 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. + + +const babelStandalonePath = arguments[0]; +load(babelStandalonePath); +const inputFilePath = arguments[2]; +const input = read(inputFilePath); +const options = JSON.parse(arguments[1]); +const output = Babel.transform(input, options).code; +console.log(output); diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart index da1a88a1f7f..2eb764857d2 100644 --- a/tools/testing/dart/command.dart +++ b/tools/testing/dart/command.dart @@ -257,7 +257,8 @@ class ProcessCommand extends Command { } class CompilationCommand extends ProcessCommand { - final String _outputFile; + /// The primary output file that will be created by this command. + final String outputFile; /// If true, then the compilation is run even if the input files are older /// than the output file. @@ -266,7 +267,7 @@ class CompilationCommand extends ProcessCommand { CompilationCommand._( String displayName, - this._outputFile, + this.outputFile, this._alwaysCompile, this._bootstrapDependencies, String executable, @@ -279,7 +280,7 @@ class CompilationCommand extends ProcessCommand { CompilationCommand indexedCopy(int index) => CompilationCommand._( displayName, - _outputFile, + outputFile, _alwaysCompile, _bootstrapDependencies, executable, @@ -291,7 +292,7 @@ class CompilationCommand extends ProcessCommand { bool get outputIsUpToDate { if (_alwaysCompile) return false; - var file = new io.File(new Path("$_outputFile.deps").toNativePath()); + var file = new io.File(new Path("$outputFile.deps").toNativePath()); if (!file.existsSync()) return false; var lines = file.readAsLinesSync(); @@ -305,7 +306,7 @@ class CompilationCommand extends ProcessCommand { dependencies.addAll(_bootstrapDependencies); var jsOutputLastModified = TestUtils.lastModifiedCache - .getLastModified(new Uri(scheme: 'file', path: _outputFile)); + .getLastModified(new Uri(scheme: 'file', path: outputFile)); if (jsOutputLastModified == null) return false; for (var dependency in dependencies) { @@ -321,14 +322,14 @@ class CompilationCommand extends ProcessCommand { void _buildHashCode(HashCodeBuilder builder) { super._buildHashCode(builder); - builder.addJson(_outputFile); + builder.addJson(outputFile); builder.addJson(_alwaysCompile); builder.addJson(_bootstrapDependencies); } bool _equal(CompilationCommand other) => super._equal(other) && - _outputFile == other._outputFile && + outputFile == other.outputFile && _alwaysCompile == other._alwaysCompile && deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies); } @@ -352,7 +353,7 @@ class FastaCompilationCommand extends CompilationCommand { @override FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand._( _compilerLocation, - _outputFile, + outputFile, _bootstrapDependencies, executable, arguments, @@ -442,7 +443,7 @@ class VMKernelCompilationCommand extends CompilationCommand { VMKernelCompilationCommand indexedCopy(int index) => VMKernelCompilationCommand._( - _outputFile, + outputFile, _alwaysCompile, _bootstrapDependencies, executable, diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart index 4a580e66da2..77d196f6cf8 100644 --- a/tools/testing/dart/compiler_configuration.dart +++ b/tools/testing/dart/compiler_configuration.dart @@ -118,8 +118,6 @@ abstract class CompilerConfiguration { } } - // TODO(ahe): It shouldn't be necessary to pass [buildDir] to any of these - // functions. It is fixed for a given configuration. String computeCompilerPath() { throw "Unknown compiler for: $runtimeType"; } @@ -130,15 +128,6 @@ abstract class CompilerConfiguration { List bootstrapDependencies() => const []; - /// Creates a [Command] to compile [inputFile] to [outputFile]. - Command createCommand(String inputFile, String outputFile, - List sharedOptions, Map environment) { - // TODO(rnystrom): See if this method can be unified with - // computeCompilationArtifact() and/or computeCompilerArguments() for the - // other compilers. - throw new UnsupportedError("$this does not support createCommand()."); - } - CommandArtifact computeCompilationArtifact( /// Each test has its own temporary directory to avoid name collisions. @@ -486,10 +475,26 @@ class Dart2jsCompilerConfiguration extends Dart2xCompilerConfiguration { List arguments, Map environmentOverrides) { var compilerArguments = arguments.toList() ..addAll(_configuration.dart2jsOptions); - return new CommandArtifact([ - computeCompilationCommand( - '$tempDir/out.js', compilerArguments, environmentOverrides) - ], '$tempDir/out.js', 'application/javascript'); + + var commands = []; + // TODO(athom): input filename extraction is copied from DDC. Maybe this + // should be passed to computeCompilationArtifact, instead? + var inputFile = arguments.last; + var inputFilename = (new Uri.file(inputFile)).pathSegments.last; + var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}"; + var babel = _configuration.babel; + var babelOut = out; + if (babel != null && babel.isNotEmpty) { + out = out.replaceAll('.js', '.raw.js'); + } + commands.add(computeCompilationCommand( + out, compilerArguments, environmentOverrides)); + + if (babel != null && babel.isNotEmpty) { + commands.add(computeBabelCommand(out, babelOut, babel)); + } + + return new CommandArtifact(commands, babelOut, 'application/javascript'); } List computeRuntimeArguments( @@ -507,6 +512,22 @@ class Dart2jsCompilerConfiguration extends Dart2xCompilerConfiguration { return runtimeConfiguration.dart2jsPreambles(preambleDir) ..add(artifact.filename); } + + Command computeBabelCommand(String input, String output, String options) { + var uri = Repository.uri; + var babelTransform = + uri.resolve('tools/testing/dart/babel_transform.js').toFilePath(); + var babelStandalone = + uri.resolve('third_party/babel/babel.min.js').toFilePath(); + return Command.compilation( + 'babel', + output, + [], + _configuration.runtimeConfiguration.d8FileName, + [babelTransform, "--", babelStandalone, options, input], + {}, + alwaysCompile: true); // TODO(athom): ensure dependency tracking works. + } } /// Configuration for `dartdevc` and `dartdevk` (DDC with Kernel) @@ -537,7 +558,7 @@ class DevCompilerConfiguration extends CompilerConfiguration { return result; } - Command createCommand(String inputFile, String outputFile, + Command _createCommand(String inputFile, String outputFile, List sharedOptions, Map environment) { /// This can be disabled to test DDC's hybrid mode (automatically converting /// Analyzer summaries to Kernel files). @@ -629,7 +650,7 @@ class DevCompilerConfiguration extends CompilerConfiguration { var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}"; return new CommandArtifact( - [createCommand(inputFile, outputFile, sharedOptions, environment)], + [_createCommand(inputFile, outputFile, sharedOptions, environment)], outputFile, "application/javascript"); } @@ -1206,12 +1227,6 @@ class FastaCompilerConfiguration extends CompilerConfiguration { @override List bootstrapDependencies() => [_platformDill]; - @override - Command createCommand(String inputFile, String outputFile, - List sharedOptions, Map environment) { - throw new UnimplementedError(); - } - @override CommandArtifact computeCompilationArtifact(String tempDir, List arguments, Map environmentOverrides) { diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart index b903330372c..da990fb966a 100644 --- a/tools/testing/dart/configuration.dart +++ b/tools/testing/dart/configuration.dart @@ -165,6 +165,7 @@ class TestConfiguration { final String outputDirectory; final String packageRoot; final String suiteDirectory; + String get babel => configuration.babel; String get builderTag => configuration.builderTag; final List reproducingArguments; @@ -211,24 +212,30 @@ class TestConfiguration { /// build/none_vm_release_x64 String get buildDirectory => system.outputDirectory + configurationDirectory; + int _timeout; + // TODO(whesse): Put non-default timeouts explicitly in configs, not this. /// Calculates a default timeout based on the compiler and runtime used, /// and the mode, architecture, etc. int get timeout { - if (configuration.timeout == null) { - var isReload = hotReload || hotReloadRollback; + if (_timeout == null) { + if (configuration.timeout > 0) { + _timeout = configuration.timeout; + } else { + var isReload = hotReload || hotReloadRollback; - var compilerMulitiplier = compilerConfiguration.timeoutMultiplier; - var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier( - mode: mode, - isChecked: isChecked, - isReload: isReload, - arch: architecture); + var compilerMulitiplier = compilerConfiguration.timeoutMultiplier; + var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier( + mode: mode, + isChecked: isChecked, + isReload: isReload, + arch: architecture); - configuration.timeout = 60 * compilerMulitiplier * runtimeMultiplier; + _timeout = 60 * compilerMulitiplier * runtimeMultiplier; + } } - return configuration.timeout; + return _timeout; } List get standardOptions { diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart index a21d647dd80..9519f1ce9ad 100644 --- a/tools/testing/dart/options.dart +++ b/tools/testing/dart/options.dart @@ -225,7 +225,7 @@ compact, color, line, verbose, silent, status, buildbot, diff''', new _Option.bool( 'silent_failures', "Don't complain about failing tests. This is useful when in " - "combination with --write-results.", + "combination with --write-results.", hide: true), new _Option.bool('report_in_json', 'When listing with --list, output result summary in JSON.', @@ -253,12 +253,12 @@ compact, color, line, verbose, silent, status, buildbot, diff''', new _Option.bool( 'write_results', 'Write results to a "${TestUtils.resultsFileName}" json file ' - 'located at the debug_output_directory.', + 'located at the debug_output_directory.', hide: true), new _Option.bool( 'write_logs', 'Include the stdout and stderr of tests that don\'t match expectations ' - 'in the "${TestUtils.logsFileName}" file', + 'in the "${TestUtils.logsFileName}" file', hide: true), new _Option.bool( 'reset_browser_configuration', @@ -302,6 +302,11 @@ options. Used to be able to make sane updates to the status files.''', 'dart2js_options', 'Extra options for dart2js compilation step.', hide: true), new _Option('shared_options', 'Extra shared options.', hide: true), + new _Option( + 'babel', + '''Transforms dart2js output with Babel. The value must be +Babel options JSON.''', + hide: true), new _Option( 'suite_dir', 'Additional directory to add to the testing matrix.', hide: true), @@ -700,6 +705,7 @@ compiler.''', isMinified: data["minified"] as bool, vmOptions: vmOptions, dart2jsOptions: dart2jsOptions, + babel: data['babel'] as String, builderTag: data["builder_tag"] as String, previewDart2: true); var configuration = new TestConfiguration( diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart index daf4c68485e..38c10b18150 100644 --- a/tools/testing/dart/runtime_configuration.dart +++ b/tools/testing/dart/runtime_configuration.dart @@ -8,9 +8,7 @@ import 'command.dart'; import 'compiler_configuration.dart'; import 'configuration.dart'; import 'repository.dart'; -// TODO(ahe): Remove this import, we can precompute all the values required -// from TestSuite once the refactoring is complete. -import 'test_suite.dart'; +import 'utils.dart'; /// Describes the commands to run a given test case or its compiled output. /// @@ -82,7 +80,6 @@ abstract class RuntimeConfiguration { } List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -92,9 +89,74 @@ abstract class RuntimeConfiguration { throw "Unimplemented runtime '$runtimeType'"; } + /** + * The output directory for this suite's configuration. + */ + String get buildDir => _configuration.buildDirectory; + List dart2jsPreambles(Uri preambleDir) => []; bool get shouldSkipNegativeTests => false; + + /// Returns the path to the Dart VM executable. + String get dartVmBinaryFileName { + // Controlled by user with the option "--dart". + var dartExecutable = _configuration.dartPath; + + if (dartExecutable == null) { + dartExecutable = dartVmExecutableFileName; + } + + TestUtils.ensureExists(dartExecutable, _configuration); + return dartExecutable; + } + + String get dartVmExecutableFileName { + return _configuration.useSdk + ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix' + : '$buildDir/dart$executableBinarySuffix'; + } + + String get dartPrecompiledBinaryFileName { + // Controlled by user with the option "--dart_precompiled". + var dartExecutable = _configuration.dartPrecompiledPath; + + if (dartExecutable == null || dartExecutable == '') { + var suffix = executableBinarySuffix; + dartExecutable = '$buildDir/dart_precompiled_runtime$suffix'; + } + + TestUtils.ensureExists(dartExecutable, _configuration); + return dartExecutable; + } + + String get processTestBinaryFileName { + var suffix = executableBinarySuffix; + var processTestExecutable = '$buildDir/process_test$suffix'; + TestUtils.ensureExists(processTestExecutable, _configuration); + return processTestExecutable; + } + + String get d8FileName { + var suffix = executableBinarySuffix; + var d8Dir = Repository.dir.append('third_party/d8'); + var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix'); + var d8 = d8Path.toNativePath(); + TestUtils.ensureExists(d8, _configuration); + return d8; + } + + String get jsShellFileName { + var executableSuffix = executableBinarySuffix; + var executable = 'jsshell$executableSuffix'; + var jsshellDir = Repository.uri.resolve("tools/testing/bin").path; + var jsshell = '$jsshellDir/$executable'; + TestUtils.ensureExists(jsshell, _configuration); + return jsshell; + } + + String get executableBinarySuffix => Platform.isWindows ? '.exe' : ''; + String get executableScriptSuffix => Platform.isWindows ? '.bat' : ''; } /// The 'none' runtime configuration. @@ -102,7 +164,6 @@ class NoneRuntimeConfiguration extends RuntimeConfiguration { NoneRuntimeConfiguration() : super._subclass(); List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -130,7 +191,6 @@ class D8RuntimeConfiguration extends CommandLineJavaScriptRuntime { D8RuntimeConfiguration() : super('d8'); List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -140,7 +200,7 @@ class D8RuntimeConfiguration extends CommandLineJavaScriptRuntime { checkArtifact(artifact); return [ Command.jsCommandLine( - moniker, suite.d8FileName, arguments, environmentOverrides) + moniker, d8FileName, arguments, environmentOverrides) ]; } @@ -154,7 +214,6 @@ class JsshellRuntimeConfiguration extends CommandLineJavaScriptRuntime { JsshellRuntimeConfiguration() : super('jsshell'); List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -163,7 +222,7 @@ class JsshellRuntimeConfiguration extends CommandLineJavaScriptRuntime { checkArtifact(artifact); return [ Command.jsCommandLine( - moniker, suite.jsShellFileName, arguments, environmentOverrides) + moniker, jsShellFileName, arguments, environmentOverrides) ]; } @@ -214,7 +273,6 @@ class DartVmRuntimeConfiguration extends RuntimeConfiguration { //// The standalone Dart VM binary, "dart" or "dart.exe". class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration { List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -232,9 +290,9 @@ class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration { if (isCrashExpected) { arguments.insert(0, '--suppress-core-dump'); } - String executable = suite.dartVmBinaryFileName; + String executable = dartVmBinaryFileName; if (type == 'application/kernel-ir-fully-linked') { - executable = suite.dartVmExecutableFileName; + executable = dartVmExecutableFileName; } return [Command.vm(executable, arguments, environmentOverrides)]; } @@ -248,7 +306,6 @@ class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration { useElf = useElf; List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -261,8 +318,7 @@ class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration { } return [ - Command.vm( - suite.dartPrecompiledBinaryFileName, arguments, environmentOverrides) + Command.vm(dartPrecompiledBinaryFileName, arguments, environmentOverrides) ]; } } @@ -272,7 +328,6 @@ class DartkAdbRuntimeConfiguration extends DartVmRuntimeConfiguration { static const String DeviceTestDir = '/data/local/tmp/testing/test'; List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -284,8 +339,8 @@ class DartkAdbRuntimeConfiguration extends DartVmRuntimeConfiguration { throw "dart cannot run files of type '$type'."; } - final String buildPath = suite.buildDir; - final String processTest = suite.processTestBinaryFileName; + final String buildPath = buildDir; + final String processTest = processTestBinaryFileName; return [ Command.adbDartk(buildPath, processTest, script, arguments, extraLibs) ]; @@ -305,7 +360,6 @@ class DartPrecompiledAdbRuntimeConfiguration useElf = useElf; List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, @@ -317,8 +371,8 @@ class DartPrecompiledAdbRuntimeConfiguration throw "dart_precompiled cannot run files of type '$type'."; } - String precompiledRunner = suite.dartPrecompiledBinaryFileName; - String processTest = suite.processTestBinaryFileName; + String precompiledRunner = dartPrecompiledBinaryFileName; + String processTest = processTestBinaryFileName; return [ Command.adbPrecompiled( precompiledRunner, processTest, script, arguments, useBlobs, useElf) @@ -343,17 +397,16 @@ class SelfCheckRuntimeConfiguration extends DartVmRuntimeConfiguration { } List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, List extraLibs, bool isCrashExpected) { - String executable = suite.dartVmBinaryFileName; + String executable = dartVmBinaryFileName; return selfCheckers .map((String tester) => Command.vmBatch( executable, tester, arguments, environmentOverrides, - checked: suite.configuration.isChecked)) + checked: _configuration.isChecked)) .toList(); } @@ -366,7 +419,6 @@ class SelfCheckRuntimeConfiguration extends DartVmRuntimeConfiguration { // TODO(ahe): Remove this class. class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration { List computeRuntimeCommands( - TestSuite suite, CommandArtifact artifact, List arguments, Map environmentOverrides, diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart index ed69296521f..1d13426f54e 100644 --- a/tools/testing/dart/test_runner.dart +++ b/tools/testing/dart/test_runner.dart @@ -244,7 +244,7 @@ class TestCase extends UniqueObject { * it is longer than MAX_HEAD characters, and just keeps the head and * the last TAIL_LENGTH characters of the output. */ -class OutputLog { +class OutputLog implements StreamConsumer> { static const int MAX_HEAD = 500 * 1024; static const int TAIL_LENGTH = 10 * 1024; List head = []; @@ -252,6 +252,7 @@ class OutputLog { List complete; bool dataDropped = false; bool hasNonUtf8 = false; + StreamSubscription _subscription; OutputLog(); @@ -325,6 +326,53 @@ be increased, please contact dart-engprod or file an issue. } return complete; } + + @override + Future addStream(Stream> stream) { + _subscription = stream.listen(this.add); + return _subscription.asFuture(); + } + + @override + Future close() { + toList(); + return _subscription?.cancel(); + } + + Future cancel() { + return _subscription?.cancel(); + } +} + +// An [OutputLog] that tees the output to a file as well. +class FileOutputLog extends OutputLog { + io.File _outputFile; + io.IOSink _sink; + + FileOutputLog(this._outputFile); + + @override + void add(List data) { + super.add(data); + _sink ??= _outputFile.openWrite(); + _sink.add(data); + } + + @override + Future close() { + return Future.wait([ + super.close(), + if (_sink != null) _sink.flush().whenComplete(_sink.close) + ]); + } + + @override + Future cancel() { + return Future.wait([ + super.cancel(), + if (_sink != null) _sink.flush().whenComplete(_sink.close) + ]); + } } // Helper to get a list of all child pids for a parent process. @@ -381,16 +429,19 @@ class RunningProcess { int timeout; bool timedOut = false; DateTime startTime; - Timer timeoutTimer; int pid; - OutputLog stdout = new OutputLog(); - OutputLog stderr = new OutputLog(); + OutputLog stdout; + OutputLog stderr = OutputLog(); + StreamConsumer stdoutConsumer; List diagnostics = []; bool compilationSkipped = false; Completer completer; TestConfiguration configuration; - RunningProcess(this.command, this.timeout, {this.configuration}); + RunningProcess(this.command, this.timeout, + {this.configuration, io.File outputFile}) { + stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog(); + } Future run() { completer = new Completer(); @@ -410,44 +461,10 @@ class RunningProcess { environment: processEnvironment, workingDirectory: command.workingDirectory); processFuture.then((io.Process process) { - StreamSubscription stdoutSubscription = - _drainStream(process.stdout, stdout); - StreamSubscription stderrSubscription = - _drainStream(process.stderr, stderr); - - var stdoutCompleter = new Completer(); - var stderrCompleter = new Completer(); - - bool stdoutDone = false; - bool stderrDone = false; + var stdoutFuture = process.stdout.pipe(stdout); + var stderrFuture = process.stderr.pipe(stderr); pid = process.pid; - // This timer is used to close stdio to the subprocess once we got - // the exitCode. Sometimes descendants of the subprocess keep stdio - // handles alive even though the direct subprocess is dead. - Timer watchdogTimer; - - closeStdout([_]) { - if (!stdoutDone) { - stdoutCompleter.complete(); - stdoutDone = true; - if (stderrDone && watchdogTimer != null) { - watchdogTimer.cancel(); - } - } - } - - closeStderr([_]) { - if (!stderrDone) { - stderrCompleter.complete(); - stderrDone = true; - - if (stdoutDone && watchdogTimer != null) { - watchdogTimer.cancel(); - } - } - } - // Close stdin so that tests that try to block on input will fail. process.stdin.close(); timeoutHandler() async { @@ -507,30 +524,31 @@ class RunningProcess { } } - stdoutSubscription.asFuture().then(closeStdout); - stderrSubscription.asFuture().then(closeStderr); - - process.exitCode.then((exitCode) { - if (!stdoutDone || !stderrDone) { - watchdogTimer = new Timer(MAX_STDIO_DELAY, () { - DebugLogger.warning( - "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)"); - watchdogTimer = null; - stdoutSubscription.cancel(); - stderrSubscription.cancel(); - closeStdout(); - closeStderr(); - }); - } - - Future.wait([stdoutCompleter.future, stderrCompleter.future]) - .then((_) { + // Wait for the process to finish or timeout + process.exitCode + .timeout(Duration(seconds: timeout), onTimeout: timeoutHandler) + .then((exitCode) { + // This timeout is used to close stdio to the subprocess once we got + // the exitCode. Sometimes descendants of the subprocess keep stdio + // handles alive even though the direct subprocess is dead. + Future.wait([stdoutFuture, stderrFuture]).timeout(MAX_STDIO_DELAY, + onTimeout: () async { + DebugLogger.warning( + "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)"); + await stdout.cancel(); + await stderr.cancel(); + _commandComplete(exitCode); + return null; + }).then((_) { + if (stdout is FileOutputLog) { + // Prevent logging data that has already been written to a file + // and is unlikely too add value in the logs because the command + // succeeded. + stdout.complete = []; + } _commandComplete(exitCode); }); }); - - timeoutTimer = - new Timer(new Duration(seconds: timeout), timeoutHandler); }).catchError((e) { // TODO(floitsch): should we try to report the stacktrace? print("Process error:"); @@ -543,9 +561,6 @@ class RunningProcess { } void _commandComplete(int exitCode) { - if (timeoutTimer != null) { - timeoutTimer.cancel(); - } var commandOutput = _createCommandOutput(command, exitCode); completer.complete(commandOutput); } @@ -573,11 +588,6 @@ class RunningProcess { return commandOutput; } - StreamSubscription _drainStream( - Stream> source, OutputLog destination) { - return source.listen(destination.add); - } - Map _createProcessEnvironment() { var environment = new Map.from(io.Platform.environment); @@ -1209,7 +1219,8 @@ class CommandExecutorImpl implements CommandExecutor { return _getBatchRunner(name) .runCommand(name, command, timeout, command.arguments); } else if (command is CompilationCommand && - globalConfiguration.batchDart2JS) { + globalConfiguration.batchDart2JS && + command.displayName == 'dart2js') { return _getBatchRunner("dart2js") .runCommand("dart2js", command, timeout, command.arguments); } else if (command is AnalysisCommand && globalConfiguration.batch) { @@ -1243,6 +1254,12 @@ class CommandExecutorImpl implements CommandExecutor { var name = command.displayName; return _getBatchRunner(command.displayName + command.dartFile) .runCommand(name, command, timeout, command.arguments); + } else if (command is CompilationCommand && + command.displayName == 'babel') { + return new RunningProcess(command, timeout, + configuration: globalConfiguration, + outputFile: io.File(command.outputFile)) + .run(); } else if (command is ProcessCommand) { return new RunningProcess(command, timeout, configuration: globalConfiguration) diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart index 620245507a0..f00c75dedea 100644 --- a/tools/testing/dart/test_suite.dart +++ b/tools/testing/dart/test_suite.dart @@ -140,12 +140,6 @@ abstract class TestSuite { Map get environmentOverrides => _environmentOverrides; - /** - * Whether or not binaries should be found in the root build directory or - * in the built SDK. - */ - bool get useSdk => configuration.useSdk; - /** * The output directory for this suite's configuration. */ @@ -165,80 +159,6 @@ abstract class TestSuite { return name; } - /// Returns the name of the Dart VM executable. - String get dartVmBinaryFileName { - // Controlled by user with the option "--dart". - var dartExecutable = configuration.dartPath; - - if (dartExecutable == null) { - dartExecutable = dartVmExecutableFileName; - } - - TestUtils.ensureExists(dartExecutable, configuration); - return dartExecutable; - } - - String get dartVmExecutableFileName { - return useSdk - ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix' - : '$buildDir/dart$executableBinarySuffix'; - } - - String get dartPrecompiledBinaryFileName { - // Controlled by user with the option "--dart_precompiled". - var dartExecutable = configuration.dartPrecompiledPath; - - if (dartExecutable == null || dartExecutable == '') { - var suffix = executableBinarySuffix; - dartExecutable = '$buildDir/dart_precompiled_runtime$suffix'; - } - - TestUtils.ensureExists(dartExecutable, configuration); - return dartExecutable; - } - - String get processTestBinaryFileName { - var suffix = executableBinarySuffix; - var processTestExecutable = '$buildDir/process_test$suffix'; - TestUtils.ensureExists(processTestExecutable, configuration); - return processTestExecutable; - } - - String get d8FileName { - var suffix = getExecutableSuffix('d8'); - var d8Dir = Repository.dir.append('third_party/d8'); - var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix'); - var d8 = d8Path.toNativePath(); - TestUtils.ensureExists(d8, configuration); - return d8; - } - - String get jsShellFileName { - var executableSuffix = getExecutableSuffix('jsshell'); - var executable = 'jsshell$executableSuffix'; - var jsshellDir = '${Repository.dir.toNativePath()}/tools/testing/bin'; - return '$jsshellDir/$executable'; - } - - /** - * The file extension (if any) that should be added to the given executable - * name for the current platform. - */ - // TODO(ahe): Get rid of this. Use executableBinarySuffix instead. - String getExecutableSuffix(String executable) { - if (Platform.operatingSystem == 'windows') { - if (executable == 'd8' || executable == 'vm' || executable == 'none') { - return '.exe'; - } else { - return '.bat'; - } - } - return ''; - } - - String get executableBinarySuffix => Platform.isWindows ? '.exe' : ''; - String get executableScriptSuffix => Platform.isWindows ? '.bat' : ''; - /** * Call the callback function onTest with a [TestCase] argument for each * test in the suite. When all tests have been processed, call [onDone]. @@ -585,7 +505,7 @@ class StandardTestSuite extends TestSuite { extraVmOptions = configuration.vmOptions, super(configuration, suiteName, statusFilePaths) { // Initialize _dart2JsBootstrapDependencies - if (!useSdk) { + if (!configuration.useSdk) { _dart2JsBootstrapDependencies = []; } else { _dart2JsBootstrapDependencies = [ @@ -933,7 +853,6 @@ class StandardTestSuite extends TestSuite { return commands ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands( - this, compilationArtifact, runtimeArguments, environment, @@ -1028,30 +947,28 @@ class StandardTestSuite extends TestSuite { var fileName = info.filePath.toNativePath(); var optionsFromFile = info.optionsFromFile; var compilationTempDir = createCompilationOutputDirectory(info.filePath); - var jsWrapperFileName = '$compilationTempDir/test.js'; var nameNoExt = info.filePath.filenameWithoutExtension; + var outputDir = compilationTempDir; + var commonArguments = + commonArgumentsFromFile(info.filePath, optionsFromFile); // Use existing HTML document if available. String content; var customHtml = new File( info.filePath.directoryPath.append('$nameNoExt.html').toNativePath()); if (customHtml.existsSync()) { - jsWrapperFileName = '$tempDir/$nameNoExt.js'; + outputDir = tempDir; content = customHtml.readAsStringSync().replaceAll( '%TEST_SCRIPTS%', ''); } else { // Synthesize an HTML file for the test. if (configuration.compiler == Compiler.dart2js) { - var scriptPath = _createUrlPathFromFile(new Path(jsWrapperFileName)); + var scriptPath = _createUrlPathFromFile( + new Path('$compilationTempDir/$nameNoExt.js')); content = dart2jsHtml(fileName, scriptPath); } else { var jsDir = new Path(compilationTempDir).relativeTo(Repository.dir).toString(); - jsWrapperFileName = - new Path('$compilationTempDir/$nameNoExt.js').toNativePath(); - // Always run with synchronous starts of `async` functions. - // If we want to make this dependent on other parameters or flags, - // this flag could be become conditional. content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler); } } @@ -1062,36 +979,21 @@ class StandardTestSuite extends TestSuite { // Construct the command(s) that compile all the inputs needed by the // browser test. var commands = []; + const supportedCompilers = { + Compiler.dart2js, + Compiler.dartdevc, + Compiler.dartdevk + }; + assert(supportedCompilers.contains(configuration.compiler)); + var sharedOptions = optionsFromFile["sharedOptions"] as List; + var dart2jsOptions = optionsFromFile["dart2jsOptions"] as List; + var ddcOptions = optionsFromFile["ddcOptions"] as List; - void addCompileCommand(String fileName, String toPath) { - switch (configuration.compiler) { - case Compiler.dart2js: - commands.add(_dart2jsCompileCommand( - fileName, toPath, tempDir, optionsFromFile)); - break; - - case Compiler.dartdevc: - case Compiler.dartdevk: - var ddcOptions = optionsFromFile["sharedOptions"] as List; - ddcOptions.addAll(optionsFromFile["ddcOptions"] as List); - commands.add(configuration.compilerConfiguration.createCommand( - fileName, toPath, ddcOptions, environmentOverrides)); - break; - - default: - assert(false); - } - } - - addCompileCommand(fileName, jsWrapperFileName); - - // Some tests require compiling multiple input scripts. - for (var name in optionsFromFile['otherScripts'] as List) { - var namePath = new Path(name); - var fromPath = info.filePath.directoryPath.join(namePath).toNativePath(); - var toPath = new Path('$tempDir/${namePath.filename}.js').toNativePath(); - addCompileCommand(fromPath, toPath); - } + var args = configuration.compilerConfiguration.computeCompilerArguments( + null, sharedOptions, null, dart2jsOptions, ddcOptions, commonArguments); + var compilation = configuration.compilerConfiguration + .computeCompilationArtifact(outputDir, args, environmentOverrides); + commands.addAll(compilation.commands); if (info.optionsFromFile['isMultiHtmlTest'] as bool) { // Variables for browser multi-tests. @@ -1128,43 +1030,6 @@ class StandardTestSuite extends TestSuite { enqueueNewTestCase(fullName, commands, expectations, info); } - /// Creates a [Command] to compile a single .dart file using dart2js. - Command _dart2jsCompileCommand(String inputFile, String outputFile, - String dir, Map optionsFromFile) { - var args = []; - - if (compilerPath.endsWith('.dart')) { - // Run the compiler script via the Dart VM. - args.add(compilerPath); - } - - args.addAll(configuration.standardOptions); - args.addAll(configuration.dart2jsOptions); - - var packages = packagesArgument(optionsFromFile['packageRoot'] as String, - optionsFromFile['packages'] as String); - if (packages != null) args.add(packages); - - args.add('--out=$outputFile'); - args.add(inputFile); - - var options = optionsFromFile['sharedOptions'] as List; - if (options != null) args.addAll(options); - options = optionsFromFile['dart2jsOptions'] as List; - if (options != null) args.addAll(options); - if (configuration.compiler == Compiler.dart2js) { - if (configuration.noPreviewDart2) { - args.add("--no-preview-dart-2"); - } else { - args.add("--preview-dart-2"); - } - } - - return Command.compilation(Compiler.dart2js.name, outputFile, - dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides, - alwaysCompile: !useSdk); - } - List commonArgumentsFromFile( Path filePath, Map optionsFromFile) { var args = configuration.standardOptions.toList(); @@ -1185,14 +1050,6 @@ class StandardTestSuite extends TestSuite { } } - if (configuration.compiler == Compiler.dart2js) { - if (configuration.noPreviewDart2) { - args.add("--no-preview-dart-2"); - } else { - args.add("--preview-dart-2"); - } - } - args.add(filePath.toNativePath()); return args; @@ -1241,12 +1098,6 @@ class StandardTestSuite extends TestSuite { * // Environment=ENV_VAR1=foo bar * // Environment=ENV_VAR2=bazz * - * - For tests that depend on compiling other files with dart2js (e.g. - * isolate tests that use multiple source scripts), you can specify - * additional files to compile using a comment too, as follows: - * - * // OtherScripts=file1.dart file2.dart - * * - Most tests are not web tests, but can (and will be) wrapped within * an HTML file and another script file to test them also on browser * environments (e.g. language and corelib tests are run this way). @@ -1272,7 +1123,6 @@ class StandardTestSuite extends TestSuite { } RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)"); RegExp environmentRegExp = new RegExp(r"// Environment=(.*)"); - RegExp otherScriptsRegExp = new RegExp(r"// OtherScripts=(.*)"); RegExp otherResourcesRegExp = new RegExp(r"// OtherResources=(.*)"); RegExp sharedObjectsRegExp = new RegExp(r"// SharedObjects=(.*)"); RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)"); @@ -1365,12 +1215,6 @@ class StandardTestSuite extends TestSuite { } } - var otherScripts = []; - matches = otherScriptsRegExp.allMatches(contents); - for (var match in matches) { - otherScripts.addAll(wordSplit(match[1])); - } - var otherResources = []; matches = otherResourcesRegExp.allMatches(contents); for (var match in matches) { @@ -1438,7 +1282,6 @@ class StandardTestSuite extends TestSuite { "hasCompileError": hasCompileError, "hasRuntimeError": hasRuntimeError, "hasStaticWarning": hasStaticWarning, - "otherScripts": otherScripts, "otherResources": otherResources, "sharedObjects": sharedObjects, "isMultitest": isMultitest, @@ -1461,7 +1304,6 @@ class StandardTestSuite extends TestSuite { "hasCompileError": false, "hasRuntimeError": false, "hasStaticWarning": false, - "otherScripts": const [], "isMultitest": false, "isMultiHtmlTest": false, "subtestNames": const [],