Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(593)

Unified Diff: tests/compiler/dart2js/equivalence/check_functions.dart

Issue 2879593004: Reorganize equivalence test helpers (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tests/compiler/dart2js/equivalence/check_functions.dart
diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4f82bde0ff62a82929215ac5616a924934a7047a
--- /dev/null
+++ b/tests/compiler/dart2js/equivalence/check_functions.dart
@@ -0,0 +1,612 @@
+// 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.
+
+/// Equivalence test functions for data objects.
+
+library dart2js.equivalence.functions;
+
+import 'package:expect/expect.dart';
+import 'package:compiler/src/common/resolution.dart';
+import 'package:compiler/src/common_elements.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/types.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.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/js_backend/interceptor_data.dart';
+import 'package:compiler/src/serialization/equivalence.dart';
+import 'package:compiler/src/universe/class_set.dart';
+import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/world.dart';
+import 'check_helpers.dart';
+
+void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2,
+ {TestStrategy strategy: const TestStrategy(),
+ bool allowExtra: false,
+ bool verbose: false}) {
+ if (verbose) {
+ print(closedWorld1.dump());
+ print(closedWorld2.dump());
+ }
+ checkClassHierarchyNodes(
+ closedWorld1,
+ closedWorld2,
+ closedWorld1
+ .getClassHierarchyNode(closedWorld1.commonElements.objectClass),
+ closedWorld2
+ .getClassHierarchyNode(closedWorld2.commonElements.objectClass),
+ strategy.elementEquivalence,
+ verbose: verbose);
+
+ checkNativeData(closedWorld1.nativeData, closedWorld2.nativeData,
+ strategy: strategy, allowExtra: allowExtra, verbose: verbose);
+ checkInterceptorData(closedWorld1.interceptorData,
+ closedWorld2.interceptorData, strategy.elementEquivalence,
+ verbose: verbose);
+}
+
+void checkNativeData(NativeDataImpl data1, NativeDataImpl data2,
+ {TestStrategy strategy: const TestStrategy(),
+ bool allowExtra: false,
+ bool verbose: false}) {
+ checkMapEquivalence(data1, data2, 'nativeMemberName', data1.nativeMemberName,
+ data2.nativeMemberName, strategy.elementEquivalence, equality,
+ allowExtra: allowExtra);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'nativeMethodBehavior',
+ data1.nativeMethodBehavior,
+ data2.nativeMethodBehavior,
+ strategy.elementEquivalence,
+ (a, b) => testNativeBehavior(a, b, strategy: strategy),
+ allowExtra: allowExtra);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'nativeFieldLoadBehavior',
+ data1.nativeFieldLoadBehavior,
+ data2.nativeFieldLoadBehavior,
+ strategy.elementEquivalence,
+ (a, b) => testNativeBehavior(a, b, strategy: strategy),
+ allowExtra: allowExtra);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'nativeFieldStoreBehavior',
+ data1.nativeFieldStoreBehavior,
+ data2.nativeFieldStoreBehavior,
+ strategy.elementEquivalence,
+ (a, b) => testNativeBehavior(a, b, strategy: strategy),
+ allowExtra: allowExtra);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'jsInteropLibraryNames',
+ data1.jsInteropLibraryNames,
+ data2.jsInteropLibraryNames,
+ strategy.elementEquivalence,
+ equality);
+
+ checkSetEquivalence(
+ data1,
+ data2,
+ 'anonymousJsInteropClasses',
+ data1.anonymousJsInteropClasses,
+ data2.anonymousJsInteropClasses,
+ strategy.elementEquivalence);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'jsInteropClassNames',
+ data1.jsInteropClassNames,
+ data2.jsInteropClassNames,
+ strategy.elementEquivalence,
+ equality);
+
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'jsInteropMemberNames',
+ data1.jsInteropMemberNames,
+ data2.jsInteropMemberNames,
+ strategy.elementEquivalence,
+ equality);
+}
+
+void checkInterceptorData(InterceptorDataImpl data1, InterceptorDataImpl data2,
+ bool elementEquivalence(Entity a, Entity b),
+ {bool verbose: false}) {
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'interceptedElements',
+ data1.interceptedElementsForTesting,
+ data2.interceptedElementsForTesting,
+ equality,
+ (a, b) => areSetsEquivalent(a, b, elementEquivalence));
+
+ checkSetEquivalence(data1, data2, 'interceptedClasses',
+ data1.interceptedClasses, data2.interceptedClasses, elementEquivalence);
+
+ checkSetEquivalence(
+ data1,
+ data2,
+ 'classesMixedIntoInterceptedClasses',
+ data1.classesMixedIntoInterceptedClassesForTesting,
+ data2.classesMixedIntoInterceptedClassesForTesting,
+ elementEquivalence);
+}
+
+void checkClassHierarchyNodes(
+ ClosedWorld closedWorld1,
+ ClosedWorld closedWorld2,
+ ClassHierarchyNode node1,
+ ClassHierarchyNode node2,
+ bool elementEquivalence(Entity a, Entity b),
+ {bool verbose: false}) {
+ if (verbose) {
+ print('Checking $node1 vs $node2');
+ }
+ ClassEntity cls1 = node1.cls;
+ ClassEntity cls2 = node2.cls;
+ Expect.isTrue(elementEquivalence(cls1, cls2),
+ "Element identity mismatch for ${cls1} vs ${cls2}.");
+ Expect.equals(
+ node1.isDirectlyInstantiated,
+ node2.isDirectlyInstantiated,
+ "Value mismatch for 'isDirectlyInstantiated' "
+ "for ${cls1} vs ${cls2}.");
+ Expect.equals(
+ node1.isIndirectlyInstantiated,
+ node2.isIndirectlyInstantiated,
+ "Value mismatch for 'isIndirectlyInstantiated' "
+ "for ${node1.cls} vs ${node2.cls}.");
+ // TODO(johnniwinther): Enforce a canonical and stable order on direct
+ // subclasses.
+ for (ClassHierarchyNode child in node1.directSubclasses) {
+ bool found = false;
+ for (ClassHierarchyNode other in node2.directSubclasses) {
+ ClassEntity child1 = child.cls;
+ ClassEntity child2 = other.cls;
+ if (elementEquivalence(child1, child2)) {
+ checkClassHierarchyNodes(
+ closedWorld1, closedWorld2, child, other, elementEquivalence,
+ verbose: verbose);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (child.isInstantiated) {
+ print('Missing subclass ${child.cls} of ${node1.cls} '
+ 'in ${node2.directSubclasses}');
+ print(closedWorld1.dump(
+ verbose ? closedWorld1.commonElements.objectClass : node1.cls));
+ print(closedWorld2.dump(
+ verbose ? closedWorld2.commonElements.objectClass : node2.cls));
+ }
+ Expect.isFalse(
+ child.isInstantiated,
+ 'Missing subclass ${child.cls} of ${node1.cls} in '
+ '${node2.directSubclasses}');
+ }
+ }
+ checkMixinUses(
+ closedWorld1, closedWorld2, node1.cls, node2.cls, elementEquivalence,
+ verbose: verbose);
+}
+
+void checkMixinUses(
+ ClosedWorld closedWorld1,
+ ClosedWorld closedWorld2,
+ ClassEntity class1,
+ ClassEntity class2,
+ bool elementEquivalence(Entity a, Entity b),
+ {bool verbose: false}) {
+ checkSets(closedWorld1.mixinUsesOf(class1), closedWorld2.mixinUsesOf(class2),
+ "Mixin uses of $class1 vs $class2", elementEquivalence,
+ verbose: verbose);
+}
+
+/// Check member property equivalence between all members common to [compiler1]
+/// and [compiler2].
+void checkLoadedLibraryMembers(
+ Compiler compiler1,
+ Compiler compiler2,
+ bool hasProperty(Element member1),
+ void checkMemberProperties(Compiler compiler1, Element member1,
+ Compiler compiler2, Element member2,
+ {bool verbose}),
+ {bool verbose: false}) {
+ void checkMembers(Element member1, Element member2) {
+ if (member1.isClass && member2.isClass) {
+ ClassElement class1 = member1;
+ ClassElement class2 = member2;
+ if (!class1.isResolved) return;
+
+ if (hasProperty(member1)) {
+ if (areElementsEquivalent(member1, member2)) {
+ checkMemberProperties(compiler1, member1, compiler2, member2,
+ verbose: verbose);
+ }
+ }
+
+ class1.forEachLocalMember((m1) {
+ checkMembers(m1, class2.localLookup(m1.name));
+ });
+ ClassElement superclass1 = class1.superclass;
+ ClassElement superclass2 = class2.superclass;
+ while (superclass1 != null && superclass1.isUnnamedMixinApplication) {
+ for (ConstructorElement c1 in superclass1.constructors) {
+ checkMembers(c1, superclass2.lookupConstructor(c1.name));
+ }
+ superclass1 = superclass1.superclass;
+ superclass2 = superclass2.superclass;
+ }
+ return;
+ }
+
+ if (!hasProperty(member1)) {
+ return;
+ }
+
+ if (member2 == null) {
+ throw 'Missing member for ${member1}';
+ }
+
+ if (areElementsEquivalent(member1, member2)) {
+ checkMemberProperties(compiler1, member1, compiler2, member2,
+ verbose: verbose);
+ }
+ }
+
+ for (LibraryElement library1 in compiler1.libraryLoader.libraries) {
+ LibraryElement library2 =
+ compiler2.libraryLoader.lookupLibrary(library1.canonicalUri);
+ if (library2 != null) {
+ library1.forEachLocalMember((Element member1) {
+ checkMembers(member1, library2.localLookup(member1.name));
+ });
+ }
+ }
+}
+
+/// Check equivalence of all resolution impacts.
+void checkAllImpacts(Compiler compiler1, Compiler compiler2,
+ {bool verbose: false}) {
+ checkLoadedLibraryMembers(compiler1, compiler2, (Element member1) {
+ return compiler1.resolution.hasResolutionImpact(member1);
+ }, checkImpacts, verbose: verbose);
+}
+
+/// Check equivalence of resolution impact for [member1] and [member2].
+void checkImpacts(
+ Compiler compiler1, Element member1, Compiler compiler2, Element member2,
+ {bool verbose: false}) {
+ ResolutionImpact impact1 = compiler1.resolution.getResolutionImpact(member1);
+ ResolutionImpact impact2 = compiler2.resolution.getResolutionImpact(member2);
+
+ if (impact1 == null && impact2 == null) return;
+
+ if (verbose) {
+ print('Checking impacts for $member1 vs $member2');
+ }
+
+ if (impact1 == null) {
+ throw 'Missing impact for $member1. $member2 has $impact2';
+ }
+ if (impact2 == null) {
+ throw 'Missing impact for $member2. $member1 has $impact1';
+ }
+
+ testResolutionImpactEquivalence(impact1, impact2,
+ strategy: const CheckStrategy());
+}
+
+void checkAllResolvedAsts(Compiler compiler1, Compiler compiler2,
+ {bool verbose: false}) {
+ checkLoadedLibraryMembers(compiler1, compiler2, (Element member1) {
+ return member1 is ExecutableElement &&
+ compiler1.resolution.hasResolvedAst(member1);
+ }, checkResolvedAsts, verbose: verbose);
+}
+
+/// Check equivalence of [impact1] and [impact2].
+void checkResolvedAsts(
+ Compiler compiler1, Element member1, Compiler compiler2, Element member2,
+ {bool verbose: false}) {
+ if (!compiler2.serialization.isDeserialized(member2)) {
+ return;
+ }
+ ResolvedAst resolvedAst1 = compiler1.resolution.getResolvedAst(member1);
+ ResolvedAst resolvedAst2 = compiler2.serialization.getResolvedAst(member2);
+
+ if (resolvedAst1 == null || resolvedAst2 == null) return;
+
+ if (verbose) {
+ print('Checking resolved asts for $member1 vs $member2');
+ }
+
+ testResolvedAstEquivalence(resolvedAst1, resolvedAst2, const CheckStrategy());
+}
+
+void checkNativeClasses(
+ Compiler compiler1, Compiler compiler2, TestStrategy strategy) {
+ Iterable<ClassEntity> nativeClasses1 = compiler1
+ .backend.nativeResolutionEnqueuerForTesting.nativeClassesForTesting;
+ Iterable<ClassEntity> nativeClasses2 = compiler2
+ .backend.nativeResolutionEnqueuerForTesting.nativeClassesForTesting;
+
+ checkSetEquivalence(compiler1, compiler2, 'nativeClasses', nativeClasses1,
+ nativeClasses2, strategy.elementEquivalence);
+
+ Iterable<ClassEntity> registeredClasses1 = compiler1
+ .backend.nativeResolutionEnqueuerForTesting.registeredClassesForTesting;
+ Iterable<ClassEntity> registeredClasses2 = compiler2
+ .backend.nativeResolutionEnqueuerForTesting.registeredClassesForTesting;
+
+ checkSetEquivalence(compiler1, compiler2, 'registeredClasses',
+ registeredClasses1, registeredClasses2, strategy.elementEquivalence);
+}
+
+void checkNativeBasicData(NativeBasicDataImpl data1, NativeBasicDataImpl data2,
+ TestStrategy strategy) {
+ checkMapEquivalence(
+ data1,
+ data2,
+ 'nativeClassTagInfo',
+ data1.nativeClassTagInfo,
+ data2.nativeClassTagInfo,
+ strategy.elementEquivalence,
+ (a, b) => a == b);
+ // TODO(johnniwinther): Check the remaining properties.
+}
+
+void checkBackendUsage(
+ BackendUsageImpl usage1, BackendUsageImpl usage2, TestStrategy strategy) {
+ checkSetEquivalence(
+ usage1,
+ usage2,
+ 'globalClassDependencies',
+ usage1.globalClassDependencies,
+ usage2.globalClassDependencies,
+ strategy.elementEquivalence);
+ checkSetEquivalence(
+ usage1,
+ usage2,
+ 'globalFunctionDependencies',
+ usage1.globalFunctionDependencies,
+ usage2.globalFunctionDependencies,
+ strategy.elementEquivalence);
+ checkSetEquivalence(
+ usage1,
+ usage2,
+ 'helperClassesUsed',
+ usage1.helperClassesUsed,
+ usage2.helperClassesUsed,
+ strategy.elementEquivalence);
+ checkSetEquivalence(
+ usage1,
+ usage2,
+ 'helperFunctionsUsed',
+ usage1.helperFunctionsUsed,
+ usage2.helperFunctionsUsed,
+ strategy.elementEquivalence);
+ 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, TestStrategy strategy) {
+ checkMembers(MemberEntity member1, MemberEntity member2) {
+ Expect.equals(env1.isDeferredLoadLibraryGetter(member1),
+ env2.isDeferredLoadLibraryGetter(member2));
+
+ checkListEquivalence(
+ member1,
+ member2,
+ 'metadata',
+ env1.getMemberMetadata(member1),
+ env2.getMemberMetadata(member2),
+ strategy.testConstantValues);
+ }
+
+ checkSetEquivalence(env1, env2, 'libraries', env1.libraries, env2.libraries,
+ strategy.elementEquivalence,
+ onSameElement: (LibraryEntity lib1, LibraryEntity lib2) {
+ Expect.identical(lib1, env1.lookupLibrary(lib1.canonicalUri));
+ Expect.identical(lib2, env2.lookupLibrary(lib2.canonicalUri));
+
+ List<ClassEntity> classes2 = <ClassEntity>[];
+ env1.forEachClass(lib1, (ClassEntity cls1) {
+ Expect.identical(cls1, env1.lookupClass(lib1, cls1.name));
+
+ String className = cls1.name;
+ ClassEntity cls2 = env2.lookupClass(lib2, className);
+ Expect.isNotNull(cls2, 'Missing class $className in $lib2');
+ Expect.identical(cls2, env2.lookupClass(lib2, cls2.name));
+
+ check(lib1, lib2, 'class:${className}', cls1, cls2,
+ strategy.elementEquivalence);
+
+ Expect.equals(env1.isGenericClass(cls1), env2.isGenericClass(cls2));
+
+ check(
+ cls1,
+ cls2,
+ 'superclass',
+ env1.getSuperClass(cls1, skipUnnamedMixinApplications: false),
+ env2.getSuperClass(cls2, skipUnnamedMixinApplications: false),
+ strategy.elementEquivalence);
+ check(
+ cls1,
+ cls2,
+ 'superclass',
+ env1.getSuperClass(cls1, skipUnnamedMixinApplications: true),
+ env2.getSuperClass(cls2, skipUnnamedMixinApplications: true),
+ strategy.elementEquivalence);
+
+ List<InterfaceType> supertypes1 = <InterfaceType>[];
+ env1.forEachSupertype(cls1, supertypes1.add);
+ List<InterfaceType> supertypes2 = <InterfaceType>[];
+ env2.forEachSupertype(cls2, supertypes1.add);
+ strategy.testTypeLists(
+ cls1, cls2, 'supertypes', supertypes1, supertypes2);
+
+ List<ClassEntity> mixins1 = <ClassEntity>[];
+ env1.forEachMixin(cls1, mixins1.add);
+ List<ClassEntity> mixins2 = <ClassEntity>[];
+ env2.forEachMixin(cls2, mixins2.add);
+ strategy.testLists(
+ cls1, cls2, 'mixins', mixins1, mixins2, strategy.elementEquivalence);
+
+ Map<MemberEntity, ClassEntity> members1 = <MemberEntity, ClassEntity>{};
+ Map<MemberEntity, ClassEntity> members2 = <MemberEntity, ClassEntity>{};
+ env1.forEachClassMember(cls1,
+ (ClassEntity declarer1, MemberEntity member1) {
+ if (cls1 == declarer1) {
+ Expect.identical(
+ member1,
+ env1.lookupClassMember(cls1, member1.name,
+ setter: member1.isSetter));
+ }
+ members1[member1] = declarer1;
+ });
+ env2.forEachClassMember(cls2,
+ (ClassEntity declarer2, MemberEntity member2) {
+ if (cls2 == declarer2) {
+ Expect.identical(
+ member2,
+ env2.lookupClassMember(cls2, member2.name,
+ setter: member2.isSetter));
+ }
+ members2[member2] = declarer2;
+ });
+ checkMapEquivalence(cls1, cls2, 'members', members1, members2, (a, b) {
+ bool result = strategy.elementEquivalence(a, b);
+ if (result) checkMembers(a, b);
+ return result;
+ }, strategy.elementEquivalence);
+
+ 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].
+}
+
+bool areInstantiationInfosEquivalent(
+ InstantiationInfo info1,
+ InstantiationInfo info2,
+ bool elementEquivalence(Entity a, Entity b),
+ bool typeEquivalence(DartType a, DartType b)) {
+ checkMaps(
+ info1.instantiationMap,
+ info2.instantiationMap,
+ 'instantiationMap of\n '
+ '${info1.instantiationMap}\nvs ${info2.instantiationMap}',
+ elementEquivalence,
+ (a, b) => areSetsEquivalent(
+ a, b, (a, b) => areInstancesEquivalent(a, b, typeEquivalence)));
+ return true;
+}
+
+bool areInstancesEquivalent(Instance instance1, Instance instance2,
+ bool typeEquivalence(DartType a, DartType b)) {
+ InterfaceType type1 = instance1.type;
+ InterfaceType type2 = instance2.type;
+ return typeEquivalence(type1, type2) &&
+ instance1.kind == instance2.kind &&
+ instance1.isRedirection == instance2.isRedirection;
+}
+
+void checkResolutionEnqueuers(
+ BackendUsage backendUsage1,
+ BackendUsage backendUsage2,
+ ResolutionEnqueuer enqueuer1,
+ ResolutionEnqueuer enqueuer2,
+ {bool elementEquivalence(Entity a, Entity b): areElementsEquivalent,
+ bool typeEquivalence(DartType a, DartType b): areTypesEquivalent,
+ bool elementFilter(Element element),
+ bool verbose: false}) {
+ ResolutionWorldBuilderBase worldBuilder1 = enqueuer1.worldBuilder;
+ ResolutionWorldBuilderBase worldBuilder2 = enqueuer2.worldBuilder;
+
+ checkSets(
+ enqueuer1.worldBuilder.instantiatedTypes,
+ enqueuer2.worldBuilder.instantiatedTypes,
+ "Instantiated types mismatch",
+ typeEquivalence,
+ verbose: verbose);
+
+ checkSets(
+ enqueuer1.worldBuilder.directlyInstantiatedClasses,
+ enqueuer2.worldBuilder.directlyInstantiatedClasses,
+ "Directly instantiated classes mismatch",
+ elementEquivalence,
+ verbose: verbose);
+
+ checkMaps(
+ worldBuilder1.getInstantiationMap(),
+ worldBuilder2.getInstantiationMap(),
+ "Instantiated classes mismatch",
+ elementEquivalence,
+ (a, b) => areInstantiationInfosEquivalent(
+ a, b, elementEquivalence, typeEquivalence),
+ verbose: verbose);
+
+ checkSets(enqueuer1.processedEntities, enqueuer2.processedEntities,
+ "Processed element mismatch", elementEquivalence, elementFilter: (e) {
+ return elementFilter != null ? elementFilter(e) : true;
+ }, verbose: verbose);
+
+ checkSets(enqueuer1.worldBuilder.isChecks, enqueuer2.worldBuilder.isChecks,
+ "Is-check mismatch", typeEquivalence,
+ verbose: verbose);
+
+ Expect.equals(backendUsage1.isInvokeOnUsed, backendUsage2.isInvokeOnUsed,
+ "JavaScriptBackend.hasInvokeOnSupport mismatch");
+ Expect.equals(
+ backendUsage1.isFunctionApplyUsed,
+ backendUsage1.isFunctionApplyUsed,
+ "JavaScriptBackend.hasFunctionApplySupport mismatch");
+ Expect.equals(
+ backendUsage1.isRuntimeTypeUsed,
+ backendUsage2.isRuntimeTypeUsed,
+ "JavaScriptBackend.hasRuntimeTypeSupport mismatch");
+ Expect.equals(backendUsage1.isIsolateInUse, backendUsage2.isIsolateInUse,
+ "JavaScriptBackend.hasIsolateSupport mismatch");
+}

Powered by Google App Engine
This is Rietveld 408576698