OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016, 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 import 'dart:async'; | |
6 | |
7 import 'package:front_end/compiler_options.dart'; | |
8 import 'package:front_end/dependency_grapher.dart'; | |
9 import 'package:front_end/memory_file_system.dart'; | |
10 import 'package:path/path.dart' as pathos; | |
11 import 'package:test/test.dart'; | |
12 import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
13 | |
14 main() { | |
15 defineReflectiveSuite(() { | |
16 defineReflectiveTests(DependencyGrapherTest); | |
17 }); | |
18 } | |
19 | |
20 @reflectiveTest | |
21 class DependencyGrapherTest { | |
22 LibraryNode checkLibrary(LibraryCycleNode cycle, String uri, | |
23 {List<String> dependencies: const [], List<String> parts: const []}) { | |
24 var library = cycle.libraries[Uri.parse(uri)]; | |
25 expect(library.uri.toString(), uri); | |
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
style nit: I prefer '${library.uri}'
It's shorter
Paul Berry
2016/12/16 02:46:45
Done.
| |
26 expect(library.dependencies.map((dep) => dep.uri.toString()).toList(), | |
27 unorderedEquals(dependencies)); | |
28 expect( | |
29 library.parts.map((part) => part.toString()), unorderedEquals(parts)); | |
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
is .toList needed here (or not needed above?)
Paul Berry
2016/12/16 02:46:45
Not needed above. Good catch.
| |
30 return library; | |
31 } | |
32 | |
33 Future<List<LibraryCycleNode>> getCycles(Map<String, String> contents, | |
34 [List<String> startingPoints]) async { | |
35 // If no starting points given, assume the first entry in [contents] is the | |
36 // single starting point. | |
37 startingPoints ??= [contents.keys.first]; | |
38 var fileSystem = new MemoryFileSystem(pathos.posix, '/'); | |
39 contents.forEach((path, text) { | |
40 fileSystem.entityForPath(path).writeAsStringSync(text); | |
41 }); | |
42 // TODO(paulberry): implement and test other option possibilities. | |
43 var options = new CompilerOptions() | |
44 ..fileSystem = fileSystem | |
45 ..chaseDependencies = true; | |
46 var graph = await graphForProgram( | |
47 startingPoints.map(pathos.posix.toUri).toList(), options); | |
48 return graph.topologicallySortedCycles; | |
49 } | |
50 | |
51 /// Sort the given library cycles into a deterministic order based on their | |
52 /// URIs for easier unit testing. | |
53 List<LibraryCycleNode> sortCycles(Iterable<LibraryCycleNode> cycles) { | |
54 var result = cycles.toList(); | |
55 String sortKey(LibraryCycleNode node) => node.libraries.keys.join(','); | |
56 result.sort((a, b) => Comparable.compare(sortKey(a), sortKey(b))); | |
57 return result; | |
58 } | |
59 | |
60 test_exportDependency() async { | |
61 var cycles = | |
62 await getCycles({'/foo.dart': 'export "bar.dart";', '/bar.dart': ''}); | |
63 expect(cycles, hasLength(2)); | |
64 expect(cycles[0].libraries, hasLength(1)); | |
65 checkLibrary(cycles[0], 'file:///bar.dart'); | |
66 expect(cycles[1].libraries, hasLength(1)); | |
67 checkLibrary(cycles[1], 'file:///foo.dart', | |
68 dependencies: ['file:///bar.dart']); | |
69 } | |
70 | |
71 test_importDependency() async { | |
72 var cycles = | |
73 await getCycles({'/foo.dart': 'import "bar.dart";', '/bar.dart': ''}); | |
74 expect(cycles, hasLength(2)); | |
75 expect(cycles[0].libraries, hasLength(1)); | |
76 checkLibrary(cycles[0], 'file:///bar.dart'); | |
77 expect(cycles[1].libraries, hasLength(1)); | |
78 checkLibrary(cycles[1], 'file:///foo.dart', | |
79 dependencies: ['file:///bar.dart']); | |
80 } | |
81 | |
82 test_multipleStartingPoints() async { | |
83 var cycles = await getCycles({ | |
84 '/a.dart': 'import "c.dart";', | |
85 '/b.dart': 'import "c.dart";', | |
86 '/c.dart': '' | |
87 }, [ | |
88 '/a.dart', | |
89 '/b.dart' | |
90 ]); | |
91 expect(cycles, hasLength(3)); | |
92 expect(cycles[0].libraries, hasLength(1)); | |
93 checkLibrary(cycles[0], 'file:///c.dart'); | |
94 // The other two cycles might be in any order, so sort them for | |
95 // reproducibility. | |
96 List<LibraryCycleNode> otherCycles = sortCycles(cycles.sublist(1)); | |
97 checkLibrary(otherCycles[0], 'file:///a.dart', | |
98 dependencies: ['file:///c.dart']); | |
99 checkLibrary(otherCycles[1], 'file:///b.dart', | |
100 dependencies: ['file:///c.dart']); | |
101 } | |
102 | |
103 test_parts() async { | |
104 var cycles = await getCycles({ | |
105 '/foo.dart': 'library foo; part "a.dart"; part "b.dart";', | |
106 '/a.dart': 'part of foo;', | |
107 '/b.dart': 'part of foo;' | |
108 }); | |
109 expect(cycles, hasLength(1)); | |
110 expect(cycles[0].libraries, hasLength(1)); | |
111 checkLibrary(cycles[0], 'file:///foo.dart', | |
112 parts: ['file:///a.dart', 'file:///b.dart']); | |
113 } | |
114 | |
115 test_relativeUris() async { | |
116 var cycles = await getCycles({ | |
117 '/a.dart': 'import "b/c.dart";', | |
118 '/b/c.dart': 'import "d/e.dart";', | |
119 '/b/d/e.dart': 'import "../f.dart";', | |
120 '/b/f.dart': '' | |
121 }); | |
122 expect(cycles, hasLength(4)); | |
123 expect(cycles[0].libraries, hasLength(1)); | |
124 checkLibrary(cycles[0], 'file:///b/f.dart'); | |
125 expect(cycles[1].libraries, hasLength(1)); | |
126 checkLibrary(cycles[1], 'file:///b/d/e.dart', | |
127 dependencies: ['file:///b/f.dart']); | |
128 expect(cycles[2].libraries, hasLength(1)); | |
129 checkLibrary(cycles[2], 'file:///b/c.dart', | |
130 dependencies: ['file:///b/d/e.dart']); | |
131 expect(cycles[3].libraries, hasLength(1)); | |
132 checkLibrary(cycles[3], 'file:///a.dart', | |
133 dependencies: ['file:///b/c.dart']); | |
134 } | |
135 | |
136 test_simpleCycle() async { | |
137 var cycles = await getCycles( | |
138 {'/foo.dart': 'import "bar.dart";', '/bar.dart': 'import "foo.dart";'}); | |
139 expect(cycles, hasLength(1)); | |
140 expect(cycles[0].libraries, hasLength(2)); | |
141 var foo = checkLibrary(cycles[0], 'file:///foo.dart', | |
142 dependencies: ['file:///bar.dart']); | |
143 var bar = checkLibrary(cycles[0], 'file:///bar.dart', | |
144 dependencies: ['file:///foo.dart']); | |
145 expect(foo.dependencies[0], same(bar)); | |
146 expect(bar.dependencies[0], same(foo)); | |
147 } | |
148 | |
149 test_singleFile() async { | |
150 var cycles = await getCycles({'/foo.dart': ''}); | |
151 expect(cycles, hasLength(1)); | |
152 expect(cycles[0].libraries, hasLength(1)); | |
153 checkLibrary(cycles[0], 'file:///foo.dart'); | |
154 } | |
155 } | |
OLD | NEW |