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

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

Issue 17507003: Clean up barback tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Revise. Created 7 years, 5 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_graph/transform_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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 library barback.test.utils; 5 library barback.test.utils;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection';
8 9
9 import 'package:barback/barback.dart'; 10 import 'package:barback/barback.dart';
10 import 'package:barback/src/asset_graph.dart'; 11 import 'package:barback/src/asset_graph.dart';
11 import 'package:pathos/path.dart' as pathos; 12 import 'package:pathos/path.dart' as pathos;
12 import 'package:scheduled_test/scheduled_test.dart'; 13 import 'package:scheduled_test/scheduled_test.dart';
13 14
14 // TODO(rnystrom): Get rid of this or find a better path for it. 15 // 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 import '../../../sdk/lib/_internal/pub/test/command_line_config.dart';
16 17
17 var _configured = false; 18 var _configured = false;
18 19
20 MockProvider _provider;
21 AssetGraph _graph;
22
23 /// [BuildResult]s that have been output by the graph before an expectation has
24 /// consumed them.
25 ///
26 /// Since [AssetGraph] starts building immediately in the background, results
27 /// may start streaming before we've set an explicit expectation. When that
28 /// occurs, we just queue them up here.
29 final _buildResults = new Queue<BuildResult>();
30
31 /// The expectations we have on upcoming [BuildResult]s.
32 final _buildExpectations = new Queue<Completer<BuildResult>>();
33
19 void initConfig() { 34 void initConfig() {
20 if (_configured) return; 35 if (_configured) return;
21 _configured = true; 36 _configured = true;
22 unittestConfiguration = new CommandLineConfiguration(); 37 unittestConfiguration = new CommandLineConfiguration();
23 } 38 }
24 39
25 /// Expects that [graph] will return an asset matching [name] and [contents]. 40 /// Creates a new [AssetProvider] and [AssetGraph] with the given [assets] and
26 void expectAsset(AssetGraph graph, String name, [String contents]) { 41 /// [transformers].
42 ///
43 /// This graph is used internally by most of the other functions in this
44 /// library so you must call it in the test before calling any of the other
45 /// functions. These other functions are automatically scheduled, with the
nweiz 2013/06/27 00:19:25 "These other functions" is unclear, especially sin
Bob Nystrom 2013/06/27 17:55:14 Done.
46 /// exception of [updateSources] and [removeSources].
47 ///
48 /// [assets] may either be an [Iterable] or a [Map]. If an [Iterable], each
nweiz 2013/06/27 00:19:25 "If an" -> "If it's an"
Bob Nystrom 2013/06/27 17:55:14 Done.
49 /// element may either be an [AssetId] or a string that can be parsed to one.
50 /// If it's a [Map], each key should be a string that can be parsed to an
51 /// [AssetId] and the value is a string defining the contents of that asset.
nweiz 2013/06/27 00:19:25 "value is" -> "value should be"
Bob Nystrom 2013/06/27 17:55:14 Done.
52 void initGraph([assets, Iterable<Iterable<Transformer>> transformers]) {
53 if (assets == null) assets = [];
54 if (transformers == null) transformers = [];
55
56 _provider = new MockProvider(assets);
57 _graph = new AssetGraph(_provider, transformers);
58
59 _graph.results.listen(wrapAsync((result) {
60 if (_buildExpectations.isEmpty) {
61 // We aren't waiting for a result yet, so just queue it up for later.
62 _buildResults.add(result);
63 } else {
64 // See if it meets the expectation.
65 _buildExpectations.removeFirst().complete(result);
66 }
67 }));
68
69 currentSchedule.onComplete.schedule(() {
70 // Discard any unused results. It's OK for a test to not care about some
71 // build results.
72 _buildResults.clear();
73 }, "clear unused build results");
74
75 // This library should ensure that you can't move to the next test until all
76 // build expectations are processed.
77 assert(_buildExpectations.isEmpty);
78 }
79
80 /// Updates [assets] in the current [AssetProvider].
81 ///
82 /// Each item in the list may either be an [AssetId] or a string that can be
83 /// parsed as one. Note that this method is not automatically scheduled, so you
84 /// will typically wrap it in a call to [schedule] yourself.
nweiz 2013/06/27 00:19:25 "you will typically wrap it" is confusing. Most of
Bob Nystrom 2013/06/27 17:55:14 Done.
85 ///
86 void updateSources(Iterable assets) {
87 // Allow strings as asset IDs.
88 assets = assets.map((asset) {
89 if (asset is String) return new AssetId.parse(asset);
90 return asset;
91 });
92
93 _graph.updateSources(assets);
94 }
95
96 /// Removes [assets] from the current [AssetProvider].
97 ///
98 /// Each item in the list may either be an [AssetId] or a string that can be
99 /// parsed as one. Note that this method is not automatically scheduled, so you
100 /// will typically wrap it in a call to [schedule] yourself.
101 void removeSources(Iterable assets) {
102 // Allow strings as asset IDs.
103 assets = assets.map((asset) {
104 if (asset is String) return new AssetId.parse(asset);
105 return asset;
106 });
107
108 _graph.removeSources(assets);
109 }
110
111 /// Changes the contents of an asset identified by [name] to [contents].
112 ///
113 /// Does not update it in the graph.
114 void modifyAsset(String name, String contents) {
115 schedule(() {
116 _provider._modifyAsset(name, contents);
117 }, "modify asset $name");
118 }
119
120 /// Pauses the internally created [AssetProvider]. All asset requests that the
nweiz 2013/06/27 00:19:25 Paragraph break
Bob Nystrom 2013/06/27 17:55:14 Done.
121 /// [AssetGraph] makes to the provider after this will not complete until
122 /// [resumeProvider] is called.
123 void pauseProvider() {
124 schedule(() =>_provider._pause(), "resume provider");
nweiz 2013/06/27 00:19:25 "resume" -> "pause"
Bob Nystrom 2013/06/27 17:55:14 Done.
125 }
126
127 /// Unpauses the provider after a call to [pauseProvider] and allows all
128 /// pending asset loads to finish.
129 void resumeProvider() {
130 schedule(() => _provider._resume(), "pause provider");
nweiz 2013/06/27 00:19:25 "pause" -> "resume"
Bob Nystrom 2013/06/27 17:55:14 Done.
131 }
132
133 /// Waits for the next [BuildResult] to be emitted and asserts that it is a
134 /// build success.
135 void buildShouldSucceed() {
136 schedule(() {
137 return _getNextBuildResult().then((result) {
138 expect(result.succeeded, isTrue);
139 });
140 }, "wait for build to succeed");
141 }
142
143 /// Waits for the next [BuildResult] to be emitted and asserts that it is a
144 /// build failure. Invokes [callback] with the error (not the result) so that
145 /// it can provide more precise expectations.
146 void buildShouldFail(void callback(error)) {
147 schedule(() {
148 return _getNextBuildResult().then((result) {
149 expect(result.succeeded, isFalse);
150 callback(result.error);
151 });
152 }, "wait for build error");
153 }
154
155 Future<BuildResult> _getNextBuildResult() {
156 if (_buildResults.isNotEmpty) {
157 return new Future.value(_buildResults.removeFirst());
158 }
159
160 // We don't have any results yet, so enqueue the expectation.
161 var completer = new Completer<BuildResult>();
162 _buildExpectations.add(completer);
163 return completer.future;
164 }
165
166 /// Expects that the graph will deliver an asset matching [name] and [contents].
167 ///
168 /// If [contents] is omitted, defaults to the asset's filename without an
169 /// extension (which is the same default that [initGraph] uses).
170 void expectAsset(String name, [String contents]) {
27 var id = new AssetId.parse(name); 171 var id = new AssetId.parse(name);
28 172
29 if (contents == null) { 173 if (contents == null) {
30 contents = pathos.basenameWithoutExtension(id.path); 174 contents = pathos.basenameWithoutExtension(id.path);
31 } 175 }
32 176
33 schedule(() { 177 schedule(() {
34 return graph.getAssetById(id).then((asset) { 178 return _graph.getAssetById(id).then((asset) {
35 // TODO(rnystrom): Make an actual Matcher class for this. 179 // TODO(rnystrom): Make an actual Matcher class for this.
36 expect(asset, new isInstanceOf<MockAsset>()); 180 expect(asset, new isInstanceOf<MockAsset>());
37 expect(asset._id.package, equals(id.package)); 181 expect(asset._id.package, equals(id.package));
38 expect(asset._id.path, equals(id.path)); 182 expect(asset._id.path, equals(id.path));
39 expect(asset._contents, equals(contents)); 183 expect(asset._contents, equals(contents));
40 }); 184 });
41 }, "get asset $name"); 185 }, "get asset $name");
42 } 186 }
43 187
44 /// Expects that [graph] will not find an asset matching [name]. 188 /// Expects that the graph will not find an asset matching [name].
45 void expectNoAsset(AssetGraph graph, String name) { 189 void expectNoAsset(String name) {
46 var id = new AssetId.parse(name); 190 var id = new AssetId.parse(name);
47 191
48 // Make sure the future gets the error. 192 // Make sure the future gets the error.
49 schedule(() { 193 schedule(() {
50 return graph.getAssetById(id).then((asset) { 194 return _graph.getAssetById(id).then((asset) {
51 fail("Should have thrown error but got $asset."); 195 fail("Should have thrown error but got $asset.");
52 }).catchError((error) { 196 }).catchError((error) {
53 expect(error, new isInstanceOf<AssetNotFoundException>()); 197 expect(error, new isInstanceOf<AssetNotFoundException>());
54 expect(error.id, equals(id)); 198 expect(error.id, equals(id));
55 }); 199 });
56 }, "get asset $name"); 200 }, "get asset $name");
57 } 201 }
58 202
59 /// Expects that [graph] will have an output file collision error on an asset 203 /// Expects that the graph will have an output file collision error on an asset
60 /// matching [name]. 204 /// matching [name].
61 Future expectCollision(AssetGraph graph, String name) { 205 Future expectCollision(String name) {
62 var id = new AssetId.parse(name); 206 var id = new AssetId.parse(name);
63 return schedule(() { 207 return schedule(() {
64 return graph.results.first.then((result) { 208 return _graph.results.first.then((result) {
65 expect(result.error, new isInstanceOf<AssetCollisionException>()); 209 expect(result.error, new isInstanceOf<AssetCollisionException>());
66 expect(result.error.id, equals(id)); 210 expect(result.error.id, equals(id));
67 }); 211 });
68 }, "get collision on $name"); 212 }, "get collision on $name");
69 } 213 }
70 214
71 /// Expects that [graph] will have an error on an asset matching [name] for 215 /// Expects that [graph] will have an error on an asset matching [name] for
72 /// missing [input]. 216 /// missing [input].
73 Future expectMissingInput(AssetGraph graph, String name, String input) { 217 Future expectMissingInput(AssetGraph graph, String name, String input) {
74 var missing = new AssetId.parse(input); 218 var missing = new AssetId.parse(input);
75 219
76 // Make sure the future gets the error. 220 // Make sure the future gets the error.
77 schedule(() { 221 schedule(() {
78 return graph.getAssetById(new AssetId.parse(name)).then((asset) { 222 return graph.getAssetById(new AssetId.parse(name)).then((asset) {
79 fail("Should have thrown error but got $asset."); 223 fail("Should have thrown error but got $asset.");
80 }).catchError((error) { 224 }).catchError((error) {
81 expect(error, new isInstanceOf<MissingInputException>()); 225 expect(error, new isInstanceOf<MissingInputException>());
82 expect(error.id, equals(missing)); 226 expect(error.id, equals(missing));
83 }); 227 });
84 }, "get missing input on $name"); 228 }, "get missing input on $name");
85 } 229 }
86 230
87 /// An [AssetProvider] that provides the given set of assets. 231 /// An [AssetProvider] that provides the given set of assets.
88 class MockProvider implements AssetProvider { 232 class MockProvider implements AssetProvider {
89 Iterable<String> get packages => _packages.keys; 233 Iterable<String> get packages => _packages.keys;
90 234
91 final _packages = new Map<String, List<MockAsset>>(); 235 final _packages = new Map<String, List<MockAsset>>();
92 236
93 /// The completer that [getAsset()] is waiting on to complete. 237 /// The completer that [getAsset()] is waiting on to complete when paused.
94 /// 238 ///
95 /// If `null` it will return the asset immediately. 239 /// If `null` it will return the asset immediately.
96 Completer _wait; 240 Completer _pauseCompleter;
97 241
98 /// Tells the provider to wait during [getAsset] until [complete()] 242 /// Tells the provider to wait during [getAsset] until [complete()]
99 /// is called. 243 /// is called.
100 /// 244 ///
101 /// Lets you test the asynchronous behavior of loading. 245 /// Lets you test the asynchronous behavior of loading.
102 void wait() { 246 void _pause() {
103 _wait = new Completer(); 247 _pauseCompleter = new Completer();
104 } 248 }
105 249
106 void complete() { 250 void _resume() {
107 _wait.complete(); 251 _pauseCompleter.complete();
108 _wait = null; 252 _pauseCompleter = null;
109 } 253 }
110 254
111 MockProvider(assets) { 255 MockProvider(assets) {
112 if (assets is Map) { 256 if (assets is Map) {
113 assets.forEach((asset, contents) { 257 assets.forEach((asset, contents) {
114 var id = new AssetId.parse(asset); 258 var id = new AssetId.parse(asset);
115 var package = _packages.putIfAbsent(id.package, () => []); 259 var package = _packages.putIfAbsent(id.package, () => []);
116 package.add(new MockAsset(id, contents)); 260 package.add(new MockAsset(id, contents));
117 }); 261 });
118 } else if (assets is Iterable) { 262 } else if (assets is Iterable) {
119 for (var asset in assets) { 263 for (var asset in assets) {
120 var id = new AssetId.parse(asset); 264 var id = new AssetId.parse(asset);
121 var package = _packages.putIfAbsent(id.package, () => []); 265 var package = _packages.putIfAbsent(id.package, () => []);
122 var contents = pathos.basenameWithoutExtension(id.path); 266 var contents = pathos.basenameWithoutExtension(id.path);
123 package.add(new MockAsset(id, contents)); 267 package.add(new MockAsset(id, contents));
124 } 268 }
125 } 269 }
126 } 270 }
127 271
128 void modifyAsset(String name, String contents) { 272 void _modifyAsset(String name, String contents) {
129 var id = new AssetId.parse(name); 273 var id = new AssetId.parse(name);
130 var asset = _packages[id.package].firstWhere((a) => a._id == id); 274 var asset = _packages[id.package].firstWhere((a) => a._id == id);
131 asset._contents = contents; 275 asset._contents = contents;
132 } 276 }
133 277
134 List<AssetId> listAssets(String package, {String within}) { 278 List<AssetId> listAssets(String package, {String within}) {
135 if (within != null) { 279 if (within != null) {
136 throw new UnimplementedError("Doesn't handle 'within' yet."); 280 throw new UnimplementedError("Doesn't handle 'within' yet.");
137 } 281 }
138 282
139 return _packages[package].map((asset) => asset.id); 283 return _packages[package].map((asset) => asset.id);
140 } 284 }
141 285
142 Future<Asset> getAsset(AssetId id) { 286 Future<Asset> getAsset(AssetId id) {
143 var future; 287 var future;
144 if (_wait != null) { 288 if (_pauseCompleter != null) {
145 future = _wait.future; 289 future = _pauseCompleter.future;
146 } else { 290 } else {
147 future = new Future.value(); 291 future = new Future.value();
148 } 292 }
149 293
150 return future.then((_) { 294 return future.then((_) {
151 var package = _packages[id.package]; 295 var package = _packages[id.package];
152 if (package == null) throw new AssetNotFoundException(id); 296 if (package == null) throw new AssetNotFoundException(id);
153 297
154 return package.firstWhere((asset) => asset._id == id, 298 return package.firstWhere((asset) => asset._id == id,
155 orElse: () => throw new AssetNotFoundException(id)); 299 orElse: () => throw new AssetNotFoundException(id));
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 477
334 MockAsset(this._id, this._contents); 478 MockAsset(this._id, this._contents);
335 479
336 String readAsString() => _contents; 480 String readAsString() => _contents;
337 Stream<List<int>> read() => throw new UnimplementedError(); 481 Stream<List<int>> read() => throw new UnimplementedError();
338 482
339 serialize() => throw new UnimplementedError(); 483 serialize() => throw new UnimplementedError();
340 484
341 String toString() => "MockAsset $_id $_contents"; 485 String toString() => "MockAsset $_id $_contents";
342 } 486 }
OLDNEW
« no previous file with comments | « pkg/barback/test/asset_graph/transform_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698