| OLD | NEW |
| 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 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 } | 124 } |
| 125 | 125 |
| 126 /// Pauses the schedule until the currently running build completes. | 126 /// Pauses the schedule until the currently running build completes. |
| 127 /// | 127 /// |
| 128 /// Validates that the build completed successfully. | 128 /// Validates that the build completed successfully. |
| 129 void waitForBuild() { | 129 void waitForBuild() { |
| 130 schedule(() { | 130 schedule(() { |
| 131 return _graph.results.first.then((result) { | 131 return _graph.results.first.then((result) { |
| 132 expect(result.succeeded, isTrue); | 132 expect(result.succeeded, isTrue); |
| 133 }); | 133 }); |
| 134 }); | 134 }, "wait for build"); |
| 135 } | 135 } |
| 136 | 136 |
| 137 /// Schedules an expectation that the graph will deliver an asset matching | 137 /// Schedules an expectation that the graph will deliver an asset matching |
| 138 /// [name] and [contents]. | 138 /// [name] and [contents]. |
| 139 /// | 139 /// |
| 140 /// If [contents] is omitted, defaults to the asset's filename without an | 140 /// If [contents] is omitted, defaults to the asset's filename without an |
| 141 /// extension (which is the same default that [initGraph] uses). | 141 /// extension (which is the same default that [initGraph] uses). |
| 142 void expectAsset(String name, [String contents]) { | 142 void expectAsset(String name, [String contents]) { |
| 143 var id = new AssetId.parse(name); | 143 var id = new AssetId.parse(name); |
| 144 | 144 |
| 145 if (contents == null) { | 145 if (contents == null) { |
| 146 contents = pathos.basenameWithoutExtension(id.path); | 146 contents = pathos.basenameWithoutExtension(id.path); |
| 147 } | 147 } |
| 148 | 148 |
| 149 schedule(() { | 149 schedule(() { |
| 150 return _graph.getAssetById(id).then((asset) { | 150 return _graph.getAssetById(id).then((asset) { |
| 151 // TODO(rnystrom): Make an actual Matcher class for this. | 151 // TODO(rnystrom): Make an actual Matcher class for this. |
| 152 expect(asset, new isInstanceOf<MockAsset>()); | 152 expect(asset, new isInstanceOf<MockAsset>()); |
| 153 expect(asset._id.package, equals(id.package)); | 153 expect(asset.id, equals(id)); |
| 154 expect(asset._id.path, equals(id.path)); | 154 expect(asset.contents, equals(contents)); |
| 155 expect(asset._contents, equals(contents)); | |
| 156 }); | 155 }); |
| 157 }, "get asset $name"); | 156 }, "get asset $name"); |
| 158 } | 157 } |
| 159 | 158 |
| 160 /// Schedules an expectation that the graph will not find an asset matching | 159 /// Schedules an expectation that the graph will not find an asset matching |
| 161 /// [name]. | 160 /// [name]. |
| 162 void expectNoAsset(String name) { | 161 void expectNoAsset(String name) { |
| 163 var id = new AssetId.parse(name); | 162 var id = new AssetId.parse(name); |
| 164 | 163 |
| 165 // Make sure the future gets the error. | 164 // Make sure the future gets the error. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 var id = new AssetId.parse(asset); | 234 var id = new AssetId.parse(asset); |
| 236 var package = _packages.putIfAbsent(id.package, () => []); | 235 var package = _packages.putIfAbsent(id.package, () => []); |
| 237 var contents = pathos.basenameWithoutExtension(id.path); | 236 var contents = pathos.basenameWithoutExtension(id.path); |
| 238 package.add(new MockAsset(id, contents)); | 237 package.add(new MockAsset(id, contents)); |
| 239 } | 238 } |
| 240 } | 239 } |
| 241 } | 240 } |
| 242 | 241 |
| 243 void _modifyAsset(String name, String contents) { | 242 void _modifyAsset(String name, String contents) { |
| 244 var id = new AssetId.parse(name); | 243 var id = new AssetId.parse(name); |
| 245 var asset = _packages[id.package].firstWhere((a) => a._id == id); | 244 var asset = _packages[id.package].firstWhere((a) => a.id == id); |
| 246 asset._contents = contents; | 245 asset.contents = contents; |
| 247 } | 246 } |
| 248 | 247 |
| 249 List<AssetId> listAssets(String package, {String within}) { | 248 List<AssetId> listAssets(String package, {String within}) { |
| 250 if (within != null) { | 249 if (within != null) { |
| 251 throw new UnimplementedError("Doesn't handle 'within' yet."); | 250 throw new UnimplementedError("Doesn't handle 'within' yet."); |
| 252 } | 251 } |
| 253 | 252 |
| 254 return _packages[package].map((asset) => asset.id); | 253 return _packages[package].map((asset) => asset.id); |
| 255 } | 254 } |
| 256 | 255 |
| 257 Future<Asset> getAsset(AssetId id) { | 256 Future<Asset> getAsset(AssetId id) { |
| 258 var future; | 257 var future; |
| 259 if (_pauseCompleter != null) { | 258 if (_pauseCompleter != null) { |
| 260 future = _pauseCompleter.future; | 259 future = _pauseCompleter.future; |
| 261 } else { | 260 } else { |
| 262 future = new Future.value(); | 261 future = new Future.value(); |
| 263 } | 262 } |
| 264 | 263 |
| 265 return future.then((_) { | 264 return future.then((_) { |
| 266 var package = _packages[id.package]; | 265 var package = _packages[id.package]; |
| 267 if (package == null) throw new AssetNotFoundException(id); | 266 if (package == null) throw new AssetNotFoundException(id); |
| 268 | 267 |
| 269 return package.firstWhere((asset) => asset._id == id, | 268 return package.firstWhere((asset) => asset.id == id, |
| 270 orElse: () => throw new AssetNotFoundException(id)); | 269 orElse: () => throw new AssetNotFoundException(id)); |
| 271 }); | 270 }); |
| 272 } | 271 } |
| 273 } | 272 } |
| 274 | 273 |
| 275 /// A [Transformer] that takes assets ending with one extension and generates | 274 /// A [Transformer] that takes assets ending with one extension and generates |
| 276 /// assets with a given extension. | 275 /// assets with a given extension. |
| 277 /// | 276 /// |
| 278 /// Appends the output extension to the contents of the input file. | 277 /// Appends the output extension to the contents of the input file. |
| 279 class RewriteTransformer extends Transformer { | 278 class RewriteTransformer extends Transformer { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 /// Lets you test the asynchronous behavior of transformers. | 310 /// Lets you test the asynchronous behavior of transformers. |
| 312 void wait() { | 311 void wait() { |
| 313 _wait = new Completer(); | 312 _wait = new Completer(); |
| 314 } | 313 } |
| 315 | 314 |
| 316 void complete() { | 315 void complete() { |
| 317 _wait.complete(); | 316 _wait.complete(); |
| 318 _wait = null; | 317 _wait = null; |
| 319 } | 318 } |
| 320 | 319 |
| 321 Future<bool> isPrimary(AssetId asset) { | 320 Future<bool> isPrimary(Asset asset) { |
| 322 return new Future.value(asset.extension == ".$from"); | 321 return new Future.value(asset.id.extension == ".$from"); |
| 323 } | 322 } |
| 324 | 323 |
| 325 Future apply(Transform transform) { | 324 Future apply(Transform transform) { |
| 326 numRuns++; | 325 numRuns++; |
| 327 if (!_started.isCompleted) _started.complete(); | 326 if (!_started.isCompleted) _started.complete(); |
| 328 _runningTransforms++; | 327 _runningTransforms++; |
| 329 return transform.primaryInput.then((input) { | 328 return transform.primaryInput.then((input) { |
| 330 return Future.wait(to.split(" ").map((extension) { | 329 return Future.wait(to.split(" ").map((extension) { |
| 331 var id = transform.primaryId.changeExtension(".$extension"); | 330 var id = transform.primaryId.changeExtension(".$extension"); |
| 332 return input.readAsString().then((content) { | 331 return input.readAsString().then((content) { |
| 333 transform.addOutput(id, new MockAsset(id, "$content.$extension")); | 332 transform.addOutput(new MockAsset(id, "$content.$extension")); |
| 334 }); | 333 }); |
| 335 })).then((_) { | 334 })).then((_) { |
| 336 if (_wait != null) return _wait.future; | 335 if (_wait != null) return _wait.future; |
| 337 }); | 336 }); |
| 338 }).whenComplete(() { | 337 }).whenComplete(() { |
| 339 _runningTransforms--; | 338 _runningTransforms--; |
| 340 }); | 339 }); |
| 341 } | 340 } |
| 342 | 341 |
| 343 String toString() => "$from->$to"; | 342 String toString() => "$from->$to"; |
| 344 } | 343 } |
| 345 | 344 |
| 346 /// A [Transformer] that takes an input asset that contains a comma-separated | 345 /// A [Transformer] that takes an input asset that contains a comma-separated |
| 347 /// list of paths and outputs a file for each path. | 346 /// list of paths and outputs a file for each path. |
| 348 class OneToManyTransformer extends Transformer { | 347 class OneToManyTransformer extends Transformer { |
| 349 final String extension; | 348 final String extension; |
| 350 | 349 |
| 351 /// The number of times the transformer has been applied. | 350 /// The number of times the transformer has been applied. |
| 352 int numRuns = 0; | 351 int numRuns = 0; |
| 353 | 352 |
| 354 /// Creates a transformer that consumes assets with [extension]. | 353 /// Creates a transformer that consumes assets with [extension]. |
| 355 /// | 354 /// |
| 356 /// That file contains a comma-separated list of paths and it will output | 355 /// That file contains a comma-separated list of paths and it will output |
| 357 /// files at each of those paths. | 356 /// files at each of those paths. |
| 358 OneToManyTransformer(this.extension); | 357 OneToManyTransformer(this.extension); |
| 359 | 358 |
| 360 Future<bool> isPrimary(AssetId asset) { | 359 Future<bool> isPrimary(Asset asset) { |
| 361 return new Future.value(asset.extension == ".$extension"); | 360 return new Future.value(asset.id.extension == ".$extension"); |
| 362 } | 361 } |
| 363 | 362 |
| 364 Future apply(Transform transform) { | 363 Future apply(Transform transform) { |
| 365 numRuns++; | 364 numRuns++; |
| 366 return transform.primaryInput.then((input) { | 365 return transform.primaryInput.then((input) { |
| 367 return input.readAsString().then((lines) { | 366 return input.readAsString().then((lines) { |
| 368 for (var line in lines.split(",")) { | 367 for (var line in lines.split(",")) { |
| 369 var id = new AssetId(transform.primaryId.package, line); | 368 var id = new AssetId(transform.primaryId.package, line); |
| 370 transform.addOutput(id, new MockAsset(id, "spread $extension")); | 369 transform.addOutput(new MockAsset(id, "spread $extension")); |
| 371 } | 370 } |
| 372 }); | 371 }); |
| 373 }); | 372 }); |
| 374 } | 373 } |
| 375 | 374 |
| 376 String toString() => "1->many $extension"; | 375 String toString() => "1->many $extension"; |
| 377 } | 376 } |
| 378 | 377 |
| 379 /// A transformer that uses the contents of a file to define the other inputs. | 378 /// A transformer that uses the contents of a file to define the other inputs. |
| 380 /// | 379 /// |
| 381 /// Outputs a file with the same name as the primary but with an "out" | 380 /// Outputs a file with the same name as the primary but with an "out" |
| 382 /// extension containing the concatenated contents of all non-primary inputs. | 381 /// extension containing the concatenated contents of all non-primary inputs. |
| 383 class ManyToOneTransformer extends Transformer { | 382 class ManyToOneTransformer extends Transformer { |
| 384 final String extension; | 383 final String extension; |
| 385 | 384 |
| 386 /// The number of times the transformer has been applied. | 385 /// The number of times the transformer has been applied. |
| 387 int numRuns = 0; | 386 int numRuns = 0; |
| 388 | 387 |
| 389 /// Creates a transformer that consumes assets with [extension]. | 388 /// Creates a transformer that consumes assets with [extension]. |
| 390 /// | 389 /// |
| 391 /// That file contains a comma-separated list of paths and it will input | 390 /// That file contains a comma-separated list of paths and it will input |
| 392 /// files at each of those paths. | 391 /// files at each of those paths. |
| 393 ManyToOneTransformer(this.extension); | 392 ManyToOneTransformer(this.extension); |
| 394 | 393 |
| 395 Future<bool> isPrimary(AssetId asset) { | 394 Future<bool> isPrimary(Asset asset) { |
| 396 return new Future.value(asset.extension == ".$extension"); | 395 return new Future.value(asset.id.extension == ".$extension"); |
| 397 } | 396 } |
| 398 | 397 |
| 399 Future apply(Transform transform) { | 398 Future apply(Transform transform) { |
| 400 numRuns++; | 399 numRuns++; |
| 401 return transform.primaryInput.then((primary) { | 400 return transform.primaryInput.then((primary) { |
| 402 return primary.readAsString().then((contents) { | 401 return primary.readAsString().then((contents) { |
| 403 // Get all of the included inputs. | 402 // Get all of the included inputs. |
| 404 var inputs = contents.split(",").map((path) { | 403 var inputs = contents.split(",").map((path) { |
| 405 var id = new AssetId(transform.primaryId.package, path); | 404 var id = new AssetId(transform.primaryId.package, path); |
| 406 return transform.getInput(id); | 405 return transform.getInput(id); |
| 407 }); | 406 }); |
| 408 | 407 |
| 409 return Future.wait(inputs); | 408 return Future.wait(inputs); |
| 410 }).then((inputs) { | 409 }).then((inputs) { |
| 411 // Concatenate them to one output. | 410 // Concatenate them to one output. |
| 412 var output = ""; | 411 var output = ""; |
| 413 return Future.forEach(inputs, (input) { | 412 return Future.forEach(inputs, (input) { |
| 414 return input.readAsString().then((contents) { | 413 return input.readAsString().then((contents) { |
| 415 output += contents; | 414 output += contents; |
| 416 }); | 415 }); |
| 417 }).then((_) { | 416 }).then((_) { |
| 418 var id = transform.primaryId.changeExtension(".out"); | 417 var id = transform.primaryId.changeExtension(".out"); |
| 419 transform.addOutput(id, new MockAsset(id, output)); | 418 transform.addOutput(new MockAsset(id, output)); |
| 420 }); | 419 }); |
| 421 }); | 420 }); |
| 422 }); | 421 }); |
| 423 } | 422 } |
| 424 | 423 |
| 425 String toString() => "many->1 $extension"; | 424 String toString() => "many->1 $extension"; |
| 426 } | 425 } |
| 427 | 426 |
| 428 /// A transformer that throws an exception when run, after generating the | 427 /// A transformer that throws an exception when run, after generating the |
| 429 /// given outputs. | 428 /// given outputs. |
| 430 class BadTransformer extends Transformer { | 429 class BadTransformer extends Transformer { |
| 431 /// The error it throws. | 430 /// The error it throws. |
| 432 static const ERROR = "I am a bad transformer!"; | 431 static const ERROR = "I am a bad transformer!"; |
| 433 | 432 |
| 434 /// The list of asset names that it should output. | 433 /// The list of asset names that it should output. |
| 435 final List<String> outputs; | 434 final List<String> outputs; |
| 436 | 435 |
| 437 BadTransformer(this.outputs); | 436 BadTransformer(this.outputs); |
| 438 | 437 |
| 439 Future<bool> isPrimary(AssetId asset) => new Future.value(true); | 438 Future<bool> isPrimary(Asset asset) => new Future.value(true); |
| 440 Future apply(Transform transform) { | 439 Future apply(Transform transform) { |
| 441 return new Future(() { | 440 return new Future(() { |
| 442 // Create the outputs first. | 441 // Create the outputs first. |
| 443 for (var output in outputs) { | 442 for (var output in outputs) { |
| 444 var id = new AssetId.parse(output); | 443 var id = new AssetId.parse(output); |
| 445 transform.addOutput(id, new MockAsset(id, output)); | 444 transform.addOutput(new MockAsset(id, output)); |
| 446 } | 445 } |
| 447 | 446 |
| 448 // Then fail. | 447 // Then fail. |
| 449 throw ERROR; | 448 throw ERROR; |
| 450 }); | 449 }); |
| 451 } | 450 } |
| 452 } | 451 } |
| 453 | 452 |
| 454 /// An implementation of [Asset] that never hits the file system. | 453 /// An implementation of [Asset] that never hits the file system. |
| 455 class MockAsset implements Asset { | 454 class MockAsset implements Asset { |
| 456 final AssetId _id; | 455 final AssetId id; |
| 457 String _contents; | 456 String contents; |
| 458 | 457 |
| 459 MockAsset(this._id, this._contents); | 458 MockAsset(this.id, this.contents); |
| 460 | 459 |
| 461 Future<String> readAsString() => new Future.value(_contents); | 460 Future<String> readAsString() => new Future.value(contents); |
| 462 Stream<List<int>> read() => throw new UnimplementedError(); | 461 Stream<List<int>> read() => throw new UnimplementedError(); |
| 463 | 462 |
| 464 serialize() => throw new UnimplementedError(); | 463 serialize() => throw new UnimplementedError(); |
| 465 | 464 |
| 466 String toString() => "MockAsset $_id $_contents"; | 465 String toString() => "MockAsset $id $contents"; |
| 467 } | 466 } |
| OLD | NEW |