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

Unified Diff: pkg/front_end/test/dependency_grapher_test.dart

Issue 2575403005: Implement a front end API for querying the dependency structure of a project. (Closed)
Patch Set: Created 4 years 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 side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/test/dependency_grapher_test.dart
diff --git a/pkg/front_end/test/dependency_grapher_test.dart b/pkg/front_end/test/dependency_grapher_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cf348bd26ffa50fa96d5f1e0f9f22dfa34edded2
--- /dev/null
+++ b/pkg/front_end/test/dependency_grapher_test.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:front_end/compiler_options.dart';
+import 'package:front_end/dependency_grapher.dart';
+import 'package:front_end/memory_file_system.dart';
+import 'package:path/path.dart' as pathos;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DependencyGrapherTest);
+ });
+}
+
+@reflectiveTest
+class DependencyGrapherTest {
+ LibraryNode checkLibrary(LibraryCycleNode cycle, String uri,
+ {List<String> dependencies: const [], List<String> parts: const []}) {
+ var library = cycle.libraries[Uri.parse(uri)];
+ 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.
+ expect(library.dependencies.map((dep) => dep.uri.toString()).toList(),
+ unorderedEquals(dependencies));
+ expect(
+ 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.
+ return library;
+ }
+
+ Future<List<LibraryCycleNode>> getCycles(Map<String, String> contents,
+ [List<String> startingPoints]) async {
+ // If no starting points given, assume the first entry in [contents] is the
+ // single starting point.
+ startingPoints ??= [contents.keys.first];
+ var fileSystem = new MemoryFileSystem(pathos.posix, '/');
+ contents.forEach((path, text) {
+ fileSystem.entityForPath(path).writeAsStringSync(text);
+ });
+ // TODO(paulberry): implement and test other option possibilities.
+ var options = new CompilerOptions()
+ ..fileSystem = fileSystem
+ ..chaseDependencies = true;
+ var graph = await graphForProgram(
+ startingPoints.map(pathos.posix.toUri).toList(), options);
+ return graph.topologicallySortedCycles;
+ }
+
+ /// Sort the given library cycles into a deterministic order based on their
+ /// URIs for easier unit testing.
+ List<LibraryCycleNode> sortCycles(Iterable<LibraryCycleNode> cycles) {
+ var result = cycles.toList();
+ String sortKey(LibraryCycleNode node) => node.libraries.keys.join(',');
+ result.sort((a, b) => Comparable.compare(sortKey(a), sortKey(b)));
+ return result;
+ }
+
+ test_exportDependency() async {
+ var cycles =
+ await getCycles({'/foo.dart': 'export "bar.dart";', '/bar.dart': ''});
+ expect(cycles, hasLength(2));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///bar.dart');
+ expect(cycles[1].libraries, hasLength(1));
+ checkLibrary(cycles[1], 'file:///foo.dart',
+ dependencies: ['file:///bar.dart']);
+ }
+
+ test_importDependency() async {
+ var cycles =
+ await getCycles({'/foo.dart': 'import "bar.dart";', '/bar.dart': ''});
+ expect(cycles, hasLength(2));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///bar.dart');
+ expect(cycles[1].libraries, hasLength(1));
+ checkLibrary(cycles[1], 'file:///foo.dart',
+ dependencies: ['file:///bar.dart']);
+ }
+
+ test_multipleStartingPoints() async {
+ var cycles = await getCycles({
+ '/a.dart': 'import "c.dart";',
+ '/b.dart': 'import "c.dart";',
+ '/c.dart': ''
+ }, [
+ '/a.dart',
+ '/b.dart'
+ ]);
+ expect(cycles, hasLength(3));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///c.dart');
+ // The other two cycles might be in any order, so sort them for
+ // reproducibility.
+ List<LibraryCycleNode> otherCycles = sortCycles(cycles.sublist(1));
+ checkLibrary(otherCycles[0], 'file:///a.dart',
+ dependencies: ['file:///c.dart']);
+ checkLibrary(otherCycles[1], 'file:///b.dart',
+ dependencies: ['file:///c.dart']);
+ }
+
+ test_parts() async {
+ var cycles = await getCycles({
+ '/foo.dart': 'library foo; part "a.dart"; part "b.dart";',
+ '/a.dart': 'part of foo;',
+ '/b.dart': 'part of foo;'
+ });
+ expect(cycles, hasLength(1));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///foo.dart',
+ parts: ['file:///a.dart', 'file:///b.dart']);
+ }
+
+ test_relativeUris() async {
+ var cycles = await getCycles({
+ '/a.dart': 'import "b/c.dart";',
+ '/b/c.dart': 'import "d/e.dart";',
+ '/b/d/e.dart': 'import "../f.dart";',
+ '/b/f.dart': ''
+ });
+ expect(cycles, hasLength(4));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///b/f.dart');
+ expect(cycles[1].libraries, hasLength(1));
+ checkLibrary(cycles[1], 'file:///b/d/e.dart',
+ dependencies: ['file:///b/f.dart']);
+ expect(cycles[2].libraries, hasLength(1));
+ checkLibrary(cycles[2], 'file:///b/c.dart',
+ dependencies: ['file:///b/d/e.dart']);
+ expect(cycles[3].libraries, hasLength(1));
+ checkLibrary(cycles[3], 'file:///a.dart',
+ dependencies: ['file:///b/c.dart']);
+ }
+
+ test_simpleCycle() async {
+ var cycles = await getCycles(
+ {'/foo.dart': 'import "bar.dart";', '/bar.dart': 'import "foo.dart";'});
+ expect(cycles, hasLength(1));
+ expect(cycles[0].libraries, hasLength(2));
+ var foo = checkLibrary(cycles[0], 'file:///foo.dart',
+ dependencies: ['file:///bar.dart']);
+ var bar = checkLibrary(cycles[0], 'file:///bar.dart',
+ dependencies: ['file:///foo.dart']);
+ expect(foo.dependencies[0], same(bar));
+ expect(bar.dependencies[0], same(foo));
+ }
+
+ test_singleFile() async {
+ var cycles = await getCycles({'/foo.dart': ''});
+ expect(cycles, hasLength(1));
+ expect(cycles[0].libraries, hasLength(1));
+ checkLibrary(cycles[0], 'file:///foo.dart');
+ }
+}
« pkg/front_end/lib/dependency_grapher.dart ('K') | « pkg/front_end/lib/dependency_grapher.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698