| Index: tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
|
| diff --git a/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart b/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b761d6a539cefa67ccfecf2d323752e815121ee9
|
| --- /dev/null
|
| +++ b/tests/compiler/dart2js/kernel/closed_world_from_dill_test.dart
|
| @@ -0,0 +1,230 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +// Partial test that the closed world computed from [WorldImpact]s derived from
|
| +// kernel is equivalent to the original computed from resolution.
|
| +library dart2js.kernel.closed_world_from_dill_test;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:async_helper/async_helper.dart';
|
| +import 'package:compiler/src/commandline_options.dart';
|
| +import 'package:compiler/src/common.dart';
|
| +import 'package:compiler/src/common_elements.dart';
|
| +import 'package:compiler/src/compiler.dart';
|
| +import 'package:compiler/src/elements/entities.dart';
|
| +import 'package:compiler/src/elements/resolution_types.dart';
|
| +import 'package:compiler/src/elements/types.dart';
|
| +import 'package:compiler/src/enqueue.dart';
|
| +import 'package:compiler/src/js_backend/backend_usage.dart';
|
| +import 'package:compiler/src/js_backend/native_data.dart';
|
| +import 'package:compiler/src/kernel/element_map.dart';
|
| +import 'package:compiler/src/kernel/kernel_strategy.dart';
|
| +import 'package:compiler/src/universe/world_builder.dart';
|
| +import 'package:compiler/src/world.dart';
|
| +import 'package:expect/expect.dart';
|
| +import '../memory_compiler.dart';
|
| +import '../serialization/helper.dart';
|
| +import '../serialization/model_test_helper.dart';
|
| +import '../serialization/test_helper.dart';
|
| +
|
| +import 'closed_world_test.dart' hide KernelWorkItemBuilder;
|
| +import 'compiler_helper.dart';
|
| +import 'impact_test.dart';
|
| +
|
| +const SOURCE = const {
|
| + 'main.dart': '''
|
| +main() {
|
| + print('Hello World');
|
| +}
|
| +'''
|
| +};
|
| +
|
| +main(List<String> args) {
|
| + asyncTest(() async {
|
| + await mainInternal(args);
|
| + });
|
| +}
|
| +
|
| +enum ResultKind { crashes, errors, warnings, success, failure }
|
| +
|
| +Future<ResultKind> mainInternal(List<String> args,
|
| + {bool skipWarnings: false, bool skipErrors: false}) async {
|
| + Arguments arguments = new Arguments.from(args);
|
| + Uri entryPoint;
|
| + Map<String, String> memorySourceFiles;
|
| + if (arguments.uri != null) {
|
| + entryPoint = arguments.uri;
|
| + memorySourceFiles = const <String, String>{};
|
| + } else {
|
| + entryPoint = Uri.parse('memory:main.dart');
|
| + memorySourceFiles = SOURCE;
|
| + }
|
| +
|
| + enableDebugMode();
|
| +
|
| + print('---- analyze-only ------------------------------------------------');
|
| + DiagnosticCollector collector = new DiagnosticCollector();
|
| + Compiler compiler1 = compilerFor(
|
| + entryPoint: entryPoint,
|
| + memorySourceFiles: memorySourceFiles,
|
| + diagnosticHandler: collector,
|
| + options: [Flags.analyzeOnly, Flags.enableAssertMessage]);
|
| + ElementResolutionWorldBuilder.useInstantiationMap = true;
|
| + compiler1.resolution.retainCachesForTesting = true;
|
| + await compiler1.run(entryPoint);
|
| + if (collector.crashes.isNotEmpty) {
|
| + print('Skipping due to crashes.');
|
| + return ResultKind.crashes;
|
| + }
|
| + if (collector.errors.isNotEmpty && skipErrors) {
|
| + print('Skipping due to errors.');
|
| + return ResultKind.errors;
|
| + }
|
| + if (collector.warnings.isNotEmpty && skipWarnings) {
|
| + print('Skipping due to warnings.');
|
| + return ResultKind.warnings;
|
| + }
|
| + Expect.isFalse(compiler1.compilationFailed);
|
| + ResolutionEnqueuer enqueuer1 = compiler1.enqueuer.resolution;
|
| + BackendUsage backendUsage1 = compiler1.backend.backendUsage;
|
| + ClosedWorld closedWorld1 = compiler1.resolutionWorldBuilder.closeWorld();
|
| +
|
| + Compiler compiler2 =
|
| + await compileWithDill(entryPoint, memorySourceFiles, printSteps: true);
|
| +
|
| + KernelFrontEndStrategy frontEndStrategy = compiler2.frontEndStrategy;
|
| + KernelToElementMap elementMap = frontEndStrategy.elementMap;
|
| +
|
| + // TODO(johnniwinter): Change expectancy and continue equivalence testing when
|
| + // https://codereview.chromium.org/2862223002/ is committed.
|
| + Expect.isTrue(compiler2.compilationFailed);
|
| + return ResultKind.failure;
|
| +
|
| + KernelEquivalence equivalence = new KernelEquivalence(elementMap);
|
| +
|
| + ResolutionEnqueuer enqueuer2 = compiler2.enqueuer.resolution;
|
| + BackendUsage backendUsage2 = compiler2.backend.backendUsage;
|
| + ClosedWorld closedWorld2 = compiler2.resolutionWorldBuilder.closeWorld();
|
| + checkBackendUsage(backendUsage1, backendUsage2, equivalence);
|
| +
|
| + checkResolutionEnqueuers(backendUsage1, backendUsage2, enqueuer1, enqueuer2,
|
| + elementEquivalence: equivalence.entityEquivalence,
|
| + typeEquivalence: (ResolutionDartType a, DartType b) {
|
| + return equivalence.typeEquivalence(unalias(a), b);
|
| + }, elementFilter: elementFilter, verbose: arguments.verbose);
|
| +
|
| + checkClosedWorlds(closedWorld1, closedWorld2, equivalence.entityEquivalence,
|
| + verbose: arguments.verbose);
|
| +
|
| + return ResultKind.success;
|
| +}
|
| +
|
| +void checkNativeBasicData(NativeBasicDataImpl data1, NativeBasicDataImpl data2,
|
| + KernelEquivalence equivalence) {
|
| + checkMapEquivalence(
|
| + data1,
|
| + data2,
|
| + 'nativeClassTagInfo',
|
| + data1.nativeClassTagInfo,
|
| + data2.nativeClassTagInfo,
|
| + equivalence.entityEquivalence,
|
| + (a, b) => a == b);
|
| + // TODO(johnniwinther): Check the remaining properties.
|
| +}
|
| +
|
| +void checkBackendUsage(BackendUsageImpl usage1, BackendUsageImpl usage2,
|
| + KernelEquivalence equivalence) {
|
| + checkSetEquivalence(
|
| + usage1,
|
| + usage2,
|
| + 'globalClassDependencies',
|
| + usage1.globalClassDependencies,
|
| + usage2.globalClassDependencies,
|
| + equivalence.entityEquivalence);
|
| + checkSetEquivalence(
|
| + usage1,
|
| + usage2,
|
| + 'globalFunctionDependencies',
|
| + usage1.globalFunctionDependencies,
|
| + usage2.globalFunctionDependencies,
|
| + equivalence.entityEquivalence);
|
| + checkSetEquivalence(
|
| + usage1,
|
| + usage2,
|
| + 'helperClassesUsed',
|
| + usage1.helperClassesUsed,
|
| + usage2.helperClassesUsed,
|
| + equivalence.entityEquivalence);
|
| + checkSetEquivalence(
|
| + usage1,
|
| + usage2,
|
| + 'helperFunctionsUsed',
|
| + usage1.helperFunctionsUsed,
|
| + usage2.helperFunctionsUsed,
|
| + equivalence.entityEquivalence);
|
| + check(
|
| + usage1,
|
| + usage2,
|
| + 'needToInitializeIsolateAffinityTag',
|
| + usage1.needToInitializeIsolateAffinityTag,
|
| + usage2.needToInitializeIsolateAffinityTag);
|
| + check(
|
| + usage1,
|
| + usage2,
|
| + 'needToInitializeDispatchProperty',
|
| + usage1.needToInitializeDispatchProperty,
|
| + usage2.needToInitializeDispatchProperty);
|
| + check(usage1, usage2, 'requiresPreamble', usage1.requiresPreamble,
|
| + usage2.requiresPreamble);
|
| + check(usage1, usage2, 'isInvokeOnUsed', usage1.isInvokeOnUsed,
|
| + usage2.isInvokeOnUsed);
|
| + check(usage1, usage2, 'isRuntimeTypeUsed', usage1.isRuntimeTypeUsed,
|
| + usage2.isRuntimeTypeUsed);
|
| + check(usage1, usage2, 'isIsolateInUse', usage1.isIsolateInUse,
|
| + usage2.isIsolateInUse);
|
| + check(usage1, usage2, 'isFunctionApplyUsed', usage1.isFunctionApplyUsed,
|
| + usage2.isFunctionApplyUsed);
|
| + check(usage1, usage2, 'isNoSuchMethodUsed', usage1.isNoSuchMethodUsed,
|
| + usage2.isNoSuchMethodUsed);
|
| +}
|
| +
|
| +checkElementEnvironment(ElementEnvironment env1, ElementEnvironment env2,
|
| + KernelEquivalence equivalence) {
|
| + checkSetEquivalence(env1, env2, 'libraries', env1.libraries, env2.libraries,
|
| + equivalence.entityEquivalence,
|
| + onSameElement: (LibraryEntity lib1, LibraryEntity lib2) {
|
| + List<ClassEntity> classes2 = <ClassEntity>[];
|
| + env1.forEachClass(lib1, (ClassEntity cls1) {
|
| + String className = cls1.name;
|
| + ClassEntity cls2 = env2.lookupClass(lib2, className);
|
| + Expect.isNotNull(cls2, 'Missing class $className in $lib2');
|
| + check(lib1, lib2, 'class:${className}', cls1, cls2,
|
| + equivalence.entityEquivalence);
|
| +
|
| + check(cls1, cls2, 'superclass', env1.getSuperClass(cls1),
|
| + env2.getSuperClass(cls2), equivalence.entityEquivalence);
|
| +
|
| + Map<MemberEntity, ClassEntity> members1 = <MemberEntity, ClassEntity>{};
|
| + Map<MemberEntity, ClassEntity> members2 = <MemberEntity, ClassEntity>{};
|
| + env1.forEachClassMember(cls1,
|
| + (ClassEntity declarer1, MemberEntity member1) {
|
| + members1[member1] = declarer1;
|
| + });
|
| + env1.forEachClassMember(cls1,
|
| + (ClassEntity declarer2, MemberEntity member2) {
|
| + members2[member2] = declarer2;
|
| + });
|
| + checkMapEquivalence(cls1, cls2, 'members', members1, members2,
|
| + equivalence.entityEquivalence, equivalence.entityEquivalence);
|
| +
|
| + classes2.add(cls2);
|
| + });
|
| + env2.forEachClass(lib2, (ClassEntity cls2) {
|
| + Expect.isTrue(classes2.contains(cls2), "Extra class $cls2 in $lib2");
|
| + });
|
| + });
|
| +
|
| + // TODO(johnniwinther): Test the remaining properties of [ElementEnvironment].
|
| +}
|
|
|