blob: c84561acd18f5ee54aed35ceae1ece83e4228ff4 [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;
import 'use_flag_test_helper.dart';
export 'use_flag_test_helper.dart';
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}',
);
}
}
Future<Result> runDart(
String prefix,
List<String> arguments, {
bool printOut = true,
}) {
final augmentedArguments = <String>[]
..addAll(Platform.executableArguments)
..add('--verbosity=warning')
..addAll(arguments);
return runBinary(
prefix,
Platform.executable,
augmentedArguments,
printOut: printOut,
);
}
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, [genKernelDart, ...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,
bool printOut = true,
}) 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 (printOut && processResult.stdout.isNotEmpty) {
print('''
Command stdout:
${processResult.stdout}''');
}
if (printOut && 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 {
return 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);
});
}