blob: 2f175a5a440f762e1cb83a522b7bc32199aff90d [file] [log] [blame]
#!/usr/bin/env dart
import 'dart:async';
import 'dart:io';
import 'dart:io' as io;
import 'package:path/path.dart' as path;
const List<String> globalKnobs = const <String>[
/// Global knobs we want to turn on for all tests. But please be aware these
/// can make the tests fail. Use them via e.g. '-Dknobs.nullable.ints=true'
/// here.
];
final root = path.relative(Platform.script.resolve('.').toFilePath());
final testDir = path.join(root, 'vipunen/tests');
final vipunen = path.join(root, 'vipunen/bin/compile.dart');
final fasta = path.join(root, 'pkg/front_end/tool/fasta');
final transform = path.join(root, 'pkg/kernel/bin/transform.dart');
main(args) async {
if (args.length == 0 || !['debug', 'release'].contains(args[0])) {
print('Usage: ${Platform.executable} ${Platform.script} [debug|release]'
'<selector>');
exit(1);
}
String selector;
if (args.length == 2) {
selector = args[1];
}
final config = args[0] == 'debug' ? 'DebugX64' : 'ReleaseX64';
final buildRoot = Platform.isMacOS ? 'xcodebuild' : 'out';
final buildDir = path.join(root, '${buildRoot}/$config');
final failures = [];
final futures = <Future>[];
for (final String testFile in scanTests()) {
if (selector != null && !testFile.contains(selector)) continue;
final Set<String> flags = flagsFromFile(testFile);
flags.addAll(globalKnobs);
final dirname = path.dirname(testFile);
final basename = path.basename(testFile);
final dillFile = '$dirname/$basename.dill';
final shakenDillFile = '$dirname/$basename.shaken.dill';
final closuresDillFile = '$dirname/$basename.vipclosures.dill';
final methodcallDillFile = '$dirname/$basename.vipclosures.methodcall.dill';
final constantsDillFile =
'$dirname/$basename.vipclosures.methodcall.constants.dill';
final asmFile = '$dirname/$basename.S';
final soFile = '$dirname/$basename.so';
final printedLines = <String>[];
futures.add(runZoned(() async {
print('\nTesting $testFile:\n----------------------------------------');
final ok = await runFasta(buildDir, testFile, dillFile) &&
await transformIt('treeshake', dillFile, shakenDillFile) &&
await transformIt('vipclosures', shakenDillFile, closuresDillFile) &&
await transformIt(
'methodcall', closuresDillFile, methodcallDillFile) &&
await transformIt(
'constants', methodcallDillFile, constantsDillFile) &&
await compileIt(flags, buildDir, constantsDillFile, asmFile) &&
await assembleIt(asmFile, soFile) &&
await runIt(buildDir, soFile);
if (!ok) failures.add(testFile);
return printedLines;
}, zoneSpecification: new ZoneSpecification(print: (_, _1, _2, line) {
printedLines.add(line);
})));
}
for (final lines in await Future.wait(futures)) {
lines.forEach(print);
}
if (failures.isEmpty) {
print('ALL TESTS PASSED');
} else {
for (var test in failures) {
print("FAIL $test");
}
}
}
List<String> scanTests() {
return new Directory(testDir)
.listSync()
.where((fse) => fse is File && fse.path.endsWith('_test.dart'))
.map((file) => file.path)
.toList();
}
Future<bool> runFasta(String buildDir, String testFile, String dillFile) {
final args = [
'compile',
'-o',
dillFile,
'--platform=$buildDir/vm_platform.dill',
testFile,
];
return run(args, fasta);
}
Future<bool> transformIt(
String transformer, String fromDillFile, String toDillFile) {
return run([
'-c',
transform,
'-f',
'bin',
'-t',
transformer,
'-o',
toDillFile,
fromDillFile,
], Platform.executable);
}
Future<bool> compileIt(
Set<String> flags, String buildDir, String dillFile, String asmFile) {
final environment = new Map<String, String>.from(Platform.environment);
environment['LD_LIBRARY_PATH'] = buildDir;
return run(
[]
..addAll(flags)
..addAll(['--checked', vipunen, '-o', asmFile, dillFile]),
Platform.executable,
environment);
}
Future assembleIt(String asmFile, String soFile) {
return run(['-shared', '-fPIC', '-o', soFile, asmFile], 'g++');
}
Future runIt(String buildDir, String soFile) async {
return run(
[path.join(root, '.run.dart'), soFile], path.join(buildDir, 'dart'));
}
Future<bool> run(List<String> arguments,
[String executable, Map<String, String> environment]) async {
if (executable == null) executable = Platform.executable;
print('Running "$executable ${arguments.join(' ')}"');
final ProcessResult result = await Process.run(executable, arguments,
environment: environment, runInShell: true);
return checkResult(result.exitCode, result.stdout, result.stderr);
}
bool checkResult(int exitCode, String stdout, String stderr) {
if (exitCode != 0) {
print(' -> Failed with ${exitCode}');
print(' stdout: \n ${stdout.split('\n').join('\n ')}');
print(' stderr: \n ${stderr.split('\n').join('\n ')}');
io.exitCode = exitCode;
return false;
}
return true;
}
Set<String> flagsFromFile(String testFile) {
const String kPattern = '/// VipunenCompilerDefine=';
final Set<String> flags = new Set<String>();
for (final String line in new File(testFile).readAsLinesSync()) {
if (line.startsWith(kPattern)) {
flags.add(line.substring(kPattern.length));
}
}
return flags;
}