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

Side by Side Diff: tests/compiler/dart2js/serialization/model_test.dart

Issue 1967073002: Check closure data for serialization (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 4 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.serialization_model_test; 5 library dart2js.serialization_model_test;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 import 'package:async_helper/async_helper.dart'; 9 import 'package:async_helper/async_helper.dart';
10 import 'package:expect/expect.dart'; 10 import 'package:expect/expect.dart';
11 import 'package:compiler/src/closure.dart';
11 import 'package:compiler/src/commandline_options.dart'; 12 import 'package:compiler/src/commandline_options.dart';
12 import 'package:compiler/src/common/backend_api.dart'; 13 import 'package:compiler/src/common/backend_api.dart';
13 import 'package:compiler/src/common/names.dart'; 14 import 'package:compiler/src/common/names.dart';
14 import 'package:compiler/src/common/resolution.dart'; 15 import 'package:compiler/src/common/resolution.dart';
15 import 'package:compiler/src/compiler.dart'; 16 import 'package:compiler/src/compiler.dart';
16 import 'package:compiler/src/dart_types.dart'; 17 import 'package:compiler/src/dart_types.dart';
17 import 'package:compiler/src/elements/elements.dart'; 18 import 'package:compiler/src/elements/elements.dart';
18 import 'package:compiler/src/filenames.dart'; 19 import 'package:compiler/src/filenames.dart';
19 import 'package:compiler/src/serialization/element_serialization.dart'; 20 import 'package:compiler/src/serialization/element_serialization.dart';
20 import 'package:compiler/src/serialization/impact_serialization.dart'; 21 import 'package:compiler/src/serialization/impact_serialization.dart';
21 import 'package:compiler/src/serialization/json_serializer.dart'; 22 import 'package:compiler/src/serialization/json_serializer.dart';
22 import 'package:compiler/src/serialization/serialization.dart'; 23 import 'package:compiler/src/serialization/serialization.dart';
23 import 'package:compiler/src/serialization/equivalence.dart'; 24 import 'package:compiler/src/serialization/equivalence.dart';
24 import 'package:compiler/src/serialization/task.dart'; 25 import 'package:compiler/src/serialization/task.dart';
26 import 'package:compiler/src/tree/nodes.dart';
25 import 'package:compiler/src/universe/world_impact.dart'; 27 import 'package:compiler/src/universe/world_impact.dart';
26 import 'package:compiler/src/universe/class_set.dart'; 28 import 'package:compiler/src/universe/class_set.dart';
27 import 'package:compiler/src/universe/use.dart'; 29 import 'package:compiler/src/universe/use.dart';
28 import '../memory_compiler.dart'; 30 import '../memory_compiler.dart';
29 import 'helper.dart'; 31 import 'helper.dart';
30 import 'test_data.dart'; 32 import 'test_data.dart';
31 import 'test_helper.dart'; 33 import 'test_helper.dart';
32 34
33 main(List<String> args) { 35 main(List<String> args) {
34 asyncTest(() async { 36 asyncTest(() async {
35 Arguments arguments = new Arguments.from(args); 37 Arguments arguments = new Arguments.from(args);
36 String serializedData = await serializeDartCore(arguments: arguments); 38 String serializedData = await serializeDartCore(arguments: arguments);
37 if (arguments.filename != null) { 39 if (arguments.filename != null) {
38 Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename)); 40 Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
39 await check(serializedData, entryPoint); 41 await checkModels(serializedData, entryPoint);
40 } else { 42 } else {
41 Uri entryPoint = Uri.parse('memory:main.dart'); 43 Uri entryPoint = Uri.parse('memory:main.dart');
42 for (Test test in TESTS) { 44 for (Test test in TESTS) {
43 print('=============================================================='); 45 print('==============================================================');
44 print(test.sourceFiles); 46 print(test.sourceFiles);
45 await check( 47 await checkModels(
46 serializedData, 48 serializedData,
47 entryPoint, 49 entryPoint,
48 sourceFiles: test.sourceFiles, 50 sourceFiles: test.sourceFiles,
49 verbose: arguments.verbose); 51 verbose: arguments.verbose);
50 } 52 }
51 } 53 }
52 }); 54 });
53 } 55 }
54 56
55 Future check( 57 Future checkModels(
56 String serializedData, 58 String serializedData,
57 Uri entryPoint, 59 Uri entryPoint,
58 {Map<String, String> sourceFiles: const <String, String>{}, 60 {Map<String, String> sourceFiles: const <String, String>{},
59 bool verbose: false}) async { 61 bool verbose: false}) async {
60 62
61 print('------------------------------------------------------------------'); 63 print('------------------------------------------------------------------');
62 print('compile normal'); 64 print('compile normal');
63 print('------------------------------------------------------------------'); 65 print('------------------------------------------------------------------');
64 Compiler compilerNormal = compilerFor( 66 Compiler compilerNormal = compilerFor(
65 memorySourceFiles: sourceFiles, 67 memorySourceFiles: sourceFiles,
66 options: [Flags.analyzeOnly]); 68 options: [Flags.analyzeOnly]);
67 compilerNormal.resolution.retainCachesForTesting = true; 69 compilerNormal.resolution.retainCachesForTesting = true;
68 await compilerNormal.run(entryPoint); 70 await compilerNormal.run(entryPoint);
69 compilerNormal.phase = Compiler.PHASE_DONE_RESOLVING; 71 compilerNormal.phase = Compiler.PHASE_DONE_RESOLVING;
70 compilerNormal.world.populate(); 72 compilerNormal.world.populate();
73 compilerNormal.backend.onResolutionComplete();
71 74
72 print('------------------------------------------------------------------'); 75 print('------------------------------------------------------------------');
73 print('compile deserialized'); 76 print('compile deserialized');
74 print('------------------------------------------------------------------'); 77 print('------------------------------------------------------------------');
75 Compiler compilerDeserialized = compilerFor( 78 Compiler compilerDeserialized = compilerFor(
76 memorySourceFiles: sourceFiles, 79 memorySourceFiles: sourceFiles,
77 options: [Flags.analyzeOnly]); 80 options: [Flags.analyzeOnly]);
78 compilerDeserialized.resolution.retainCachesForTesting = true; 81 compilerDeserialized.resolution.retainCachesForTesting = true;
79 deserialize(compilerDeserialized, serializedData); 82 deserialize(compilerDeserialized, serializedData);
80 await compilerDeserialized.run(entryPoint); 83 await compilerDeserialized.run(entryPoint);
81 compilerDeserialized.phase = Compiler.PHASE_DONE_RESOLVING; 84 compilerDeserialized.phase = Compiler.PHASE_DONE_RESOLVING;
82 compilerDeserialized.world.populate(); 85 compilerDeserialized.world.populate();
86 compilerDeserialized.backend.onResolutionComplete();
83 87
84 checkAllImpacts( 88 checkAllImpacts(
85 compilerNormal, compilerDeserialized, 89 compilerNormal, compilerDeserialized,
86 verbose: verbose); 90 verbose: verbose);
87 91
88 checkSets( 92 checkSets(
89 compilerNormal.resolverWorld.directlyInstantiatedClasses, 93 compilerNormal.resolverWorld.directlyInstantiatedClasses,
90 compilerDeserialized.resolverWorld.directlyInstantiatedClasses, 94 compilerDeserialized.resolverWorld.directlyInstantiatedClasses,
91 "Directly instantiated classes mismatch", 95 "Directly instantiated classes mismatch",
92 areElementsEquivalent, 96 areElementsEquivalent,
(...skipping 11 matching lines...) Expand all
104 compilerDeserialized.resolverWorld.isChecks, 108 compilerDeserialized.resolverWorld.isChecks,
105 "Is-check mismatch", 109 "Is-check mismatch",
106 areTypesEquivalent, 110 areTypesEquivalent,
107 verbose: verbose); 111 verbose: verbose);
108 112
109 checkSets( 113 checkSets(
110 compilerNormal.enqueuer.resolution.processedElements, 114 compilerNormal.enqueuer.resolution.processedElements,
111 compilerDeserialized.enqueuer.resolution.processedElements, 115 compilerDeserialized.enqueuer.resolution.processedElements,
112 "Processed element mismatch", 116 "Processed element mismatch",
113 areElementsEquivalent, 117 areElementsEquivalent,
118 onSameElement: (a, b) {
119 checkElements(
120 compilerNormal, compilerDeserialized, a, b, verbose: verbose);
121 },
114 verbose: verbose); 122 verbose: verbose);
115 123
116 checkClassHierarchyNodes( 124 checkClassHierarchyNodes(
117 compilerNormal, 125 compilerNormal,
118 compilerDeserialized, 126 compilerDeserialized,
119 compilerNormal.world.getClassHierarchyNode( 127 compilerNormal.world.getClassHierarchyNode(
120 compilerNormal.coreClasses.objectClass), 128 compilerNormal.coreClasses.objectClass),
121 compilerDeserialized.world.getClassHierarchyNode( 129 compilerDeserialized.world.getClassHierarchyNode(
122 compilerDeserialized.coreClasses.objectClass), 130 compilerDeserialized.coreClasses.objectClass),
123 verbose: verbose); 131 verbose: verbose);
124 } 132 }
125 133
134 void checkElements(
135 Compiler compiler1, Compiler compiler2,
136 Element element1, Element element2,
137 {bool verbose: false}) {
138 if (element1.isFunction ||
139 element1.isConstructor ||
140 (element1.isField && element1.isInstanceMember)) {
141 ClosureClassMap closureData1 =
142 compiler1.closureToClassMapper.computeClosureToClassMapping(
143 compiler1.backend.frontend.getResolvedAst(element1.declaration));
144 ClosureClassMap closureData2 =
145 compiler2.closureToClassMapper.computeClosureToClassMapping(
146 compiler2.backend.frontend.getResolvedAst(element2.declaration));
147
148 checkElementIdentities(closureData1, closureData2,
149 '$element1.closureElement',
150 closureData1.closureElement, closureData2.closureElement);
151 checkElementIdentities(closureData1, closureData2,
152 '$element1.closureClassElement',
153 closureData1.closureClassElement, closureData2.closureClassElement);
154 checkElementIdentities(closureData1, closureData2,
155 '$element1.callElement',
156 closureData1.callElement, closureData2.callElement);
157 check(closureData1, closureData2,
158 '$element1.thisLocal',
159 closureData1.thisLocal, closureData2.thisLocal,
160 areLocalsEquivalent);
161 checkMaps(
162 closureData1.freeVariableMap,
163 closureData2.freeVariableMap,
164 "$element1.freeVariableMap",
165 areLocalsEquivalent,
166 areCapturedVariablesEquivalent,
167 verbose: verbose);
168 checkMaps(
169 closureData1.capturingScopes,
170 closureData2.capturingScopes,
171 "$element1.capturingScopes",
172 areNodesEquivalent,
173 areClosureScopesEquivalent,
174 verbose: verbose,
175 keyToString: nodeToString);
176 checkSets(
177 closureData1.variablesUsedInTryOrGenerator,
178 closureData2.variablesUsedInTryOrGenerator,
179 "$element1.variablesUsedInTryOrGenerator",
180 areLocalsEquivalent,
181 verbose: verbose);
182 }
183 }
184
126 void checkMixinUses( 185 void checkMixinUses(
127 Compiler compiler1, Compiler compiler2, 186 Compiler compiler1, Compiler compiler2,
128 ClassElement class1, ClassElement class2, 187 ClassElement class1, ClassElement class2,
129 {bool verbose: false}) { 188 {bool verbose: false}) {
130 189
131 checkSets( 190 checkSets(
132 compiler1.world.mixinUsesOf(class1), 191 compiler1.world.mixinUsesOf(class1),
133 compiler2.world.mixinUsesOf(class2), 192 compiler2.world.mixinUsesOf(class2),
134 "Mixin uses of $class1 vs $class2", 193 "Mixin uses of $class1 vs $class2",
135 areElementsEquivalent, 194 areElementsEquivalent,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 'Missing subclass ${child.cls} of ${node1.cls}'); 234 'Missing subclass ${child.cls} of ${node1.cls}');
176 } 235 }
177 } 236 }
178 checkMixinUses(compiler1, compiler2, node1.cls, node2.cls, verbose: verbose); 237 checkMixinUses(compiler1, compiler2, node1.cls, node2.cls, verbose: verbose);
179 } 238 }
180 239
181 void checkSets( 240 void checkSets(
182 Iterable set1, 241 Iterable set1,
183 Iterable set2, 242 Iterable set2,
184 String messagePrefix, 243 String messagePrefix,
185 bool areEquivalent(a, b), 244 bool sameElement(a, b),
186 {bool failOnUnfound: true, 245 {bool failOnUnfound: true,
187 bool verbose: false}) { 246 bool verbose: false,
247 void onSameElement(a, b)}) {
188 List common = []; 248 List common = [];
189 List unfound = []; 249 List unfound = [];
190 Set remaining = computeSetDifference( 250 Set remaining = computeSetDifference(
191 set1, set2, common, unfound, areEquivalent); 251 set1, set2, common, unfound,
252 sameElement: sameElement,
253 checkElements: onSameElement);
192 StringBuffer sb = new StringBuffer(); 254 StringBuffer sb = new StringBuffer();
193 sb.write("$messagePrefix:"); 255 sb.write("$messagePrefix:");
194 if (verbose) { 256 if (verbose) {
195 sb.write("\n Common:\n ${common.join('\n ')}"); 257 sb.write("\n Common:\n ${common.join('\n ')}");
196 } 258 }
197 if (unfound.isNotEmpty || verbose) { 259 if (unfound.isNotEmpty || verbose) {
198 sb.write("\n Unfound:\n ${unfound.join('\n ')}"); 260 sb.write("\n Unfound:\n ${unfound.join('\n ')}");
199 } 261 }
200 if (remaining.isNotEmpty || verbose) { 262 if (remaining.isNotEmpty || verbose) {
201 sb.write("\n Extra: \n ${remaining.join('\n ')}"); 263 sb.write("\n Extra: \n ${remaining.join('\n ')}");
202 } 264 }
203 String message = sb.toString(); 265 String message = sb.toString();
204 if (unfound.isNotEmpty || remaining.isNotEmpty) { 266 if (unfound.isNotEmpty || remaining.isNotEmpty) {
205 267
206 if (failOnUnfound || remaining.isNotEmpty) { 268 if (failOnUnfound || remaining.isNotEmpty) {
207 Expect.fail(message); 269 Expect.fail(message);
208 } else { 270 } else {
209 print(message); 271 print(message);
210 } 272 }
211 } else if (verbose) { 273 } else if (verbose) {
212 print(message); 274 print(message);
213 } 275 }
214 } 276 }
277
278 String defaultToString(obj) => '$obj';
279
280 void checkMaps(
281 Map map1,
282 Map map2,
283 String messagePrefix,
284 bool sameKey(a, b),
285 bool sameValue(a, b),
286 {bool failOnUnfound: true,
287 bool failOnMismatch: true,
288 bool verbose: false,
289 String keyToString(key): defaultToString,
290 String valueToString(key): defaultToString}) {
291 List common = [];
292 List unfound = [];
293 List<List> mismatch = <List>[];
294 Set remaining = computeSetDifference(
295 map1.keys, map2.keys, common, unfound,
296 sameElement: sameKey,
297 checkElements: (k1, k2) {
298 var v1 = map1[k1];
299 var v2 = map2[k2];
300 if (!sameValue(v1, v2)) {
301 mismatch.add([k1, k2]);
302 }
303 });
304 StringBuffer sb = new StringBuffer();
305 sb.write("$messagePrefix:");
306 if (verbose) {
307 sb.write("\n Common: \n");
308 for (List pair in common) {
309 var k1 = pair[0];
310 var k2 = pair[1];
311 var v1 = map1[k1];
312 var v2 = map2[k2];
313 sb.write(" key1 =${keyToString(k1)}\n");
314 sb.write(" key2 =${keyToString(k2)}\n");
315 sb.write(" value1=${valueToString(v1)}\n");
316 sb.write(" value2=${valueToString(v2)}\n");
317 }
318 }
319 if (unfound.isNotEmpty || verbose) {
320 sb.write("\n Unfound: \n");
321 for (var k1 in unfound) {
322 var v1 = map1[k1];
323 sb.write(" key1 =${keyToString(k1)}\n");
324 sb.write(" value1=${valueToString(v1)}\n");
325 }
326 }
327 if (remaining.isNotEmpty || verbose) {
328 sb.write("\n Extra: \n");
329 for (var k2 in remaining) {
330 var v2 = map2[k2];
331 sb.write(" key2 =${keyToString(k2)}\n");
332 sb.write(" value2=${valueToString(v2)}\n");
333 }
334 }
335 if (mismatch.isNotEmpty || verbose) {
336 sb.write("\n Mismatch: \n");
337 for (List pair in mismatch) {
338 var k1 = pair[0];
339 var k2 = pair[1];
340 var v1 = map1[k1];
341 var v2 = map2[k2];
342 sb.write(" key1 =${keyToString(k1)}\n");
343 sb.write(" key2 =${keyToString(k2)}\n");
344 sb.write(" value1=${valueToString(v1)}\n");
345 sb.write(" value2=${valueToString(v2)}\n");
346 }
347 }
348 String message = sb.toString();
349 if (unfound.isNotEmpty || mismatch.isNotEmpty || remaining.isNotEmpty) {
350 if ((unfound.isNotEmpty && failOnUnfound) ||
351 (mismatch.isNotEmpty && failOnMismatch) ||
352 remaining.isNotEmpty) {
353 Expect.fail(message);
354 } else {
355 print(message);
356 }
357 } else if (verbose) {
358 print(message);
359 }
360 }
361
362 bool areLocalsEquivalent(Local a, Local b) {
363 if (a == b) return true;
364 if (a == null || b == null) return false;
365
366 if (a is Element) {
367 return b is Element && areElementsEquivalent(a as Element, b as Element);
368 } else {
369 return a.runtimeType == b.runtimeType &&
370 areElementsEquivalent(a.executableContext, b.executableContext);
371 }
372 }
373
374 bool areCapturedVariablesEquivalent(CapturedVariable a, CapturedVariable b) {
375 if (a == b) return true;
376 if (a == null || b == null) return false;
377 if (a is ClosureFieldElement && b is ClosureFieldElement) {
378 return areElementsEquivalent(a.closureClass, b.closureClass) &&
379 areLocalsEquivalent(a.local, b.local);
380 } else if (a is BoxFieldElement && b is BoxFieldElement) {
381 return areElementsEquivalent(a.variableElement, b.variableElement) &&
382 areLocalsEquivalent(a.box, b.box);
383 }
384 return false;
385 }
386
387 bool areClosureScopesEquivalent(ClosureScope a, ClosureScope b) {
388 if (a == b) return true;
389 if (a == null || b == null) return false;
390 if (!areLocalsEquivalent(a.boxElement, b.boxElement)) {
391 return false;
392 }
393 checkMaps(a.capturedVariables, b.capturedVariables,
394 'ClosureScope.capturedVariables',
395 areLocalsEquivalent,
396 areElementsEquivalent);
397 checkSets(a.boxedLoopVariables, b.boxedLoopVariables,
398 'ClosureScope.boxedLoopVariables',
399 areElementsEquivalent);
400 return true;
401 }
402
403 String nodeToString(Node node) {
404 String text = '$node';
405 if (text.length > 40) {
406 return '(${node.runtimeType}) ${text.substring(0, 37)}...';
407 }
408 return '(${node.runtimeType}) $text';
409 }
OLDNEW
« no previous file with comments | « tests/compiler/dart2js/serialization/helper.dart ('k') | tests/compiler/dart2js/serialization/resolved_ast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698