OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library dart2js.serialization_model_test; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:io'; | |
9 import 'package:async_helper/async_helper.dart'; | |
10 import 'package:expect/expect.dart'; | |
11 import 'package:compiler/src/commandline_options.dart'; | |
12 import 'package:compiler/src/common/backend_api.dart'; | |
13 import 'package:compiler/src/common/names.dart'; | |
14 import 'package:compiler/src/common/resolution.dart'; | |
15 import 'package:compiler/src/compiler.dart'; | |
16 import 'package:compiler/src/dart_types.dart'; | |
17 import 'package:compiler/src/elements/elements.dart'; | |
18 import 'package:compiler/src/filenames.dart'; | |
19 import 'package:compiler/src/serialization/element_serialization.dart'; | |
20 import 'package:compiler/src/serialization/impact_serialization.dart'; | |
21 import 'package:compiler/src/serialization/json_serializer.dart'; | |
22 import 'package:compiler/src/serialization/serialization.dart'; | |
23 import 'package:compiler/src/serialization/equivalence.dart'; | |
24 import 'package:compiler/src/serialization/task.dart'; | |
25 import 'package:compiler/src/universe/world_impact.dart'; | |
26 import 'package:compiler/src/universe/class_set.dart'; | |
27 import 'package:compiler/src/universe/use.dart'; | |
28 import 'memory_compiler.dart'; | |
29 import 'serialization_helper.dart'; | |
30 import 'serialization_test_data.dart'; | |
31 import 'serialization_test_helper.dart'; | |
32 | |
33 main(List<String> args) { | |
34 asyncTest(() async { | |
35 Arguments arguments = new Arguments.from(args); | |
36 String serializedData = await serializeDartCore(arguments: arguments); | |
37 if (arguments.filename != null) { | |
38 Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename)); | |
39 await check(serializedData, entryPoint); | |
40 } else { | |
41 Uri entryPoint = Uri.parse('memory:main.dart'); | |
42 for (Test test in TESTS) { | |
43 print('=============================================================='); | |
44 print(test.sourceFiles); | |
45 await check( | |
46 serializedData, | |
47 entryPoint, | |
48 sourceFiles: test.sourceFiles, | |
49 verbose: arguments.verbose); | |
50 } | |
51 } | |
52 }); | |
53 } | |
54 | |
55 Future check( | |
56 String serializedData, | |
57 Uri entryPoint, | |
58 {Map<String, String> sourceFiles: const <String, String>{}, | |
59 bool verbose: false}) async { | |
60 | |
61 print('------------------------------------------------------------------'); | |
62 print('compile normal'); | |
63 print('------------------------------------------------------------------'); | |
64 Compiler compilerNormal = compilerFor( | |
65 memorySourceFiles: sourceFiles, | |
66 options: [Flags.analyzeOnly]); | |
67 compilerNormal.resolution.retainCachesForTesting = true; | |
68 await compilerNormal.run(entryPoint); | |
69 compilerNormal.world.populate(); | |
70 | |
71 print('------------------------------------------------------------------'); | |
72 print('compile deserialized'); | |
73 print('------------------------------------------------------------------'); | |
74 Compiler compilerDeserialized = compilerFor( | |
75 memorySourceFiles: sourceFiles, | |
76 options: [Flags.analyzeOnly]); | |
77 compilerDeserialized.resolution.retainCachesForTesting = true; | |
78 deserialize(compilerDeserialized, serializedData); | |
79 await compilerDeserialized.run(entryPoint); | |
80 compilerDeserialized.world.populate(); | |
81 | |
82 checkAllImpacts( | |
83 compilerNormal, compilerDeserialized, | |
84 verbose: verbose); | |
85 | |
86 checkSets( | |
87 compilerNormal.resolverWorld.directlyInstantiatedClasses, | |
88 compilerDeserialized.resolverWorld.directlyInstantiatedClasses, | |
89 "Directly instantiated classes mismatch", | |
90 areElementsEquivalent, | |
91 verbose: verbose); | |
92 | |
93 checkSets( | |
94 compilerNormal.resolverWorld.instantiatedTypes, | |
95 compilerDeserialized.resolverWorld.instantiatedTypes, | |
96 "Instantiated types mismatch", | |
97 areTypesEquivalent, | |
98 // TODO(johnniwinther): Ensure that all instantiated types are tracked. | |
99 failOnUnfound: false, | |
100 verbose: verbose); | |
101 | |
102 checkSets( | |
103 compilerNormal.resolverWorld.isChecks, | |
104 compilerDeserialized.resolverWorld.isChecks, | |
105 "Is-check mismatch", | |
106 areTypesEquivalent, | |
107 verbose: verbose); | |
108 | |
109 checkSets( | |
110 compilerNormal.enqueuer.resolution.processedElements, | |
111 compilerDeserialized.enqueuer.resolution.processedElements, | |
112 "Processed element mismatch", | |
113 areElementsEquivalent, | |
114 verbose: verbose); | |
115 | |
116 checkClassHierarchyNodes( | |
117 compilerNormal.world.getClassHierarchyNode( | |
118 compilerNormal.coreClasses.objectClass), | |
119 compilerDeserialized.world.getClassHierarchyNode( | |
120 compilerDeserialized.coreClasses.objectClass), | |
121 verbose: verbose); | |
122 } | |
123 | |
124 void checkClassHierarchyNodes( | |
125 ClassHierarchyNode a, ClassHierarchyNode b, | |
126 {bool verbose: false}) { | |
127 if (verbose) { | |
128 print('Checking $a vs $b'); | |
129 } | |
130 Expect.isTrue( | |
131 areElementsEquivalent(a.cls, b.cls), | |
132 "Element identity mismatch for ${a.cls} vs ${b.cls}."); | |
133 Expect.equals( | |
134 a.isDirectlyInstantiated, | |
135 b.isDirectlyInstantiated, | |
136 "Value mismatch for 'isDirectlyInstantiated' for ${a.cls} vs ${b.cls}."); | |
137 Expect.equals( | |
138 a.isIndirectlyInstantiated, | |
139 b.isIndirectlyInstantiated, | |
140 "Value mismatch for 'isIndirectlyInstantiated' " | |
141 "for ${a.cls} vs ${b.cls}."); | |
142 // TODO(johnniwinther): Enforce a canonical and stable order on direct | |
143 // subclasses. | |
144 for (ClassHierarchyNode child in a.directSubclasses) { | |
145 bool found = false; | |
146 for (ClassHierarchyNode other in b.directSubclasses) { | |
147 if (areElementsEquivalent(child.cls, other.cls)) { | |
148 checkClassHierarchyNodes(child, other, | |
149 verbose: verbose); | |
150 found = true; | |
151 break; | |
152 } | |
153 } | |
154 if (!found) { | |
155 Expect.isFalse( | |
156 child.isInstantiated, 'Missing subclass ${child.cls} of ${a.cls}'); | |
157 } | |
158 } | |
159 } | |
160 | |
161 void checkSets( | |
162 Iterable set1, | |
163 Iterable set2, | |
164 String messagePrefix, | |
165 bool areEquivalent(a, b), | |
166 {bool failOnUnfound: true, | |
167 bool verbose: false}) { | |
168 List common = []; | |
169 List unfound = []; | |
170 Set remaining = computeSetDifference( | |
171 set1, set2, common, unfound, areEquivalent); | |
172 StringBuffer sb = new StringBuffer(); | |
173 sb.write("$messagePrefix:"); | |
174 if (verbose) { | |
175 sb.write("\n Common:\n ${common.join('\n ')}"); | |
176 } | |
177 if (unfound.isNotEmpty || verbose) { | |
178 sb.write("\n Unfound:\n ${unfound.join('\n ')}"); | |
179 } | |
180 if (remaining.isNotEmpty || verbose) { | |
181 sb.write("\n Extra: \n ${remaining.join('\n ')}"); | |
182 } | |
183 String message = sb.toString(); | |
184 if (unfound.isNotEmpty || remaining.isNotEmpty) { | |
185 | |
186 if (failOnUnfound || remaining.isNotEmpty) { | |
187 Expect.fail(message); | |
188 } else { | |
189 print(message); | |
190 } | |
191 } else if (verbose) { | |
192 print(message); | |
193 } | |
194 } | |
OLD | NEW |