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

Side by Side Diff: test/dependency_graph_test.dart

Issue 973433003: Initial cut for a development server (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 9 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
(Empty)
1 library ddc.test.dependency_graph_test;
Jennifer Messerly 2015/03/03 02:24:22 copyright header?
Siggi Cherem (dart-lang) 2015/03/04 04:44:24 Done.
2
3 import 'package:unittest/compact_vm_config.dart';
4 import 'package:unittest/unittest.dart';
5
6 import 'package:dev_compiler/src/checker/dart_sdk.dart'
7 show mockSdkSources, dartSdkDirectory;
8 import 'package:dev_compiler/src/testing.dart';
9 import 'package:dev_compiler/src/options.dart';
10 import 'package:dev_compiler/src/checker/resolver.dart';
11 import 'package:dev_compiler/src/dependency_graph.dart';
12 import 'package:path/path.dart' as path;
13
14 main() {
15 groupSep = " > ";
16 useCompactVMConfiguration();
17
18 var options = new CompilerOptions();
19 var testUriResolver;
20 var context;
21 var graph;
22
23 /// Initial values for test files
24 var testFiles = {
25 '/index1.html': '''
26 <script src="foo.js"></script>
27 ''',
28 '/index2.html': '''
29 <script type="application/dart" src="a1.dart"></script>
30 ''',
31 '/index3.html': '''
32 <script type="application/dart" src="a2.dart"></script>
33 ''',
34 '/a1.dart': '''
35 library a1;
36 ''',
37 '/a2.dart': '''
38 library a2;
39 import 'a3.dart';
40 import 'a4.dart';
41 export 'a5.dart';
42 part 'a6.dart';
43 ''',
44 '/a3.dart': 'library a3;',
45 '/a4.dart': 'library a4; export "a10.dart";',
46 '/a5.dart': 'library a5;',
47 '/a6.dart': 'part of a2;',
48 '/a8.dart': 'library a8; import "a8.dart";',
49 '/a9.dart': 'library a9; import "a8.dart";',
50 '/a10.dart': 'library a10;',
51 };
52
53 nodeOf(String filepath, [bool isPart = false]) =>
54 graph.nodeFromUri(new Uri.file(filepath), isPart);
55
56 setUp(() {
57 /// We completely reset the TestUriResolver to avoid interference between
58 /// tests (since some tests modify the state of the files).
59 testUriResolver = new TestUriResolver(testFiles);
60 context = new TypeResolver.fromMock(mockSdkSources, options,
61 otherResolvers: [testUriResolver]).context;
62 graph = new SourceGraph(context, options);
63 });
64
65 group('HTML deps', () {
66 test('initial deps', () {
67 var i1 = nodeOf('/index1.html');
68 var i2 = nodeOf('/index2.html');
69 expect(i1.scripts.length, 0);
70 expect(i2.scripts.length, 0);
71 i1.update(graph);
72 i2.update(graph);
73 expect(i1.scripts.length, 0);
74 expect(i2.scripts.length, 1);
75 expect(i2.scripts.first, nodeOf('/a1.dart'));
76 });
77
78 test('add a dep', () {
79 // After initial load, dependencies are 0:
80 var node = nodeOf('/index1.html');
81 node.update(graph);
82 expect(node.scripts.length, 0);
83
84 // Adding the dependency is discovered on the next round of updates:
85 node.source.contents.modificationTime++;
86 node.source.contents.data =
87 '<script type="application/dart" src="a2.dart"></script>';
88 expect(node.scripts.length, 0);
89 node.update(graph);
90 expect(node.scripts.length, 1);
91 expect(node.scripts.first, nodeOf('/a2.dart'));
92 });
93
94 test('add more deps', () {
95 // After initial load, dependencies are 1:
96 var node = nodeOf('/index2.html');
97 node.update(graph);
98 expect(node.scripts.length, 1);
99 expect(node.scripts.first, nodeOf('/a1.dart'));
100
101 node.source.contents.modificationTime++;
102 node.source.contents.data +=
103 '<script type="application/dart" src="a2.dart"></script>';
104 expect(node.scripts.length, 1);
105 node.update(graph);
106 expect(node.scripts.length, 2);
107 expect(node.scripts.first, nodeOf('/a1.dart'));
108 expect(node.scripts.last, nodeOf('/a2.dart'));
109 });
110
111 test('remove all deps', () {
112 // After initial load, dependencies are 1:
113 var node = nodeOf('/index2.html');
114 node.update(graph);
115 expect(node.scripts.length, 1);
116 expect(node.scripts.first, nodeOf('/a1.dart'));
117
118 // Removing the dependency is discovered on the next round of updates:
119 node.source.contents.modificationTime++;
120 node.source.contents.data = '';
121 expect(node.scripts.length, 1);
122 node.update(graph);
123 expect(node.scripts.length, 0);
124 });
125 });
126
127 group('Dart deps', () {
128 test('initial deps', () {
129 var a1 = nodeOf('/a1.dart');
130 var a2 = nodeOf('/a2.dart');
131 expect(a1.imports.length, 0);
132 expect(a1.exports.length, 0);
133 expect(a1.parts.length, 0);
134 expect(a2.imports.length, 0);
135 expect(a2.exports.length, 0);
136 expect(a2.parts.length, 0);
137
138 a1.update(graph);
139 a2.update(graph);
140
141 expect(a1.imports.length, 0);
142 expect(a1.exports.length, 0);
143 expect(a1.parts.length, 0);
144 expect(a2.imports.length, 2);
145 expect(a2.exports.length, 1);
146 expect(a2.parts.length, 1);
147 expect(a2.imports.contains(nodeOf('/a3.dart')), isTrue);
148 expect(a2.imports.contains(nodeOf('/a4.dart')), isTrue);
149 expect(a2.exports.contains(nodeOf('/a5.dart')), isTrue);
150 expect(a2.parts.contains(nodeOf('/a6.dart')), isTrue);
151 });
152
153 test('add deps', () {
154 var node = nodeOf('/a1.dart');
155 node.update(graph);
156 expect(node.imports.length, 0);
157 expect(node.exports.length, 0);
158 expect(node.parts.length, 0);
159
160 node.source.contents.modificationTime++;
161 node.source.contents.data =
162 'import "a3.dart"; export "a5.dart"; part "a8.dart";';
163 node.update(graph);
164
165 expect(node.imports.length, 1);
166 expect(node.exports.length, 1);
167 expect(node.parts.length, 1);
168 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue);
169 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue);
170 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue);
171 });
172
173 test('remove deps', () {
174 var node = nodeOf('/a2.dart');
175 node.update(graph);
176 expect(node.imports.length, 2);
177 expect(node.exports.length, 1);
178 expect(node.parts.length, 1);
179 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue);
180 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue);
181 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue);
182 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue);
183
184 node.source.contents.modificationTime++;
185 node.source.contents.data =
186 'import "a3.dart"; export "a6.dart"; part "a8.dart";';
187 node.update(graph);
188
189 expect(node.imports.length, 1);
190 expect(node.exports.length, 1);
191 expect(node.parts.length, 1);
192 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue);
193 expect(node.exports.contains(nodeOf('/a6.dart')), isTrue);
194 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue);
195 });
196 });
197
198 group('local changes', () {
199 group('needs rebuild', () {
200 test('in HTML', () {
201 var node = nodeOf('/index1.html');
202 node.update(graph);
203 expect(node.needsRebuild, isTrue);
204 node.needsRebuild = false;
205
206 node.update(graph);
207 expect(node.needsRebuild, isFalse);
208
209 // For now, an empty modification is enough to trigger a rebuild
210 node.source.contents.modificationTime++;
211 expect(node.needsRebuild, isFalse);
212 node.update(graph);
213 expect(node.needsRebuild, isTrue);
214 });
215
216 test('main library in Dart', () {
217 var node = nodeOf('/a2.dart');
218 var partNode = nodeOf('/a6.dart', true);
219 node.update(graph);
220 expect(node.needsRebuild, isTrue);
221 node.needsRebuild = false;
222 partNode.needsRebuild = false;
223
224 node.update(graph);
225 expect(node.needsRebuild, isFalse);
226
227 // For now, an empty modification is enough to trigger a rebuild
228 node.source.contents.modificationTime++;
229 expect(node.needsRebuild, isFalse);
230 node.update(graph);
231 expect(node.needsRebuild, isTrue);
232 });
233
234 test('part of library in Dart', () {
235 var node = nodeOf('/a2.dart');
236 var importNode = nodeOf('/a3.dart');
237 var exportNode = nodeOf('/a5.dart');
238 var partNode = nodeOf('/a6.dart', true);
239 node.update(graph);
240 expect(node.needsRebuild, isTrue);
241 node.needsRebuild = false;
242 partNode.needsRebuild = false;
243
244 node.update(graph);
245 expect(node.needsRebuild, isFalse);
246
247 // Modification in imported/exported node makes no difference for local
248 // rebuild label (globally that's tested elsewhere)
249 importNode.source.contents.modificationTime++;
250 exportNode.source.contents.modificationTime++;
251 node.update(graph);
252 expect(node.needsRebuild, isFalse);
253 expect(partNode.needsRebuild, isFalse);
254
255 // Modification in part triggers change in containing library:
256 partNode.source.contents.modificationTime++;
257 expect(node.needsRebuild, isFalse);
258 expect(partNode.needsRebuild, isFalse);
259 node.update(graph);
260 expect(node.needsRebuild, isTrue);
261 expect(partNode.needsRebuild, isTrue);
262 });
263 });
264
265 group('structure change', () {
266 test('no mod in HTML', () {
267 var node = nodeOf('/index2.html');
268 node.update(graph);
269 expect(node.structureChanged, isTrue);
270 node.structureChanged = false;
271
272 node.update(graph);
273 expect(node.structureChanged, isFalse);
274
275 // An empty modification will not trigger a structural change
276 node.source.contents.modificationTime++;
277 expect(node.structureChanged, isFalse);
278 node.update(graph);
279 expect(node.structureChanged, isFalse);
280 });
281
282 test('added scripts in HTML', () {
283 var node = nodeOf('/index2.html');
284 node.update(graph);
285 expect(node.structureChanged, isTrue);
286 expect(node.scripts.length, 1);
287
288 node.structureChanged = false;
289 node.update(graph);
290 expect(node.structureChanged, isFalse);
291
292 // This change will not include new script tags:
293 node.source.contents.modificationTime++;
294 node.source.contents.data += '<div></div>';
295 expect(node.structureChanged, isFalse);
296 node.update(graph);
297 expect(node.structureChanged, isFalse);
298 expect(node.scripts.length, 1);
299
300 node.source.contents.modificationTime++;
301 node.source.contents.data +=
302 '<script type="application/dart" src="a4.dart"></script>';
303 expect(node.structureChanged, isFalse);
304 node.update(graph);
305 expect(node.structureChanged, isTrue);
306 expect(node.scripts.length, 2);
307 });
308
309 test('no mod in Dart', () {
310 var node = nodeOf('/a2.dart');
311 var importNode = nodeOf('/a3.dart');
312 var exportNode = nodeOf('/a5.dart');
313 var partNode = nodeOf('/a6.dart', true);
314 node.update(graph);
315 expect(node.structureChanged, isTrue);
316 node.structureChanged = false;
317
318 node.update(graph);
319 expect(node.structureChanged, isFalse);
320
321 // These modifications make no difference at all.
322 importNode.source.contents.modificationTime++;
323 exportNode.source.contents.modificationTime++;
324 partNode.source.contents.modificationTime++;
325 node.source.contents.modificationTime++;
326
327 expect(node.structureChanged, isFalse);
328 node.update(graph);
329 expect(node.structureChanged, isFalse);
330 });
331
332 test('same directives, different order', () {
333 var node = nodeOf('/a2.dart');
334 node.update(graph);
335 expect(node.structureChanged, isTrue);
336 node.structureChanged = false;
337
338 node.update(graph);
339 expect(node.structureChanged, isFalse);
340
341 // modified order of imports, but structure stays the same:
342 node.source.contents.modificationTime++;
343 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; '
344 'export "a5.dart"; part "a6.dart";';
345 node.update(graph);
346
347 expect(node.structureChanged, isFalse);
348 node.update(graph);
349 expect(node.structureChanged, isFalse);
350 });
351
352 test('changed parts', () {
353 var node = nodeOf('/a2.dart');
354 node.update(graph);
355 expect(node.structureChanged, isTrue);
356 node.structureChanged = false;
357
358 node.update(graph);
359 expect(node.structureChanged, isFalse);
360
361 // added one.
362 node.source.contents.modificationTime++;
363 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; '
364 'export "a5.dart"; part "a6.dart"; part "a7.dart";';
365 expect(node.structureChanged, isFalse);
366 node.update(graph);
367 expect(node.structureChanged, isTrue);
368
369 // no change
370 node.structureChanged = false;
371 node.source.contents.modificationTime++;
372 node.update(graph);
373 expect(node.structureChanged, isFalse);
374
375 // removed one
376 node.source.contents.modificationTime++;
377 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; '
378 'export "a5.dart"; part "a7.dart";';
379 expect(node.structureChanged, isFalse);
380 node.update(graph);
381 expect(node.structureChanged, isTrue);
382 });
383
384 test('changed import', () {
385 var node = nodeOf('/a2.dart');
386 node.update(graph);
387 expect(node.structureChanged, isTrue);
388 node.structureChanged = false;
389
390 node.update(graph);
391 expect(node.structureChanged, isFalse);
392
393 // added one.
394 node.source.contents.modificationTime++;
395 node.source.contents.data =
396 'import "a4.dart"; import "a3.dart"; import "a7.dart";'
397 'export "a5.dart"; part "a6.dart";';
398 expect(node.structureChanged, isFalse);
399 node.update(graph);
400 expect(node.structureChanged, isTrue);
401
402 // no change
403 node.structureChanged = false;
404 node.source.contents.modificationTime++;
405 node.update(graph);
406 expect(node.structureChanged, isFalse);
407
408 // removed one
409 node.source.contents.modificationTime++;
410 node.source.contents.data = 'import "a4.dart"; import "a7.dart"; '
411 'export "a5.dart"; part "a6.dart";';
412 expect(node.structureChanged, isFalse);
413 node.update(graph);
414 expect(node.structureChanged, isTrue);
415 });
416
417 test('changed exports', () {
418 var node = nodeOf('/a2.dart');
419 node.update(graph);
420 expect(node.structureChanged, isTrue);
421 node.structureChanged = false;
422
423 node.update(graph);
424 expect(node.structureChanged, isFalse);
425
426 // added one.
427 node.source.contents.modificationTime++;
428 node.source.contents.data = 'import "a4.dart"; import "a3.dart";'
429 'export "a5.dart"; export "a9.dart"; part "a6.dart";';
430 expect(node.structureChanged, isFalse);
431 node.update(graph);
432 expect(node.structureChanged, isTrue);
433
434 // no change
435 node.structureChanged = false;
436 node.source.contents.modificationTime++;
437 node.update(graph);
438 expect(node.structureChanged, isFalse);
439
440 // removed one
441 node.source.contents.modificationTime++;
442 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; '
443 'export "a5.dart"; part "a6.dart";';
444 expect(node.structureChanged, isFalse);
445 node.update(graph);
446 expect(node.structureChanged, isTrue);
447 });
448 });
449 });
450
451 group('refresh structure and marks', () {
452 test('initial marks', () {
453 var node = nodeOf('/index3.html');
454 expectGraph(node, 'index3.html');
455 refreshStructureAndMarks(node, graph);
456 expectGraph(node, '''
457 index3.html [needs-rebuild] [structure-changed]
458 |-- a2.dart [needs-rebuild] [structure-changed]
459 | |-- a3.dart [needs-rebuild]
460 | |-- a4.dart [needs-rebuild] [structure-changed]
461 | | |-- a10.dart [needs-rebuild]
462 | |-- a5.dart [needs-rebuild]
463 | |-- a6.dart [needs-rebuild]
464 ''');
465 });
466
467 test('cleared marks stay clear', () {
468 var node = nodeOf('/index3.html');
469 refreshStructureAndMarks(node, graph);
470 expectGraph(node, '''
471 index3.html [needs-rebuild] [structure-changed]
472 |-- a2.dart [needs-rebuild] [structure-changed]
473 | |-- a3.dart [needs-rebuild]
474 | |-- a4.dart [needs-rebuild] [structure-changed]
475 | | |-- a10.dart [needs-rebuild]
476 | |-- a5.dart [needs-rebuild]
477 | |-- a6.dart [needs-rebuild]
478 ''');
479 clearMarks(node);
480 expectGraph(node, '''
481 index3.html
482 |-- a2.dart
483 | |-- a3.dart
484 | |-- a4.dart
485 | | |-- a10.dart
486 | |-- a5.dart
487 | |-- a6.dart
488 ''');
489
490 refreshStructureAndMarks(node, graph);
491 expectGraph(node, '''
492 index3.html
493 |-- a2.dart
494 | |-- a3.dart
495 | |-- a4.dart
496 | | |-- a10.dart
497 | |-- a5.dart
498 | |-- a6.dart
499 ''');
500 });
501
502 test('needsRebuild mark updated on local modifications', () {
503 var node = nodeOf('/index3.html');
504 refreshStructureAndMarks(node, graph);
505 clearMarks(node);
506 var a3 = nodeOf('/a3.dart');
507 a3.source.contents.modificationTime++;
508
509 refreshStructureAndMarks(node, graph);
510 expectGraph(node, '''
511 index3.html
512 |-- a2.dart
513 | |-- a3.dart [needs-rebuild]
514 | |-- a4.dart
515 | | |-- a10.dart
516 | |-- a5.dart
517 | |-- a6.dart
518 ''');
519 });
520
521 test('structuredChanged mark updated on structure modifications', () {
522 var node = nodeOf('/index3.html');
523 refreshStructureAndMarks(node, graph);
524 clearMarks(node);
525 var a5 = nodeOf('/a5.dart');
526 a5.source.contents.modificationTime++;
527 a5.source.contents.data = 'import "a8.dart";';
528
529 refreshStructureAndMarks(node, graph);
530 expectGraph(node, '''
531 index3.html
532 |-- a2.dart
533 | |-- a3.dart
534 | |-- a4.dart
535 | | |-- a10.dart
536 | |-- a5.dart [needs-rebuild] [structure-changed]
537 | | |-- a8.dart [needs-rebuild] [structure-changed]
538 | | | |-- a8.dart...
539 | |-- a6.dart
540 ''');
541 });
542 });
543
544 group('rebuild', () {
545 var results;
546 void addName(SourceNode n) => results.add(nameFor(n));
547
548 bool buildNoTransitiveChange(SourceNode n) {
549 addName(n);
550 return false;
551 }
552
553 bool buildWithTransitiveChange(SourceNode n) {
554 addName(n);
555 return true;
556 }
557
558 setUp(() {
559 results = [];
560 });
561
562 test('everything build on first run', () {
563 var node = nodeOf('/index3.html');
564 rebuild(node, graph, buildNoTransitiveChange);
565 // Note: a6.dart is not included because it built as part of a2.dart
566 expect(results, [
567 'a3.dart',
568 'a10.dart',
569 'a4.dart',
570 'a5.dart',
571 'a2.dart',
572 'index3.html'
573 ]);
574
575 // Marks are removed automatically by rebuild
576 expectGraph(node, '''
577 index3.html
578 |-- a2.dart
579 | |-- a3.dart
580 | |-- a4.dart
581 | | |-- a10.dart
582 | |-- a5.dart
583 | |-- a6.dart
584 ''');
585 });
586
587 test('nothing to do after build', () {
588 var node = nodeOf('/index3.html');
589 rebuild(node, graph, buildNoTransitiveChange);
590
591 results = [];
592 rebuild(node, graph, buildNoTransitiveChange);
593 expect(results, []);
594 });
595
596 test('modified part triggers building library', () {
597 var node = nodeOf('/index3.html');
598 rebuild(node, graph, buildNoTransitiveChange);
599 results = [];
600
601 var a6 = nodeOf('/a6.dart');
602 a6.source.contents.modificationTime++;
603 rebuild(node, graph, buildNoTransitiveChange);
604 expect(results, ['a2.dart']);
605
606 results = [];
607 rebuild(node, graph, buildNoTransitiveChange);
608 expect(results, []);
609 });
610
611 test('non-API change triggers build stays local', () {
612 var node = nodeOf('/index3.html');
613 rebuild(node, graph, buildNoTransitiveChange);
614 results = [];
615
616 var a3 = nodeOf('/a3.dart');
617 a3.source.contents.modificationTime++;
618 rebuild(node, graph, buildNoTransitiveChange);
619 expect(results, ['a3.dart']);
620
621 results = [];
622 rebuild(node, graph, buildNoTransitiveChange);
623 expect(results, []);
624 });
625
626 test('no-API change in exported file stays local', () {
627 var node = nodeOf('/index3.html');
628 rebuild(node, graph, buildNoTransitiveChange);
629 results = [];
630
631 // similar to the test above, but a10 is exported from a4.
632 var a3 = nodeOf('/a10.dart');
633 a3.source.contents.modificationTime++;
634 rebuild(node, graph, buildNoTransitiveChange);
635 expect(results, ['a10.dart']);
636
637 results = [];
638 rebuild(node, graph, buildNoTransitiveChange);
639 expect(results, []);
640 });
641
642 test('API change in lib, triggers build on imports', () {
643 var node = nodeOf('/index3.html');
644 rebuild(node, graph, buildNoTransitiveChange);
645 results = [];
646
647 var a3 = nodeOf('/a3.dart');
648 a3.source.contents.modificationTime++;
649 rebuild(node, graph, buildWithTransitiveChange);
650 expect(results, ['a3.dart', 'a2.dart']);
651
652 results = [];
653 rebuild(node, graph, buildNoTransitiveChange);
654 expect(results, []);
655 });
656
657 test('API change in export, triggers build on imports', () {
658 var node = nodeOf('/index3.html');
659 rebuild(node, graph, buildNoTransitiveChange);
660 results = [];
661
662 var a3 = nodeOf('/a10.dart');
663 a3.source.contents.modificationTime++;
664 rebuild(node, graph, buildWithTransitiveChange);
665
666 // Node: a4.dart reexports a10.dart, but it doesn't import it, so we don't
667 // need to rebuild it.
668 expect(results, ['a10.dart', 'a2.dart']);
669
670 results = [];
671 rebuild(node, graph, buildNoTransitiveChange);
672 expect(results, []);
673 });
674
675 test('structural change rebuilds HTML, but skips unreachable code', () {
676 var node = nodeOf('/index3.html');
677 rebuild(node, graph, buildNoTransitiveChange);
678 results = [];
679
680 var a2 = nodeOf('/a2.dart');
681 a2.source.contents.modificationTime++;
682 a2.source.contents.data = 'import "a4.dart";';
683
684 var a3 = nodeOf('/a3.dart');
685 a3.source.contents.modificationTime++;
686 rebuild(node, graph, buildNoTransitiveChange);
687
688 // a3 will become unreachable, index3 reflects structural changes.
689 expect(results, ['a2.dart', 'index3.html']);
690
691 results = [];
692 rebuild(node, graph, buildNoTransitiveChange);
693 expect(results, []);
694 });
695
696 test('newly discovered files get built too', () {
697 var node = nodeOf('/index3.html');
698 rebuild(node, graph, buildNoTransitiveChange);
699 results = [];
700
701 var a2 = nodeOf('/a2.dart');
702 a2.source.contents.modificationTime++;
703 a2.source.contents.data = 'import "a9.dart";';
704
705 rebuild(node, graph, buildNoTransitiveChange);
706 expect(results, ['a8.dart', 'a9.dart', 'a2.dart', 'index3.html']);
707
708 results = [];
709 rebuild(node, graph, buildNoTransitiveChange);
710 expect(results, []);
711 });
712 });
713 }
714
715 expectGraph(SourceNode node, String expectation) {
716 expect(printReachable(node), equalsIgnoringWhitespace(expectation));
717 }
718
719 nameFor(SourceNode node) => path.basename(node.uri.path);
720 printReachable(SourceNode node) {
721 var seen = new Set();
722 var sb = new StringBuffer();
723 helper(n, {indent: 0}) {
724 if (indent > 0) {
725 sb
726 ..write("| " * (indent - 1))
727 ..write("|-- ");
728 }
729 sb.write(nameFor(n));
730 if (seen.contains(n)) {
731 sb.write('...\n');
732 return;
733 }
734 seen.add(n);
735 sb
736 ..write(' ')
737 ..write(n.needsRebuild ? '[needs-rebuild] ' : '')
738 ..write(n.structureChanged ? '[structure-changed] ' : ' ')
739 ..write('\n');
740 n.directDeps.forEach((e) => helper(e, indent: indent + 1));
741 }
742 helper(node);
743 return sb.toString();
744 }
745
746 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698