blob: 4c3b9a5611096f08482f800b31974bf16c446ad8 [file] [log] [blame]
// Copyright (c) 2016, 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.
library test.kernel.closures.suite;
import 'dart:async' show Future;
import 'dart:io' show Directory, File, Platform;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:kernel/analyzer/loader.dart'
show DartLoader, DartOptions, createDartSdk;
import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget;
import 'package:kernel/repository.dart' show Repository;
import 'kernel_chain.dart'
show MatchExpectation, Print, ReadDill, SanityCheck, WriteDill;
import 'package:testing/testing.dart'
show
Chain,
ChainContext,
Result,
StdioProcess,
Step,
TestDescription,
runMe;
import 'package:kernel/ast.dart' show Program;
import 'package:kernel/transformations/closure_conversion.dart'
as closure_conversion;
import 'package:package_config/discovery.dart' show loadPackagesFile;
class TestContext extends ChainContext {
final Uri vm;
final Uri packages;
final DartOptions options;
final DartSdk dartSdk;
final List<Step> steps;
TestContext(String sdk, this.vm, Uri packages, bool strongMode, this.dartSdk,
bool updateExpectations)
: packages = packages,
options = new DartOptions(
strongMode: strongMode,
sdk: sdk,
packagePath: packages.toFilePath()),
steps = <Step>[
const Kernel(),
const Print(),
const SanityCheck(),
const ClosureConversion(),
const Print(),
const SanityCheck(),
new MatchExpectation(".expect",
updateExpectations: updateExpectations),
const WriteDill(),
const ReadDill(),
const Run(),
];
Future<DartLoader> createLoader() async {
Repository repository = new Repository();
return new DartLoader(repository, options, await loadPackagesFile(packages),
dartSdk: dartSdk);
}
}
enum Environment {
directory,
file,
}
Future<String> getEnvironmentVariable(
String name, Environment kind, String undefined, notFound(String n)) async {
String result = Platform.environment[name];
if (result == null) {
throw undefined;
}
switch (kind) {
case Environment.directory:
if (!await new Directory(result).exists()) throw notFound(result);
break;
case Environment.file:
if (!await new File(result).exists()) throw notFound(result);
break;
}
return result;
}
Future<bool> fileExists(Uri base, String path) async {
return await new File.fromUri(base.resolve(path)).exists();
}
Future<TestContext> createContext(
Chain suite, Map<String, String> environment) async {
const String suggestion = """Try building the patched SDK by running
'tools/build.py patched_sdk'""";
// TODO(karlklose): The path is different on MacOS.
String sdk = "out/DebugX64/patched_sdk/";
Uri sdkUri = Uri.base.resolve(sdk);
const String asyncDart = "lib/async/async.dart";
if (!await fileExists(sdkUri, asyncDart)) {
throw "Couldn't find the patched SDK. $suggestion";
}
const String asyncSources = "lib/async/async_sources.gypi";
if (await fileExists(sdkUri, asyncSources)) {
throw "Found '$asyncSources' in '$sdk', so it isn't a patched SDK. "
"$suggestion";
}
// TODO(karlklose): select the VM based on the mode.
Uri vm = Uri.base.resolve("out/ReleaseX64/dart");
Uri packages = Uri.base.resolve(".packages");
bool strongMode = false;
bool updateExpectations = environment["updateExpectations"] != "false";
return new TestContext(sdk, vm, packages, strongMode,
createDartSdk(sdk, strongMode: strongMode), updateExpectations);
}
class Kernel extends Step<TestDescription, Program, TestContext> {
const Kernel();
String get name => "kernel";
Future<Result<Program>> run(
TestDescription description, TestContext testContext) async {
try {
DartLoader loader = await testContext.createLoader();
Target target = getTarget(
"vm", new TargetFlags(strongMode: testContext.options.strongMode));
String path = description.file.path;
Uri uri = Uri.base.resolve(path);
Program program = loader.loadProgram(uri, target: target);
for (var error in loader.errors) {
return fail(program, "$error");
}
target.transformProgram(program);
return pass(program);
} catch (e, s) {
return crash(e, s);
}
}
}
class ClosureConversion extends Step<Program, Program, TestContext> {
const ClosureConversion();
String get name => "closure conversion";
Future<Result<Program>> run(Program program, TestContext testContext) async {
try {
program = closure_conversion.transformProgram(program);
return pass(program);
} catch (e, s) {
return crash(e, s);
}
}
}
class Run extends Step<Uri, int, TestContext> {
const Run();
String get name => "run";
Future<Result<int>> run(Uri uri, TestContext context) async {
File generated = new File.fromUri(uri);
StdioProcess process;
try {
process = await StdioProcess
.run(context.vm.toFilePath(), [generated.path, "Hello, World!"]);
print(process.output);
} finally {
generated.parent.delete(recursive: true);
}
return process.toResult();
}
}
main(List<String> arguments) => runMe(arguments, createContext, "testing.json");