Skip to content

Commit fbe4c75

Browse files
committed
add some PackageGraph unit tests
1 parent b056fb9 commit fbe4c75

File tree

10 files changed

+142
-22
lines changed

10 files changed

+142
-22
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ build/
44
.pub/
55
pubspec.lock
66

7-
generated
7+
# Include .packages files from tests which are hand coded
8+
!test/package_graph/**/.packages

lib/src/package_graph/package_graph.dart

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44
import 'dart:io';
55

6+
import 'package:path/path.dart' as path;
67
import 'package:yaml/yaml.dart';
78

89
/// A graph of the package dependencies for an application.
@@ -16,19 +17,19 @@ class PackageGraph {
1617
PackageGraph._(this.root, Map<String, PackageNode> allPackages)
1718
: allPackages = new Map.unmodifiable(allPackages);
1819

19-
/// Creates a [PackageGraph] for the package in which you are currently
20-
/// running.
21-
factory PackageGraph.forThisPackage() {
20+
/// Creates a [PackageGraph] for the package whose top level directory lives
21+
/// at [packagePath] (no trailing slash).
22+
factory PackageGraph.forPath(String packagePath) {
2223
/// Read in the pubspec file and parse it as yaml.
23-
var pubspec = new File('pubspec.yaml');
24+
var pubspec = new File(path.join(packagePath, 'pubspec.yaml'));
2425
if (!pubspec.existsSync()) {
2526
throw 'Unable to generate package graph, no `pubspec.yaml` found. '
2627
'This program must be ran from the root directory of your package.';
2728
}
28-
var yaml = loadYaml(pubspec.readAsStringSync());
29+
var rootYaml = loadYaml(pubspec.readAsStringSync());
2930

3031
/// Read in the `.packages` file to get the locations of all packages.
31-
var packagesFile = new File('.packages');
32+
var packagesFile = new File(path.join(packagePath, '.packages'));
3233
if (!packagesFile.existsSync()) {
3334
throw 'Unable to generate package graph, no `.packages` found. '
3435
'This program must be ran from the root directory of your package.';
@@ -37,18 +38,26 @@ class PackageGraph {
3738
packagesFile.readAsLinesSync().skip(1).forEach((line) {
3839
var firstColon = line.indexOf(':');
3940
var name = line.substring(0, firstColon);
40-
var uriString = line.substring(firstColon + 1);
41+
assert(line.endsWith('lib${Platform.pathSeparator}'));
42+
// Start after package_name:, and strip out trailing `lib` dir.
43+
var uriString = line.substring(firstColon + 1, line.length - 4);
44+
var uri;
4145
try {
42-
packageLocations[name] = Uri.parse(uriString);
46+
uri = Uri.parse(uriString);
4347
} on FormatException catch (_) {
4448
/// Some types of deps don't have a scheme, and just point to a relative
4549
/// path.
46-
packageLocations[name] = new Uri.file(uriString);
50+
uri = new Uri.file(uriString);
4751
}
52+
if (!uri.isAbsolute) {
53+
uri = new Uri.file(path.join(packagePath, uri.path));
54+
}
55+
packageLocations[name] = uri;
4856
});
4957

5058
/// Create all [PackageNode]s for all deps.
5159
var nodes = <String, PackageNode>{};
60+
Map<String, dynamic> rootDeps;
5261
PackageNode addNodeAndDeps(YamlMap yaml, PackageDependencyType type,
5362
{bool isRoot: false}) {
5463
var name = yaml['name'];
@@ -57,24 +66,31 @@ class PackageGraph {
5766
name, yaml['version'], type, packageLocations[name]);
5867
nodes[name] = node;
5968

60-
_depsFromYaml(yaml, withOverrides: isRoot).forEach((name, source) {
69+
var deps = _depsFromYaml(yaml, withOverrides: isRoot);
70+
if (isRoot) rootDeps = deps;
71+
deps.forEach((name, source) {
6172
var dep = nodes[name];
6273
if (dep == null) {
6374
var pubspec = _pubspecForUri(packageLocations[name]);
64-
dep = addNodeAndDeps(pubspec, _dependencyType(source));
75+
dep = addNodeAndDeps(pubspec, _dependencyType(rootDeps[name]));
6576
}
6677
node._dependencies.add(dep);
6778
});
6879

6980
return node;
7081
}
7182

72-
var root = addNodeAndDeps(yaml, PackageDependencyType.Path, isRoot: true);
83+
var root =
84+
addNodeAndDeps(rootYaml, PackageDependencyType.Path, isRoot: true);
7385
return new PackageGraph._(root, nodes);
7486
}
7587

88+
/// Creates a [PackageGraph] for the package in which you are currently
89+
/// running.
90+
factory PackageGraph.forThisPackage() => new PackageGraph.forPath('.');
91+
7692
/// Shorthand to get a package by name.
77-
PackageNode operator[] (String packageName) => allPackages[packageName];
93+
PackageNode operator [](String packageName) => allPackages[packageName];
7894

7995
String toString() {
8096
var buffer = new StringBuffer();
@@ -118,7 +134,7 @@ class PackageNode {
118134
enum PackageDependencyType { Pub, Github, Path, }
119135

120136
PackageDependencyType _dependencyType(source) {
121-
if (source is String) return PackageDependencyType.Pub;
137+
if (source is String || source == null) return PackageDependencyType.Pub;
122138

123139
assert(source is YamlMap);
124140
assert(source.keys.length == 1);
@@ -145,14 +161,9 @@ Map<String, YamlMap> _depsFromYaml(YamlMap yaml, {bool withOverrides: false}) {
145161
return deps;
146162
}
147163

148-
/// [uri] should be directly from a `.packages` file, and points to the `lib`
149-
/// dir.
164+
/// [uri] should point to the top level directory for the package.
150165
YamlMap _pubspecForUri(Uri uri) {
151-
var libPath = uri.toFilePath();
152-
assert(libPath.endsWith('lib/'));
153-
var pubspecPath =
154-
libPath.replaceRange(libPath.length - 4, libPath.length, 'pubspec.yaml');
155-
166+
var pubspecPath = path.join(uri.toFilePath(), 'pubspec.yaml');
156167
var pubspec = new File(pubspecPath);
157168
if (!pubspec.existsSync()) {
158169
throw 'Unable to generate package graph, no `$pubspecPath` found.';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Generated by hand on 2016-02-01
2+
a:pkg/a/lib/
3+
b:pkg/b/lib/
4+
c:pkg/c/lib/
5+
d:pkg/d/lib/
6+
basic_pkg:lib/
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: a
2+
version: 2.0.0
3+
dependencies:
4+
b: ^3.0.0
5+
c: any
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name: b
2+
version: 3.0.0
3+
dependencies:
4+
c: ^0.4.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name: c
2+
version: 4.0.0
3+
dependencies:
4+
basic_pkg: ^1.0.0
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: basic_pkg
2+
version: 1.0.0
3+
dependencies:
4+
a: 2.0.0
5+
b:
6+
git: git://github.com/b/b.git
7+
c:
8+
path: pkg/c
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name: a
2+
version: 1.0.0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Created by hand, but empty
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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+
@TestOn('vm')
5+
import 'package:test/test.dart';
6+
7+
import 'package:build/build.dart';
8+
9+
main() async {
10+
PackageGraph graph;
11+
12+
group('forThisPackage ', () {
13+
setUp(() async {
14+
graph = await new PackageGraph.forThisPackage();
15+
});
16+
17+
test('root', () {
18+
expectPkg(
19+
graph.root, 'build', isNotEmpty, PackageDependencyType.Path, './');
20+
});
21+
});
22+
23+
group('basic package ', () {
24+
var basicPkgPath = 'test/package_graph/basic_pkg';
25+
26+
setUp(() async {
27+
graph = await new PackageGraph.forPath(basicPkgPath);
28+
});
29+
30+
test('allPackages', () {
31+
expect(graph.allPackages, {
32+
'a': graph['a'],
33+
'b': graph['b'],
34+
'c': graph['c'],
35+
'basic_pkg': graph['basic_pkg'],
36+
});
37+
});
38+
39+
test('root', () {
40+
expectPkg(graph.root, 'basic_pkg', '1.0.0', PackageDependencyType.Path,
41+
basicPkgPath, [graph['a'], graph['b'], graph['c']]);
42+
});
43+
44+
test('pub dependency', () {
45+
expectPkg(graph['a'], 'a', '2.0.0', PackageDependencyType.Pub,
46+
'$basicPkgPath/pkg/a/', [graph['b'], graph['c']]);
47+
});
48+
49+
test('git dependency', () {
50+
expectPkg(graph['b'], 'b', '3.0.0', PackageDependencyType.Github,
51+
'$basicPkgPath/pkg/b/', [graph['c']]);
52+
});
53+
54+
test('path dependency', () {
55+
expectPkg(graph['c'], 'c', '4.0.0', PackageDependencyType.Path,
56+
'$basicPkgPath/pkg/c/', [graph['basic_pkg']]);
57+
});
58+
});
59+
60+
test('missing pubspec throws on create', () {
61+
expect(() => new PackageGraph.forPath('no_pubspec'), throws);
62+
});
63+
64+
test('missing .packages file throws on create', () {
65+
expect(() => new PackageGraph.forPath('no_packages_file'), throws);
66+
});
67+
}
68+
69+
void expectPkg(PackageNode node, name, version, type, location,
70+
[Iterable<PackageNode> dependencies]) {
71+
expect(node.name, name);
72+
expect(node.version, version);
73+
expect(node.dependencyType, type);
74+
expect(node.location.path, location);
75+
if (dependencies != null) {
76+
expect(node.dependencies, unorderedEquals(dependencies));
77+
}
78+
}

0 commit comments

Comments
 (0)