Chromium Code Reviews| Index: tests/compiler/dart2js/serialization_model_test.dart |
| diff --git a/tests/compiler/dart2js/serialization_model_test.dart b/tests/compiler/dart2js/serialization_model_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4e47c34a684631db92ec3502fb74e60744b505cb |
| --- /dev/null |
| +++ b/tests/compiler/dart2js/serialization_model_test.dart |
| @@ -0,0 +1,236 @@ |
| +// Copyright (c) 2015, 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. |
| + |
| +library dart2js.serialization_model_test; |
| + |
| +import 'dart:async'; |
| +import 'dart:io'; |
| +import 'package:async_helper/async_helper.dart'; |
| +import 'package:expect/expect.dart'; |
| +import 'package:compiler/src/commandline_options.dart'; |
| +import 'package:compiler/src/common/backend_api.dart'; |
| +import 'package:compiler/src/common/names.dart'; |
| +import 'package:compiler/src/common/resolution.dart'; |
| +import 'package:compiler/src/compiler.dart'; |
| +import 'package:compiler/src/dart_types.dart'; |
| +import 'package:compiler/src/elements/elements.dart'; |
| +import 'package:compiler/src/filenames.dart'; |
| +import 'package:compiler/src/serialization/element_serialization.dart'; |
| +import 'package:compiler/src/serialization/impact_serialization.dart'; |
| +import 'package:compiler/src/serialization/json_serializer.dart'; |
| +import 'package:compiler/src/serialization/serialization.dart'; |
| +import 'package:compiler/src/serialization/equivalence.dart'; |
| +import 'package:compiler/src/serialization/task.dart'; |
| +import 'package:compiler/src/universe/world_impact.dart'; |
| +import 'package:compiler/src/universe/class_set.dart'; |
| +import 'package:compiler/src/universe/use.dart'; |
| +import 'memory_compiler.dart'; |
| +import 'serialization_helper.dart'; |
| +import 'serialization_analysis_test.dart'; |
| +import 'serialization_impact_test.dart'; |
| + |
| +main(List<String> arguments) { |
| + String filename; |
| + for (String arg in arguments) { |
| + if (!arg.startsWith('-')) { |
| + filename = arg; |
| + } |
| + } |
| + bool verbose = arguments.contains('-v'); |
| + |
| + asyncTest(() async { |
| + print('------------------------------------------------------------------'); |
| + print('serialize dart:core'); |
| + print('------------------------------------------------------------------'); |
| + String serializedData; |
| + File file = new File('out.data'); |
| + if (arguments.contains('-l')) { |
| + if (file.existsSync()) { |
| + print('Loading data from $file'); |
| + serializedData = file.readAsStringSync(); |
| + } |
| + } |
| + if (serializedData == null) { |
| + serializedData = await serializeDartCore(); |
| + if (arguments.contains('-s')) { |
| + print('Saving data to $file'); |
| + file.writeAsStringSync(serializedData); |
| + } |
| + } |
| + if (filename != null) { |
| + Uri entryPoint = Uri.base.resolve(nativeToUriPath(filename)); |
| + await check(serializedData, entryPoint); |
| + } else { |
| + Uri entryPoint = Uri.parse('memory:main.dart'); |
| + for (Test test in TESTS) { |
| + if (test.sourceFiles['main.dart'] |
| + .contains('main(List<String> arguments)')) { |
| + // TODO(johnniwinther): Check this test. |
| + continue; |
| + } |
| + print('=============================================================='); |
| + print(test.sourceFiles); |
| + await check( |
| + serializedData, |
| + entryPoint, |
| + sourceFiles: test.sourceFiles, |
| + verbose: verbose); |
| + } |
| + } |
| + }); |
| +} |
| + |
| +Future check( |
| + String serializedData, |
| + Uri entryPoint, |
| + {Map<String, String> sourceFiles: const <String, String>{}, |
| + bool verbose: false}) async { |
| + |
| + print('------------------------------------------------------------------'); |
| + print('compile normal'); |
| + print('------------------------------------------------------------------'); |
| + Compiler compilerNormal = compilerFor( |
| + memorySourceFiles: sourceFiles, |
| + options: [Flags.analyzeOnly]); |
| + compilerNormal.resolution.retainCaches = true; |
| + await compilerNormal.run(entryPoint); |
| + compilerNormal.world.populate(); |
| + |
| + print('------------------------------------------------------------------'); |
| + print('compile deserialized'); |
| + print('------------------------------------------------------------------'); |
| + Compiler compilerDeserialized = compilerFor( |
| + memorySourceFiles: sourceFiles, |
| + options: [Flags.analyzeOnly]); |
| + compilerDeserialized.resolution.retainCaches = true; |
| + deserialize(compilerDeserialized, serializedData); |
| + await compilerDeserialized.run(entryPoint); |
| + compilerDeserialized.world.populate(); |
| + |
| + checkResolutionImpacts( |
| + compilerNormal, compilerDeserialized, |
| + verbose: verbose); |
| + |
| + checkSets( |
| + compilerNormal.resolverWorld.directlyInstantiatedClasses, |
| + compilerDeserialized.resolverWorld.directlyInstantiatedClasses, |
| + "Directly instantiated classes mismatch", |
| + areElementsEquivalent, |
| + verbose: verbose); |
| + |
| + checkSets( |
| + compilerNormal.resolverWorld.instantiatedTypes, |
| + compilerDeserialized.resolverWorld.instantiatedTypes, |
| + "Instantiated types mismatch", |
| + areTypesEquivalent, |
| + // TODO(johnniwinther): Ensure that all instantiated types are tracked. |
| + failOnUnfound: false, |
| + verbose: verbose); |
| + |
| + checkSets( |
| + compilerNormal.resolverWorld.isChecks, |
| + compilerDeserialized.resolverWorld.isChecks, |
| + "Is-check mismatch", |
| + areTypesEquivalent, |
| + verbose: verbose); |
| + |
| + checkSets( |
| + compilerNormal.enqueuer.resolution.processedElements, |
| + compilerDeserialized.enqueuer.resolution.processedElements, |
| + "Processed element mismatch", |
| + areElementsEquivalent, |
| + verbose: verbose); |
| + |
| + checkClassHierarchyNodes( |
| + compilerNormal.world.getClassHierarchyNode( |
| + compilerNormal.coreClasses.objectClass), |
| + compilerDeserialized.world.getClassHierarchyNode( |
| + compilerDeserialized.coreClasses.objectClass), |
| + verbose: verbose); |
| +} |
| + |
| +void checkClassHierarchyNodes( |
| + ClassHierarchyNode a, ClassHierarchyNode b, |
| + {bool verbose: false}) { |
| + if (verbose) { |
| + print('Checking $a vs $b'); |
| + } |
| + Expect.isTrue( |
| + areElementsEquivalent(a.cls, b.cls), |
| + "Element identity mismatch for ${a.cls} vs ${b.cls}."); |
| + Expect.equals( |
| + a.isDirectlyInstantiated, |
| + b.isDirectlyInstantiated, |
| + "Value mismatch for 'isDirectlyInstantiated' for ${a.cls} vs ${b.cls}."); |
| + Expect.equals( |
| + a.isIndirectlyInstantiated, |
| + b.isIndirectlyInstantiated, |
| + "Value mismatch for 'isIndirectlyInstantiated' " |
| + "for ${a.cls} vs ${b.cls}."); |
| + for (ClassHierarchyNode child in a.directSubclasses) { |
| + bool found = false; |
| + for (ClassHierarchyNode other in b.directSubclasses) { |
|
Siggi Cherem (dart-lang)
2016/04/05 15:19:30
what do we need to do to guarantee that directSubc
Johnni Winther
2016/04/20 10:12:36
Adding a TODO. [ClassHierarchyNode.directSubclasse
|
| + if (areElementsEquivalent(child.cls, other.cls)) { |
| + checkClassHierarchyNodes(child, other, |
| + verbose: verbose); |
| + found = true; |
| + break; |
| + } |
| + } |
| + if (!found) { |
| + Expect.isFalse( |
| + child.isInstantiated, 'Missing subclass ${child.cls} of ${a.cls}'); |
| + } |
| + } |
| +} |
| + |
| + |
| +void checkSets( |
| + Iterable set1, |
| + Iterable set2, |
| + String messagePrefix, |
| + bool areEquivalent(a, b), |
| + {bool failOnUnfound: true, |
| + bool verbose: false}) { |
| + List common = []; |
| + List unfound = []; |
| + Set remaining = set2.toSet(); |
| + for (var element1 in set1) { |
| + bool found = false; |
| + for (var element2 in remaining) { |
|
Siggi Cherem (dart-lang)
2016/04/05 15:19:30
(a) seems that there is a lot in common between th
Johnni Winther
2016/04/20 10:12:36
(a) Done.
(b) Added as a TODO.
|
| + if (areEquivalent(element1, element2)) { |
| + found = true; |
| + remaining.remove(element2); |
| + break; |
| + } |
| + } |
| + if (found) { |
| + common.add(element1); |
| + } else { |
| + unfound.add(element1); |
| + } |
| + } |
| + StringBuffer sb = new StringBuffer(); |
| + sb.write("$messagePrefix:"); |
| + if (verbose) { |
| + sb.write("\n Common:\n ${common.join('\n ')}"); |
| + } |
| + if (unfound.isNotEmpty || verbose) { |
| + sb.write("\n Unfound:\n ${unfound.join('\n ')}"); |
| + } |
| + if (remaining.isNotEmpty || verbose) { |
| + sb.write("\n Extra: \n ${remaining.join('\n ')}"); |
| + } |
| + String message = sb.toString(); |
| + if (unfound.isNotEmpty || remaining.isNotEmpty) { |
| + |
| + if (failOnUnfound || remaining.isNotEmpty) { |
| + Expect.fail(message); |
| + } else { |
| + print(message); |
| + } |
| + } else if (verbose) { |
| + print(message); |
| + } |
| +} |