| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:front_end/compiler_options.dart'; | 7 import 'package:front_end/compiler_options.dart'; |
| 8 import 'package:front_end/dependency_grapher.dart'; | 8 import 'package:front_end/dependency_grapher.dart'; |
| 9 import 'package:front_end/memory_file_system.dart'; | 9 import 'package:front_end/memory_file_system.dart'; |
| 10 import 'package:path/path.dart' as pathos; | 10 import 'package:path/path.dart' as pathos; |
| 11 import 'package:test/test.dart'; | 11 import 'package:test/test.dart'; |
| 12 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 12 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 13 | 13 |
| 14 main() { | 14 main() { |
| 15 defineReflectiveSuite(() { | 15 defineReflectiveSuite(() { |
| 16 defineReflectiveTests(DependencyGrapherTest); | 16 defineReflectiveTests(DependencyGrapherTest); |
| 17 }); | 17 }); |
| 18 } | 18 } |
| 19 | 19 |
| 20 @reflectiveTest | 20 @reflectiveTest |
| 21 class DependencyGrapherTest { | 21 class DependencyGrapherTest { |
| 22 LibraryNode checkLibrary(LibraryCycleNode cycle, String uri, | 22 LibraryNode checkLibrary(LibraryCycleNode cycle, String uri, |
| 23 {List<String> dependencies: const [], List<String> parts: const []}) { | 23 {List<String> dependencies: const ['dart:core'], |
| 24 List<String> parts: const []}) { |
| 24 var library = cycle.libraries[Uri.parse(uri)]; | 25 var library = cycle.libraries[Uri.parse(uri)]; |
| 25 expect('${library.uri}', uri); | 26 expect('${library.uri}', uri); |
| 26 expect(library.dependencies.map((dep) => '${dep.uri}'), | 27 expect(library.dependencies.map((dep) => '${dep.uri}'), |
| 27 unorderedEquals(dependencies)); | 28 unorderedEquals(dependencies)); |
| 28 expect(library.parts.map((part) => '$part'), unorderedEquals(parts)); | 29 expect(library.parts.map((part) => '$part'), unorderedEquals(parts)); |
| 29 return library; | 30 return library; |
| 30 } | 31 } |
| 31 | 32 |
| 32 Future<List<LibraryCycleNode>> getCycles(Map<String, String> contents, | 33 Future<List<LibraryCycleNode>> getCycles(Map<String, String> contents, |
| 33 {List<String> startingPoints, String packagesFilePath = ''}) async { | 34 {List<String> startingPoints, String packagesFilePath = ''}) async { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 50 | 51 |
| 51 /// Sort the given library cycles into a deterministic order based on their | 52 /// Sort the given library cycles into a deterministic order based on their |
| 52 /// URIs for easier unit testing. | 53 /// URIs for easier unit testing. |
| 53 List<LibraryCycleNode> sortCycles(Iterable<LibraryCycleNode> cycles) { | 54 List<LibraryCycleNode> sortCycles(Iterable<LibraryCycleNode> cycles) { |
| 54 var result = cycles.toList(); | 55 var result = cycles.toList(); |
| 55 String sortKey(LibraryCycleNode node) => node.libraries.keys.join(','); | 56 String sortKey(LibraryCycleNode node) => node.libraries.keys.join(','); |
| 56 result.sort((a, b) => Comparable.compare(sortKey(a), sortKey(b))); | 57 result.sort((a, b) => Comparable.compare(sortKey(a), sortKey(b))); |
| 57 return result; | 58 return result; |
| 58 } | 59 } |
| 59 | 60 |
| 61 test_explicitCoreDependency() async { |
| 62 // If "dart:core" is explicitly imported, there shouldn't be two imports of |
| 63 // "dart:core", just one. |
| 64 var cycles = await getCycles({'/foo.dart': 'import "dart:core";'}); |
| 65 expect(cycles, hasLength(1)); |
| 66 expect(cycles[0].libraries, hasLength(1)); |
| 67 checkLibrary(cycles[0], 'file:///foo.dart'); |
| 68 } |
| 69 |
| 60 test_exportDependency() async { | 70 test_exportDependency() async { |
| 61 var cycles = | 71 var cycles = |
| 62 await getCycles({'/foo.dart': 'export "bar.dart";', '/bar.dart': ''}); | 72 await getCycles({'/foo.dart': 'export "bar.dart";', '/bar.dart': ''}); |
| 63 expect(cycles, hasLength(2)); | 73 expect(cycles, hasLength(2)); |
| 64 expect(cycles[0].libraries, hasLength(1)); | 74 expect(cycles[0].libraries, hasLength(1)); |
| 65 checkLibrary(cycles[0], 'file:///bar.dart'); | 75 checkLibrary(cycles[0], 'file:///bar.dart'); |
| 66 expect(cycles[1].libraries, hasLength(1)); | 76 expect(cycles[1].libraries, hasLength(1)); |
| 67 checkLibrary(cycles[1], 'file:///foo.dart', | 77 checkLibrary(cycles[1], 'file:///foo.dart', |
| 68 dependencies: ['file:///bar.dart']); | 78 dependencies: ['file:///bar.dart', 'dart:core']); |
| 69 } | 79 } |
| 70 | 80 |
| 71 test_importDependency() async { | 81 test_importDependency() async { |
| 72 var cycles = | 82 var cycles = |
| 73 await getCycles({'/foo.dart': 'import "bar.dart";', '/bar.dart': ''}); | 83 await getCycles({'/foo.dart': 'import "bar.dart";', '/bar.dart': ''}); |
| 74 expect(cycles, hasLength(2)); | 84 expect(cycles, hasLength(2)); |
| 75 expect(cycles[0].libraries, hasLength(1)); | 85 expect(cycles[0].libraries, hasLength(1)); |
| 76 checkLibrary(cycles[0], 'file:///bar.dart'); | 86 checkLibrary(cycles[0], 'file:///bar.dart'); |
| 77 expect(cycles[1].libraries, hasLength(1)); | 87 expect(cycles[1].libraries, hasLength(1)); |
| 78 checkLibrary(cycles[1], 'file:///foo.dart', | 88 checkLibrary(cycles[1], 'file:///foo.dart', |
| 79 dependencies: ['file:///bar.dart']); | 89 dependencies: ['file:///bar.dart', 'dart:core']); |
| 80 } | 90 } |
| 81 | 91 |
| 82 test_multipleStartingPoints() async { | 92 test_multipleStartingPoints() async { |
| 83 var cycles = await getCycles({ | 93 var cycles = await getCycles({ |
| 84 '/a.dart': 'import "c.dart";', | 94 '/a.dart': 'import "c.dart";', |
| 85 '/b.dart': 'import "c.dart";', | 95 '/b.dart': 'import "c.dart";', |
| 86 '/c.dart': '' | 96 '/c.dart': '' |
| 87 }, startingPoints: [ | 97 }, startingPoints: [ |
| 88 '/a.dart', | 98 '/a.dart', |
| 89 '/b.dart' | 99 '/b.dart' |
| 90 ]); | 100 ]); |
| 91 expect(cycles, hasLength(3)); | 101 expect(cycles, hasLength(3)); |
| 92 expect(cycles[0].libraries, hasLength(1)); | 102 expect(cycles[0].libraries, hasLength(1)); |
| 93 checkLibrary(cycles[0], 'file:///c.dart'); | 103 checkLibrary(cycles[0], 'file:///c.dart'); |
| 94 // The other two cycles might be in any order, so sort them for | 104 // The other two cycles might be in any order, so sort them for |
| 95 // reproducibility. | 105 // reproducibility. |
| 96 List<LibraryCycleNode> otherCycles = sortCycles(cycles.sublist(1)); | 106 List<LibraryCycleNode> otherCycles = sortCycles(cycles.sublist(1)); |
| 97 checkLibrary(otherCycles[0], 'file:///a.dart', | 107 checkLibrary(otherCycles[0], 'file:///a.dart', |
| 98 dependencies: ['file:///c.dart']); | 108 dependencies: ['file:///c.dart', 'dart:core']); |
| 99 checkLibrary(otherCycles[1], 'file:///b.dart', | 109 checkLibrary(otherCycles[1], 'file:///b.dart', |
| 100 dependencies: ['file:///c.dart']); | 110 dependencies: ['file:///c.dart', 'dart:core']); |
| 101 } | 111 } |
| 102 | 112 |
| 103 test_packages() async { | 113 test_packages() async { |
| 104 var cycles = await getCycles({ | 114 var cycles = await getCycles({ |
| 105 '/foo.dart': 'import "package:foo/bar.dart";', | 115 '/foo.dart': 'import "package:foo/bar.dart";', |
| 106 '/.packages': 'foo:pkg/foo/lib\nbar:pkg/bar/lib\n', | 116 '/.packages': 'foo:pkg/foo/lib\nbar:pkg/bar/lib\n', |
| 107 '/pkg/foo/lib/bar.dart': 'import "package:bar/baz.dart";', | 117 '/pkg/foo/lib/bar.dart': 'import "package:bar/baz.dart";', |
| 108 '/pkg/bar/lib/baz.dart': '' | 118 '/pkg/bar/lib/baz.dart': '' |
| 109 }, packagesFilePath: '/.packages'); | 119 }, packagesFilePath: '/.packages'); |
| 110 expect(cycles, hasLength(3)); | 120 expect(cycles, hasLength(3)); |
| 111 expect(cycles[0].libraries, hasLength(1)); | 121 expect(cycles[0].libraries, hasLength(1)); |
| 112 checkLibrary(cycles[0], 'package:bar/baz.dart'); | 122 checkLibrary(cycles[0], 'package:bar/baz.dart'); |
| 113 expect(cycles[1].libraries, hasLength(1)); | 123 expect(cycles[1].libraries, hasLength(1)); |
| 114 checkLibrary(cycles[1], 'package:foo/bar.dart', | 124 checkLibrary(cycles[1], 'package:foo/bar.dart', |
| 115 dependencies: ['package:bar/baz.dart']); | 125 dependencies: ['package:bar/baz.dart', 'dart:core']); |
| 116 expect(cycles[2].libraries, hasLength(1)); | 126 expect(cycles[2].libraries, hasLength(1)); |
| 117 checkLibrary(cycles[2], 'file:///foo.dart', | 127 checkLibrary(cycles[2], 'file:///foo.dart', |
| 118 dependencies: ['package:foo/bar.dart']); | 128 dependencies: ['package:foo/bar.dart', 'dart:core']); |
| 119 } | 129 } |
| 120 | 130 |
| 121 test_parts() async { | 131 test_parts() async { |
| 122 var cycles = await getCycles({ | 132 var cycles = await getCycles({ |
| 123 '/foo.dart': 'library foo; part "a.dart"; part "b.dart";', | 133 '/foo.dart': 'library foo; part "a.dart"; part "b.dart";', |
| 124 '/a.dart': 'part of foo;', | 134 '/a.dart': 'part of foo;', |
| 125 '/b.dart': 'part of foo;' | 135 '/b.dart': 'part of foo;' |
| 126 }); | 136 }); |
| 127 expect(cycles, hasLength(1)); | 137 expect(cycles, hasLength(1)); |
| 128 expect(cycles[0].libraries, hasLength(1)); | 138 expect(cycles[0].libraries, hasLength(1)); |
| 129 checkLibrary(cycles[0], 'file:///foo.dart', | 139 checkLibrary(cycles[0], 'file:///foo.dart', |
| 130 parts: ['file:///a.dart', 'file:///b.dart']); | 140 parts: ['file:///a.dart', 'file:///b.dart']); |
| 131 } | 141 } |
| 132 | 142 |
| 133 test_relativeUris() async { | 143 test_relativeUris() async { |
| 134 var cycles = await getCycles({ | 144 var cycles = await getCycles({ |
| 135 '/a.dart': 'import "b/c.dart";', | 145 '/a.dart': 'import "b/c.dart";', |
| 136 '/b/c.dart': 'import "d/e.dart";', | 146 '/b/c.dart': 'import "d/e.dart";', |
| 137 '/b/d/e.dart': 'import "../f.dart";', | 147 '/b/d/e.dart': 'import "../f.dart";', |
| 138 '/b/f.dart': '' | 148 '/b/f.dart': '' |
| 139 }); | 149 }); |
| 140 expect(cycles, hasLength(4)); | 150 expect(cycles, hasLength(4)); |
| 141 expect(cycles[0].libraries, hasLength(1)); | 151 expect(cycles[0].libraries, hasLength(1)); |
| 142 checkLibrary(cycles[0], 'file:///b/f.dart'); | 152 checkLibrary(cycles[0], 'file:///b/f.dart'); |
| 143 expect(cycles[1].libraries, hasLength(1)); | 153 expect(cycles[1].libraries, hasLength(1)); |
| 144 checkLibrary(cycles[1], 'file:///b/d/e.dart', | 154 checkLibrary(cycles[1], 'file:///b/d/e.dart', |
| 145 dependencies: ['file:///b/f.dart']); | 155 dependencies: ['file:///b/f.dart', 'dart:core']); |
| 146 expect(cycles[2].libraries, hasLength(1)); | 156 expect(cycles[2].libraries, hasLength(1)); |
| 147 checkLibrary(cycles[2], 'file:///b/c.dart', | 157 checkLibrary(cycles[2], 'file:///b/c.dart', |
| 148 dependencies: ['file:///b/d/e.dart']); | 158 dependencies: ['file:///b/d/e.dart', 'dart:core']); |
| 149 expect(cycles[3].libraries, hasLength(1)); | 159 expect(cycles[3].libraries, hasLength(1)); |
| 150 checkLibrary(cycles[3], 'file:///a.dart', | 160 checkLibrary(cycles[3], 'file:///a.dart', |
| 151 dependencies: ['file:///b/c.dart']); | 161 dependencies: ['file:///b/c.dart', 'dart:core']); |
| 162 } |
| 163 |
| 164 test_sdkDependency() async { |
| 165 // Dependencies on the SDK should be recorded even if SDK libraries aren't |
| 166 // being included in the graph. |
| 167 var cycles = await getCycles({'/foo.dart': 'import "dart:async";'}); |
| 168 expect(cycles, hasLength(1)); |
| 169 expect(cycles[0].libraries, hasLength(1)); |
| 170 checkLibrary(cycles[0], 'file:///foo.dart', |
| 171 dependencies: ['dart:core', 'dart:async']); |
| 152 } | 172 } |
| 153 | 173 |
| 154 test_simpleCycle() async { | 174 test_simpleCycle() async { |
| 155 var cycles = await getCycles( | 175 var cycles = await getCycles( |
| 156 {'/foo.dart': 'import "bar.dart";', '/bar.dart': 'import "foo.dart";'}); | 176 {'/foo.dart': 'import "bar.dart";', '/bar.dart': 'import "foo.dart";'}); |
| 157 expect(cycles, hasLength(1)); | 177 expect(cycles, hasLength(1)); |
| 158 expect(cycles[0].libraries, hasLength(2)); | 178 expect(cycles[0].libraries, hasLength(2)); |
| 159 var foo = checkLibrary(cycles[0], 'file:///foo.dart', | 179 var foo = checkLibrary(cycles[0], 'file:///foo.dart', |
| 160 dependencies: ['file:///bar.dart']); | 180 dependencies: ['file:///bar.dart', 'dart:core']); |
| 161 var bar = checkLibrary(cycles[0], 'file:///bar.dart', | 181 var bar = checkLibrary(cycles[0], 'file:///bar.dart', |
| 162 dependencies: ['file:///foo.dart']); | 182 dependencies: ['file:///foo.dart', 'dart:core']); |
| 163 expect(foo.dependencies[0], same(bar)); | 183 expect(foo.dependencies[0], same(bar)); |
| 164 expect(bar.dependencies[0], same(foo)); | 184 expect(bar.dependencies[0], same(foo)); |
| 165 } | 185 } |
| 166 | 186 |
| 167 test_singleFile() async { | 187 test_singleFile() async { |
| 168 var cycles = await getCycles({'/foo.dart': ''}); | 188 var cycles = await getCycles({'/foo.dart': ''}); |
| 169 expect(cycles, hasLength(1)); | 189 expect(cycles, hasLength(1)); |
| 170 expect(cycles[0].libraries, hasLength(1)); | 190 expect(cycles[0].libraries, hasLength(1)); |
| 171 checkLibrary(cycles[0], 'file:///foo.dart'); | 191 checkLibrary(cycles[0], 'file:///foo.dart'); |
| 172 } | 192 } |
| 173 } | 193 } |
| OLD | NEW |