blob: f52fb1f0eb2db7f9684eb74d30d10cd2596d4fbb [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:io';
import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:front_end/src/api_unstable/vm.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/pragma.dart'
show ConstantPragmaAnnotationParser;
import 'package:vm/transformations/type_flow/transformer.dart'
show transformComponent;
import '../../common_test_utils.dart';
final Uri pkgVmDir = Platform.script.resolve('../../..');
runTestCase(
Uri source, bool enableNullSafety, List<Uri>? linkedDependencies) async {
final target =
new TestingVmTarget(new TargetFlags(enableNullSafety: enableNullSafety));
Component component = await compileTestCaseToKernelProgram(source,
target: target, linkedDependencies: linkedDependencies);
final coreTypes = new CoreTypes(component);
component = transformComponent(target, coreTypes, component,
matcher: new ConstantPragmaAnnotationParser(coreTypes),
treeShakeProtobufs: true);
String actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
Set<Library> dependencies = {};
// Tests in /protobuf_handler consist of multiple libraries.
// Include libraries with protobuf generated messages into the result.
if (source.toString().contains('/protobuf_handler/')) {
for (var lib in component.libraries) {
if (lib.importUri
.toString()
.contains('/protobuf_handler/lib/generated/')) {
dependencies.add(lib);
}
}
}
for (var lib in component.libraries) {
if (lib.fileUri.path.endsWith('.lib.dart')) {
dependencies.add(lib);
}
}
if (dependencies.isNotEmpty) {
for (var lib in dependencies) {
lib.name ??= lib.importUri.pathSegments.last;
actual += kernelLibraryToString(lib);
}
// Remove library paths.
actual = actual.replaceAll(pkgVmDir.toString(), 'file:pkg/vm/');
}
compareResultWithExpectationsFile(source, actual);
ensureKernelCanBeSerializedToBinary(component);
}
String? argsTestName(List<String> args) {
if (args.length > 0) {
return args.last;
}
return null;
}
class TestOptions {
/// List of libraries the should be precompiled to .dill before compiling the
/// main library from source.
static const Option<List<String>?> linked =
Option('--linked', StringListValue());
/// If set, the test should be compiled with sound null safety.
static const Option<bool> nnbdStrong =
Option('--nnbd-strong', BoolValue(false));
static const List<Option> options = [linked, nnbdStrong];
}
main(List<String> args) {
final testNameFilter = argsTestName(args);
group('transform-component', () {
final testCasesDir = new Directory.fromUri(
pkgVmDir.resolve('testcases/transformations/type_flow/transformer/'));
for (var entry
in testCasesDir.listSync(recursive: true, followLinks: false)) {
final path = entry.path;
if (path.endsWith('.dart') &&
!path.endsWith('.pb.dart') &&
!path.endsWith('.lib.dart')) {
String name = entry.uri.pathSegments.last;
if (testNameFilter != null && !path.contains(testNameFilter)) {
print('Skipping ${name}');
continue;
}
List<Uri>? linkDependencies;
bool enableNullSafety = path.endsWith('_nnbd_strong.dart');
File optionsFile = new File('${path}.options');
if (optionsFile.existsSync()) {
ParsedOptions parsedOptions = ParsedOptions.parse(
ParsedOptions.readOptionsFile(optionsFile.readAsStringSync()),
TestOptions.options);
List<String>? linked = TestOptions.linked.read(parsedOptions);
if (linked != null) {
linkDependencies =
linked.map((String name) => entry.uri.resolve(name)).toList();
}
if (TestOptions.nnbdStrong.read(parsedOptions)) {
enableNullSafety = true;
}
}
test(path,
() => runTestCase(entry.uri, enableNullSafety, linkDependencies));
}
}
}, timeout: Timeout.none);
}