blob: 476b2054d1cc93d8444bcc0af2c562b41f10f71f [file] [log] [blame]
// Copyright (c) 2018, 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';
import 'dart:io';
import 'dart:math';
import 'package:expect/expect.dart';
import 'package:path/path.dart' as p;
class Result {
final String cmdline;
final ProcessResult processResult;
Result(this.cmdline, this.processResult);
String get output => processResult.stdout.trim();
}
void reportError(Result result, String msg) {
print('running ${result.cmdline}:');
if (result.processResult.stdout.isNotEmpty) {
print('''
Command stdout:
${result.processResult.stdout}''');
}
if (result.processResult.stderr.isNotEmpty) {
print('''
Command stderr:
${result.processResult.stderr}''');
}
Expect.fail(msg);
}
void expectOutput(String what, Result result) {
if (result.output != what) {
reportError(
result,
'Expected test to print \'${what}\' to stdout. '
'Actual: ${result.output}');
}
}
final String scriptSuffix = Platform.isWindows ? ".bat" : "";
final String executableSuffix = Platform.isWindows ? ".exe" : "";
final String buildDir = p.dirname(Platform.executable);
final String platformDill = p.join(buildDir, "vm_platform_strong.dill");
final String genSnapshot = p.join(buildDir, "gen_snapshot${executableSuffix}");
final String dart = p.join(buildDir, "dart${executableSuffix}");
final String dartPrecompiledRuntime =
p.join(buildDir, "dart_precompiled_runtime${executableSuffix}");
final String genKernel = p.join("pkg", "vm", "bin", "gen_kernel.dart");
final String checkedInDartVM =
p.join("tools", "sdks", "dart-sdk", "bin", "dart${executableSuffix}");
Future<Result> runDart(String prefix, List<String> arguments) {
final augmentedArguments = <String>[]
..addAll(Platform.executableArguments)
..add('--verbosity=warning')
..addAll(arguments);
return runBinary(prefix, Platform.executable, augmentedArguments);
}
Future<Result> runGenKernel(String prefix, List<String> arguments) {
final augmentedArguments = <String>[
"--platform",
platformDill,
...Platform.executableArguments.where((arg) =>
arg.startsWith('--enable-experiment=') ||
arg == '--sound-null-safety' ||
arg == '--no-sound-null-safety'),
...arguments,
];
return runGenKernelWithoutStandardOptions(prefix, augmentedArguments);
}
Future<Result> runGenKernelWithoutStandardOptions(
String prefix, List<String> arguments) {
return runBinary(prefix, checkedInDartVM, [genKernel, ...arguments]);
}
Future<Result> runGenSnapshot(String prefix, List<String> arguments) {
return runBinary(prefix, genSnapshot, arguments);
}
Future<Result> runBinary(String prefix, String binary, List<String> arguments,
{Map<String, String> environment, bool runInShell: false}) async {
print("+ $binary " + arguments.join(" "));
final processResult = await Process.run(binary, arguments,
environment: environment, runInShell: runInShell);
final result =
new Result('[$prefix] ${binary} ${arguments.join(' ')}', processResult);
if (processResult.stdout.isNotEmpty) {
print('''
Command stdout:
${processResult.stdout}''');
}
if (processResult.stderr.isNotEmpty) {
print('''
Command stderr:
${processResult.stderr}''');
}
if (result.processResult.exitCode != 0) {
reportError(result,
'[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
}
return result;
}
withTempDir(Future fun(String dir)) async {
final Directory tempDir = Directory.systemTemp.createTempSync();
try {
await fun(tempDir.path);
} finally {
tempDir.deleteSync(recursive: true);
}
}
checkDeterministicSnapshot(String snapshotKind, String expectedStdout) async {
await withTempDir((String temp) async {
final snapshot1Path = p.join(temp, 'snapshot1');
final snapshot2Path = p.join(temp, 'snapshot2');
print("Version ${Platform.version}");
final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
'--deterministic',
'--trace_class_finalization',
'--trace_type_finalization',
'--trace_compiler',
'--verbose_gc',
'--verbosity=warning',
'--snapshot=$snapshot1Path',
'--snapshot-kind=$snapshotKind',
Platform.script.toFilePath(),
'--child',
]);
expectOutput(expectedStdout, generate1Result);
final generate2Result = await runDart('GENERATE SNAPSHOT 2', [
'--deterministic',
'--trace_class_finalization',
'--trace_type_finalization',
'--trace_compiler',
'--verbose_gc',
'--verbosity=warning',
'--snapshot=$snapshot2Path',
'--snapshot-kind=$snapshotKind',
Platform.script.toFilePath(),
'--child',
]);
expectOutput(expectedStdout, generate2Result);
var snapshot1Bytes = await new File(snapshot1Path).readAsBytes();
var snapshot2Bytes = await new File(snapshot2Path).readAsBytes();
var minLength = min(snapshot1Bytes.length, snapshot2Bytes.length);
for (var i = 0; i < minLength; i++) {
if (snapshot1Bytes[i] != snapshot2Bytes[i]) {
Expect.fail("Snapshots differ at byte $i");
}
}
Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
});
}
runAppJitTest(Uri testScriptUri,
{Future<Result> Function(String snapshotPath) runSnapshot}) async {
runSnapshot ??=
(snapshotPath) => runDart('RUN FROM SNAPSHOT', [snapshotPath]);
await withTempDir((String temp) async {
final snapshotPath = p.join(temp, 'app.jit');
final testPath = testScriptUri.toFilePath();
final trainingResult = await runDart('TRAINING RUN', [
'--snapshot=$snapshotPath',
'--snapshot-kind=app-jit',
'--verbosity=warning',
testPath,
'--train'
]);
expectOutput("OK(Trained)", trainingResult);
final runResult = await runSnapshot(snapshotPath);
expectOutput("OK(Run)", runResult);
});
}