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

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

Powered by Google App Engine
This is Rietveld 408576698