blob: cf39848f667ed261687f5b59cc69bdb65d0f2d00 [file] [log] [blame]
// Copyright (c) 2019, 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.
// @dart=2.9
import 'dart:io';
import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/src/printer.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:vm/kernel_front_end.dart'
show runGlobalTransformations, ErrorDetector;
import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
show transformComponent;
import '../../common_test_utils.dart';
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
runTestCase(Uri source) async {
await shakeAndRun(source);
await compileAOT(source);
}
Future<void> shakeAndRun(Uri source) async {
final target = TestingVmTarget(TargetFlags());
Component component =
await compileTestCaseToKernelProgram(source, target: target);
List<Class> messageClasses = component.libraries
.expand(
(lib) => lib.classes.where((klass) =>
klass.superclass != null &&
klass.superclass.name == "GeneratedMessage"),
)
.toList();
globalTypeFlow.transformComponent(
TestingVmTarget(TargetFlags()), CoreTypes(component), component,
treeShakeProtobufs: true, treeShakeSignatures: false);
for (Class messageClass in messageClasses) {
expect(messageClass.enclosingLibrary.classes.contains(messageClass),
messageClass.name.endsWith('Keep'),
reason: '${messageClass.toText(astTextStrategyForTesting)}');
}
final systemTempDir = Directory.systemTemp;
final file = File('${systemTempDir.path}/${source.pathSegments.last}.dill');
try {
final sink = file.openWrite();
final printer = BinaryPrinter(sink, includeSources: false);
component.metadata.clear();
printer.writeComponentFile(component);
await sink.close();
final result = Process.runSync(
Platform.resolvedExecutable, ['--enable-asserts', file.path]);
expect(result.exitCode, 0, reason: '${result.stderr}\n${result.stdout}');
} finally {
if (file.existsSync()) {
file.deleteSync();
}
}
}
Future<void> compileAOT(Uri source) async {
final target = TestingVmTarget(TargetFlags());
Component component =
await compileTestCaseToKernelProgram(source, target: target);
// Imitate the global transformations as run by the protobuf-aware tree shaker
// in AOT mode.
// Copied verbatim from pkg/vm/bin/protobuf_aware_treeshaker.dart.
const bool useGlobalTypeFlowAnalysis = true;
const bool enableAsserts = false;
const bool useProtobufAwareTreeShakerV2 = true;
final nopErrorDetector = ErrorDetector();
runGlobalTransformations(
target,
component,
useGlobalTypeFlowAnalysis,
enableAsserts,
useProtobufAwareTreeShakerV2,
nopErrorDetector,
);
}
main() async {
final testCases = Directory(path.join(
pkgVmDir,
'testcases',
'transformations',
'type_flow',
'transformer',
'protobuf_handler',
'lib',
)).listSync().where((f) => f.path.endsWith('_test.dart'));
for (final entry in testCases) {
test(entry.path, () => runTestCase(entry.uri));
}
}