| // 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. |
| |
| 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)); |
| } |
| } |