[CFE] Add test for running old dills
This CL:
* adds a test that runs the VM with old dills (compilations of dart2js
with old checkouts) with the --compile_all argument (1).
* adds a number of old dills (for binary version 25, 27, 28, 29)
(by mistake binary version 26 sort of didn't really happen)
* adds a PRESUBMIT check in kernel that verifies that we have an
"old dill" for the current binary version, so one don't bump the
version without creating a new dill.
(1): It uses --compile_all to force the VM to "read and understand"
everything in the dill file. The hope being that we try out
all/most language constructs and thus verifies that they can be
read by the VM.
Old "old dill" files should be removed once the VM stops supporting that
version. That is a manual process, but a test should complain that the VM
cannot read the old "old dill"(s) once/if that happens.
This should (help) detect errors such as the one recently where a merge
error caused a single "if >= 28" (that should have been "if >= 29" and
thus stopped the VM from reading dills from version 28) to slip through
and require a lot of debugging a few days later.
Change-Id: Id79e16c7ad896c0ccc4e181465b05b67822ac31a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/113698
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/test/old_dill_test.dart b/pkg/front_end/test/old_dill_test.dart
new file mode 100644
index 0000000..df757c40
--- /dev/null
+++ b/pkg/front_end/test/old_dill_test.dart
@@ -0,0 +1,128 @@
+// 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.
+
+import 'dart:async' show Future;
+
+import 'dart:io';
+
+import 'package:kernel/binary/tag.dart' show Tag;
+
+import 'package:testing/testing.dart'
+ show ChainContext, Result, Step, TestDescription, Chain, runMe;
+
+Future<Null> main([List<String> arguments = const []]) async {
+ if (arguments.length == 1 && arguments[0] == "--generate") {
+ print("Should now generate a dill of dart2js.");
+ await generateDill();
+ return null;
+ } else if (arguments.length == 1 && arguments[0] == "--checkDill") {
+ await checkDill();
+ return null;
+ }
+ await runMe(arguments, createContext, "../testing.json");
+ await checkDill();
+}
+
+String get dartVm => Platform.resolvedExecutable;
+
+Uri generateOutputUri(int binaryVersion, int compileNumber) {
+ return Uri.base.resolve("pkg/front_end/testcases/old_dills/"
+ "dart2js"
+ ".version.$binaryVersion"
+ ".compile.$compileNumber"
+ ".dill");
+}
+
+verifyNotUsingCheckedInDart() {
+ String vm = dartVm.replaceAll(r"\", "/");
+ if (vm.contains("tools/sdks/dart-sdk/bin/dart")) {
+ throw "Running with checked-in VM which is not supported";
+ }
+}
+
+Future<Null> checkDill() async {
+ Uri uri = generateOutputUri(Tag.BinaryFormatVersion, 1);
+ if (!new File.fromUri(uri).existsSync()) {
+ print("File $uri doesn't exist. Generate running script");
+ print("${Platform.script.toFilePath()} --generate");
+ exit(1);
+ }
+}
+
+Future<Null> generateDill() async {
+ Uri fastaCompile = Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart");
+ if (!new File.fromUri(fastaCompile).existsSync()) {
+ throw "compile.dart from fasta tools couldn't be found";
+ }
+
+ Uri dart2js = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+ if (!new File.fromUri(dart2js).existsSync()) {
+ throw "dart2js couldn't be found";
+ }
+
+ int compileNumber = 0;
+ Uri output;
+ do {
+ compileNumber++;
+ output = generateOutputUri(Tag.BinaryFormatVersion, compileNumber);
+ } while (new File.fromUri(output).existsSync());
+
+ ProcessResult result = await Process.run(
+ dartVm,
+ [
+ fastaCompile.toFilePath(),
+ "sdkroot:/pkg/compiler/bin/dart2js.dart",
+ "-o",
+ output.toFilePath(),
+ "--target=vm",
+ "--single-root-base=${Uri.base.toFilePath()}",
+ "--single-root-scheme=sdkroot",
+ ],
+ workingDirectory: Uri.base.toFilePath());
+ if (result.exitCode != 0) {
+ print("stdout: ${result.stdout}");
+ print("stderr: ${result.stderr}");
+ print("Exit code: ${result.exitCode}");
+ throw "Got exit code ${result.exitCode}";
+ } else {
+ print("File generated.");
+ }
+}
+
+Future<Context> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new Context();
+}
+
+class Context extends ChainContext {
+ final List<Step> steps = const <Step>[
+ const RunDill(),
+ ];
+}
+
+class RunDill extends Step<TestDescription, TestDescription, Context> {
+ const RunDill();
+
+ String get name => "RunDill";
+
+ Future<Result<TestDescription>> run(
+ TestDescription description, Context context) async {
+ verifyNotUsingCheckedInDart();
+ ProcessResult result = await Process.run(
+ dartVm,
+ [
+ "--compile_all",
+ description.uri.toFilePath(),
+ "-h",
+ ],
+ workingDirectory: Uri.base.toFilePath());
+ print("stdout: ${result.stdout}");
+ print("stderr: ${result.stderr}");
+ print("Exit code: ${result.exitCode}");
+ if (result.exitCode != 0) {
+ return fail(description, "Got exit code ${result.exitCode}");
+ }
+ return pass(description);
+ }
+}
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 794a2a1..df8d7bd 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -108,6 +108,7 @@
dictionary
differs
dillfile
+dills
dirname
disagree
disconnect
@@ -316,6 +317,8 @@
scans
screen
scripts
+sdkroot
+sdks
secondary
seconds
segment
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill
new file mode 100644
index 0000000..deb7a1a
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill
new file mode 100644
index 0000000..40f0b90
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill
new file mode 100644
index 0000000..606bbf1
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill
new file mode 100644
index 0000000..060ab45
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/old_dills.status b/pkg/front_end/testcases/old_dills/old_dills.status
new file mode 100644
index 0000000..e22cfe5
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/old_dills.status
@@ -0,0 +1,3 @@
+# 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.md file.
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 3f10468..9ee45ec 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -221,6 +221,19 @@
},
{
+ "name": "old_dill_test",
+ "kind": "Chain",
+ "source": "test/old_dill_test.dart",
+ "path": "testcases/old_dills/",
+ "status": "testcases/old_dills/old_dills.status",
+ "pattern": [
+ ".*\\.dill$"
+ ],
+ "exclude": [
+ ]
+ },
+
+ {
"name": "lint_test",
"kind": "Chain",
"source": "test/lint_test.dart",
diff --git a/pkg/kernel/PRESUBMIT.py b/pkg/kernel/PRESUBMIT.py
new file mode 100644
index 0000000..9d898e4
--- /dev/null
+++ b/pkg/kernel/PRESUBMIT.py
@@ -0,0 +1,61 @@
+# 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.
+"""Front-end specific presubmit script.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+import imp
+import os.path
+import subprocess
+
+
+def runSmokeTest(input_api, output_api):
+ hasChangedFiles = False
+ for git_file in input_api.AffectedTextFiles():
+ filename = git_file.AbsoluteLocalPath()
+ if filename.endswith(".dart"):
+ hasChangedFiles = True
+ break
+
+ if hasChangedFiles:
+ local_root = input_api.change.RepositoryRoot()
+ utils = imp.load_source('utils',
+ os.path.join(local_root, 'tools', 'utils.py'))
+ dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
+ smoke_test = os.path.join(local_root, 'pkg', 'kernel', 'tool',
+ 'smoke_test_quick.dart')
+
+ windows = utils.GuessOS() == 'win32'
+ if windows:
+ dart += '.exe'
+
+ if not os.path.isfile(dart):
+ print('WARNING: dart not found: %s' % dart)
+ return []
+
+ if not os.path.isfile(smoke_test):
+ print('WARNING: kernel smoke test not found: %s' % smoke_test)
+ return []
+
+ args = [dart, smoke_test]
+ process = subprocess.Popen(
+ args, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+ outs, _ = process.communicate()
+
+ if process.returncode != 0:
+ return [output_api.PresubmitError(
+ 'Kernel smoke test failure(s):',
+ long_text=outs)]
+
+ return []
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return runSmokeTest(input_api, output_api)
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return runSmokeTest(input_api, output_api)
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
new file mode 100644
index 0000000..2065aea
--- /dev/null
+++ b/pkg/kernel/tool/smoke_test_quick.dart
@@ -0,0 +1,62 @@
+// 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.
+
+import 'dart:io';
+
+final String repoDir = _computeRepoDir();
+
+String get dartVm => Platform.executable;
+
+main(List<String> args) async {
+ Stopwatch stopwatch = new Stopwatch()..start();
+ List<Future> futures = new List<Future>();
+ futures.add(run("pkg/front_end/test/old_dill_test.dart", ["--checkDill"]));
+ await Future.wait(futures);
+ print("\n-----------------------\n");
+ print("Done with exitcode $exitCode in ${stopwatch.elapsedMilliseconds} ms");
+}
+
+Future<void> run(String script, List<String> scriptArguments,
+ {bool filter: true}) async {
+ List<String> arguments = [];
+ arguments.add("$script");
+ arguments.addAll(scriptArguments);
+
+ Stopwatch stopwatch = new Stopwatch()..start();
+ ProcessResult result =
+ await Process.run(dartVm, arguments, workingDirectory: repoDir);
+ String runWhat = "${dartVm} ${arguments.join(' ')}";
+ if (result.exitCode != 0) {
+ exitCode = result.exitCode;
+ print("-----");
+ print("Running: $runWhat: "
+ "Failed with exit code ${result.exitCode} "
+ "in ${stopwatch.elapsedMilliseconds} ms.");
+ String stdout = result.stdout.toString();
+ if (filter) {
+ List<String> lines = stdout.split("\n");
+ int lastIgnored = -1;
+ for (int i = 0; i < lines.length; i++) {
+ if (lines[i].startsWith("[ ")) lastIgnored = i;
+ }
+ lines.removeRange(0, lastIgnored + 1);
+ stdout = lines.join("\n");
+ }
+ stdout = stdout.trim();
+ if (stdout.isNotEmpty) {
+ print(stdout);
+ print("-----");
+ }
+ } else {
+ print("Running: $runWhat: Done in ${stopwatch.elapsedMilliseconds} ms.");
+ }
+}
+
+String _computeRepoDir() {
+ ProcessResult result = Process.runSync(
+ 'git', ['rev-parse', '--show-toplevel'],
+ runInShell: true,
+ workingDirectory: new File.fromUri(Platform.script).parent.path);
+ return (result.stdout as String).trim();
+}