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

Side by Side Diff: pkg/barback/test/utils.dart

Issue 16854005: First pass at build dependency graph for barback. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Handle unprovided sources and errors a bit better. Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « pkg/barback/test/asset_id_test.dart ('k') | pkg/pathos/lib/path.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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 library barback.test.utils;
6
7 import 'dart:async';
8
9 import 'package:barback/barback.dart';
10 import 'package:barback/src/asset_graph.dart';
11 import 'package:pathos/path.dart' as pathos;
12 import 'package:scheduled_test/scheduled_test.dart';
13
14 // TODO(rnystrom): Get rid of this or find a better path for it.
15 import '../../../sdk/lib/_internal/pub/test/command_line_config.dart';
16
17 var _configured = false;
18
19 void initConfig() {
20 if (_configured) return;
21 _configured = true;
22 unittestConfiguration = new CommandLineConfiguration();
23 }
24
25 /// Expects that [graph] will return an asset matching [name] and [contents].
26 void expectAsset(AssetGraph graph, String name, [String contents]) {
27 var id = new AssetId.parse(name);
28
29 if (contents == null) {
30 contents = pathos.basenameWithoutExtension(id.path);
31 }
32
33 schedule(() {
34 return graph.getAssetById(id).then((asset) {
35 // TODO(rnystrom): Make an actual Matcher class for this.
36 expect(asset, new isInstanceOf<MockAsset>());
37 expect(asset._id.package, equals(id.package));
38 expect(asset._id.path, equals(id.path));
39 expect(asset._contents, equals(contents));
40 });
41 }, "get asset $name");
42 }
43
44 /// Expects that [graph] will not find an asset matching [name].
45 void expectNoAsset(AssetGraph graph, String name) {
46 var id = new AssetId.parse(name);
47
48 // Make sure the future gets the error.
49 schedule(() {
50 return graph.getAssetById(id).then((asset) {
51 fail("Should have thrown error but got $asset.");
52 }).catchError((error) {
53 expect(error, new isInstanceOf<AssetNotFoundException>());
54 expect(error.id, equals(id));
55 });
56 }, "get asset $name");
57 }
58
59 /// Expects that [graph] will have an output file collision error on an asset
60 /// matching [name].
61 Future expectCollision(AssetGraph graph, String name) {
62 var id = new AssetId.parse(name);
63 return schedule(() {
64 return graph.results.first.then((result) {
65 expect(result.error, new isInstanceOf<AssetCollisionException>());
66 expect(result.error.id, equals(id));
67 });
68 }, "get collision on $name");
69 }
70
71 /// Expects that [graph] will have an error on an asset matching [name] for
72 /// missing [input].
73 Future expectMissingInput(AssetGraph graph, String name, String input) {
74 var missing = new AssetId.parse(input);
75
76 // Make sure the future gets the error.
77 schedule(() {
78 return graph.getAssetById(new AssetId.parse(name)).then((asset) {
79 fail("Should have thrown error but got $asset.");
80 }).catchError((error) {
81 expect(error, new isInstanceOf<MissingInputException>());
82 expect(error.id, equals(missing));
83 });
84 }, "get missing input on $name");
85 }
86
87 /// An [AssetProvider] that provides the given set of assets.
88 class MockProvider implements AssetProvider {
89 Iterable<String> get packages => _packages.keys;
90
91 final _packages = new Map<String, List<MockAsset>>();
92
93 /// The completer that [getAsset()] is waiting on to complete.
94 ///
95 /// If `null` it will return the asset immediately.
96 Completer _wait;
97
98 /// Tells the provider to wait during [getAsset] until [complete()]
99 /// is called.
100 ///
101 /// Lets you test the asynchronous behavior of loading.
102 void wait() {
103 _wait = new Completer();
104 }
105
106 void complete() {
107 _wait.complete();
108 _wait = null;
109 }
110
111 MockProvider(assets) {
112 if (assets is Map) {
113 assets.forEach((asset, contents) {
114 var id = new AssetId.parse(asset);
115 var package = _packages.putIfAbsent(id.package, () => []);
116 package.add(new MockAsset(id, contents));
117 });
118 } else if (assets is Iterable) {
119 for (var asset in assets) {
120 var id = new AssetId.parse(asset);
121 var package = _packages.putIfAbsent(id.package, () => []);
122 var contents = pathos.basenameWithoutExtension(id.path);
123 package.add(new MockAsset(id, contents));
124 }
125 }
126 }
127
128 void modifyAsset(String name, String contents) {
129 var id = new AssetId.parse(name);
130 var asset = _packages[id.package].firstWhere((a) => a._id == id);
131 asset._contents = contents;
132 }
133
134 List<AssetId> listAssets(String package, {String within}) {
135 if (within != null) {
136 throw new UnimplementedError("Doesn't handle 'within' yet.");
137 }
138
139 return _packages[package].map((asset) => asset.id);
140 }
141
142 Future<Asset> getAsset(AssetId id) {
143 var future;
144 if (_wait != null) {
145 future = _wait.future;
146 } else {
147 future = new Future.value();
148 }
149
150 return future.then((_) {
151 var package = _packages[id.package];
152 if (package == null) throw new AssetNotFoundException(id);
153
154 return package.firstWhere((asset) => asset._id == id,
155 orElse: () => throw new AssetNotFoundException(id));
156 });
157 }
158 }
159
160 /// A [Transformer] that takes assets ending with one extension and generates
161 /// assets with a given extension.
162 ///
163 /// Appends the output extension to the contents of the input file.
164 class RewriteTransformer extends Transformer {
165 final String from;
166 final String to;
167
168 /// The number of times the transformer has been applied.
169 int numRuns = 0;
170
171 /// The number of currently running transforms.
172 int _runningTransforms = 0;
173
174 /// The completer that the transform is waiting on to complete.
175 ///
176 /// If `null` the transform will complete immediately.
177 Completer _wait;
178
179 /// A future that completes when the first apply of this transformer begins.
180 Future get started => _started.future;
181 final _started = new Completer();
182
183 /// Creates a transformer that rewrites assets whose extension is [from] to
184 /// one whose extension is [to].
185 ///
186 /// [to] may be a space-separated list in which case multiple outputs will be
187 /// created for each input.
188 RewriteTransformer(this.from, this.to);
189
190 /// `true` if any transforms are currently running.
191 bool get isRunning => _runningTransforms > 0;
192
193 /// Tells the transform to wait during its transformation until [complete()]
194 /// is called.
195 ///
196 /// Lets you test the asynchronous behavior of transformers.
197 void wait() {
198 _wait = new Completer();
199 }
200
201 void complete() {
202 _wait.complete();
203 _wait = null;
204 }
205
206 Future<bool> isPrimary(AssetId asset) {
207 return new Future.value(asset.extension == ".$from");
208 }
209
210 Future apply(Transform transform) {
211 numRuns++;
212 if (!_started.isCompleted) _started.complete();
213 _runningTransforms++;
214 return transform.primaryInput.then((input) {
215 for (var extension in to.split(" ")) {
216 var id = transform.primaryId.changeExtension(".$extension");
217 var content = input.readAsString() + ".$extension";
218 transform.addOutput(id, new MockAsset(id, content));
219
220 }
221
222 if (_wait != null) return _wait.future;
223 }).whenComplete(() {
224 _runningTransforms--;
225 });
226 }
227
228 String toString() => "$from->$to";
229 }
230
231 /// A [Transformer] that takes an input asset that contains a comma-separated
232 /// list of paths and outputs a file for each path.
233 class OneToManyTransformer extends Transformer {
234 final String extension;
235
236 /// The number of times the transformer has been applied.
237 int numRuns = 0;
238
239 /// Creates a transformer that consumes assets with [extension].
240 ///
241 /// That file contains a comma-separated list of paths and it will output
242 /// files at each of those paths.
243 OneToManyTransformer(this.extension);
244
245 Future<bool> isPrimary(AssetId asset) {
246 return new Future.value(asset.extension == ".$extension");
247 }
248
249 Future apply(Transform transform) {
250 numRuns++;
251 return transform.primaryInput.then((input) {
252 for (var line in input.readAsString().split(",")) {
253 var id = new AssetId(transform.primaryId.package, line);
254 transform.addOutput(id, new MockAsset(id, "spread $extension"));
255 }
256 });
257 }
258
259 String toString() => "1->many $extension";
260 }
261
262 /// A transformer that uses the contents of a file to define the other inputs.
263 ///
264 /// Outputs a file with the same name as the primary but with an "out"
265 /// extension containing the concatenated contents of all non-primary inputs.
266 class ManyToOneTransformer extends Transformer {
267 final String extension;
268
269 /// The number of times the transformer has been applied.
270 int numRuns = 0;
271
272 /// Creates a transformer that consumes assets with [extension].
273 ///
274 /// That file contains a comma-separated list of paths and it will input
275 /// files at each of those paths.
276 ManyToOneTransformer(this.extension);
277
278 Future<bool> isPrimary(AssetId asset) {
279 return new Future.value(asset.extension == ".$extension");
280 }
281
282 Future apply(Transform transform) {
283 numRuns++;
284 return transform.primaryInput.then((primary) {
285 // Get all of the included inputs.
286 var inputs = primary.readAsString().split(",").map((path) {
287 var id = new AssetId(transform.primaryId.package, path);
288 return transform.getInput(id);
289 });
290
291 // Concatenate them to one output.
292 return Future.wait(inputs).then((inputs) {
293 var id = transform.primaryId.changeExtension(".out");
294 var contents = inputs.map((input) => input.readAsString()).join();
295 transform.addOutput(id, new MockAsset(id, contents));
296 });
297 });
298 }
299
300 String toString() => "many->1 $extension";
301 }
302
303 /// A transformer that throws an exception when run, after generating the
304 /// given outputs.
305 class BadTransformer extends Transformer {
306 /// The error it throws.
307 static const ERROR = "I am a bad transformer!";
308
309 /// The list of asset names that it should output.
310 final List<String> outputs;
311
312 BadTransformer(this.outputs);
313
314 Future<bool> isPrimary(AssetId asset) => new Future.value(true);
315 Future apply(Transform transform) {
316 return new Future(() {
317 // Create the outputs first.
318 for (var output in outputs) {
319 var id = new AssetId.parse(output);
320 transform.addOutput(id, new MockAsset(id, output));
321 }
322
323 // Then fail.
324 throw ERROR;
325 });
326 }
327 }
328
329 /// An implementation of [Asset] that never hits the file system.
330 class MockAsset implements Asset {
331 final AssetId _id;
332 String _contents;
333
334 MockAsset(this._id, this._contents);
335
336 String readAsString() => _contents;
337 Stream<List<int>> read() => throw new UnimplementedError();
338
339 serialize() => throw new UnimplementedError();
340
341 String toString() => "MockAsset $_id $_contents";
342 }
OLDNEW
« no previous file with comments | « pkg/barback/test/asset_id_test.dart ('k') | pkg/pathos/lib/path.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698