Chromium Code Reviews| 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:convert' show Encoding; | 8 import 'dart:convert' show Encoding; |
| 9 | 9 |
| 10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 // There should be one successful build after adding all the transformers but | 107 // There should be one successful build after adding all the transformers but |
| 108 // before adding any sources. | 108 // before adding any sources. |
| 109 if (!transformers.isEmpty) buildShouldSucceed(); | 109 if (!transformers.isEmpty) buildShouldSucceed(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 /// Updates [assets] in the current [PackageProvider]. | 112 /// Updates [assets] in the current [PackageProvider]. |
| 113 /// | 113 /// |
| 114 /// Each item in the list may either be an [AssetId] or a string that can be | 114 /// Each item in the list may either be an [AssetId] or a string that can be |
| 115 /// parsed as one. | 115 /// parsed as one. |
| 116 void updateSources(Iterable assets) { | 116 void updateSources(Iterable assets) { |
| 117 assets = _parseAssets(assets); | 117 var parsed = _parseAssets(assets); |
| 118 schedule(() => _barback.updateSources(assets), | 118 schedule(() => _barback.updateSources(parsed), |
| 119 "updating ${assets.join(', ')}"); | 119 "updating ${parsed.join(', ')}"); |
| 120 } | 120 } |
| 121 | 121 |
| 122 /// Updates [assets] in the current [PackageProvider]. | 122 /// Updates [assets] in the current [PackageProvider]. |
| 123 /// | 123 /// |
| 124 /// Each item in the list may either be an [AssetId] or a string that can be | 124 /// Each item in the list may either be an [AssetId] or a string that can be |
| 125 /// parsed as one. Unlike [updateSources], this is not automatically scheduled | 125 /// parsed as one. Unlike [updateSources], this is not automatically scheduled |
| 126 /// and will be run synchronously when called. | 126 /// and will be run synchronously when called. |
| 127 void updateSourcesSync(Iterable assets) => | 127 void updateSourcesSync(Iterable assets) => |
| 128 _barback.updateSources(_parseAssets(assets)); | 128 _barback.updateSources(_parseAssets(assets)); |
| 129 | 129 |
| 130 /// Removes [assets] from the current [PackageProvider]. | 130 /// Removes [assets] from the current [PackageProvider]. |
| 131 /// | 131 /// |
| 132 /// Each item in the list may either be an [AssetId] or a string that can be | 132 /// Each item in the list may either be an [AssetId] or a string that can be |
| 133 /// parsed as one. | 133 /// parsed as one. |
| 134 void removeSources(Iterable assets) { | 134 void removeSources(Iterable assets) { |
| 135 assets = _parseAssets(assets); | 135 var parsed = _parseAssets(assets); |
| 136 schedule(() => _barback.removeSources(assets), | 136 schedule(() => _barback.removeSources(parsed), |
| 137 "removing ${assets.join(', ')}"); | 137 "removing ${parsed.join(', ')}"); |
| 138 } | 138 } |
| 139 | 139 |
| 140 /// Removes [assets] from the current [PackageProvider]. | 140 /// Removes [assets] from the current [PackageProvider]. |
| 141 /// | 141 /// |
| 142 /// Each item in the list may either be an [AssetId] or a string that can be | 142 /// Each item in the list may either be an [AssetId] or a string that can be |
| 143 /// parsed as one. Unlike [removeSources], this is not automatically scheduled | 143 /// parsed as one. Unlike [removeSources], this is not automatically scheduled |
| 144 /// and will be run synchronously when called. | 144 /// and will be run synchronously when called. |
| 145 void removeSourcesSync(Iterable assets) => | 145 void removeSourcesSync(Iterable assets) => |
| 146 _barback.removeSources(_parseAssets(assets)); | 146 _barback.removeSources(_parseAssets(assets)); |
| 147 | 147 |
| 148 /// Sets the transformers for [package] to [transformers]. | 148 /// Sets the transformers for [package] to [transformers]. |
| 149 void updateTransformers(String package, Iterable<Iterable> transformers) { | 149 void updateTransformers(String package, Iterable<Iterable> transformers) { |
| 150 schedule(() => _barback.updateTransformers(package, transformers), | 150 schedule(() => _barback.updateTransformers(package, transformers), |
| 151 "updating transformers for $package"); | 151 "updating transformers for $package"); |
| 152 } | 152 } |
| 153 | 153 |
| 154 /// Parse a list of strings or [AssetId]s into a list of [AssetId]s. | 154 /// Parse a list of strings or [AssetId]s into a list of [AssetId]s. |
| 155 List<AssetId> _parseAssets(Iterable assets) { | 155 List<AssetId> _parseAssets(Iterable assets) { |
| 156 return assets.map((asset) { | 156 return assets.map((asset) { |
| 157 if (asset is String) return new AssetId.parse(asset); | 157 if (asset is String) return new AssetId.parse(asset); |
| 158 return asset; | 158 return asset as AssetId; |
| 159 }).toList(); | 159 }).toList(); |
| 160 } | 160 } |
| 161 | 161 |
| 162 /// Schedules a change to the contents of an asset identified by [name] to | 162 /// Schedules a change to the contents of an asset identified by [name] to |
| 163 /// [contents]. | 163 /// [contents]. |
| 164 /// | 164 /// |
| 165 /// Does not update it in the graph. | 165 /// Does not update it in the graph. |
| 166 void modifyAsset(String name, String contents) { | 166 void modifyAsset(String name, String contents) { |
| 167 schedule(() { | 167 schedule(() { |
| 168 _provider._modifyAsset(name, contents); | 168 _provider._modifyAsset(name, contents); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 void buildShouldNotBeDone() { | 203 void buildShouldNotBeDone() { |
| 204 _futureShouldNotCompleteUntil( | 204 _futureShouldNotCompleteUntil( |
| 205 _barback.results.elementAt(_nextBuildResult), | 205 _barback.results.elementAt(_nextBuildResult), |
| 206 schedule(() => pumpEventQueue(), "build should not terminate"), | 206 schedule(() => pumpEventQueue(), "build should not terminate"), |
| 207 "build"); | 207 "build"); |
| 208 } | 208 } |
| 209 | 209 |
| 210 /// Expects that the next [BuildResult] is a build success. | 210 /// Expects that the next [BuildResult] is a build success. |
| 211 void buildShouldSucceed() { | 211 void buildShouldSucceed() { |
| 212 expect(_getNextBuildResult("build should succeed").then((result) { | 212 expect(_getNextBuildResult("build should succeed").then((result) { |
| 213 result.errors.forEach(currentSchedule.signalError); | 213 for (var error in result.errors) { |
| 214 currentSchedule.signalError(error); | |
| 215 } | |
| 214 expect(result.succeeded, isTrue); | 216 expect(result.succeeded, isTrue); |
| 215 }), completes); | 217 }), completes); |
| 216 } | 218 } |
| 217 | 219 |
| 218 /// Expects that the next [BuildResult] emitted is a failure. | 220 /// Expects that the next [BuildResult] emitted is a failure. |
| 219 /// | 221 /// |
| 220 /// [matchers] is a list of matchers to match against the errors that caused the | 222 /// [matchers] is a list of matchers to match against the errors that caused the |
| 221 /// build to fail. Every matcher is expected to match an error, but the order of | 223 /// build to fail. Every matcher is expected to match an error, but the order of |
| 222 /// matchers is unimportant. | 224 /// matchers is unimportant. |
| 223 void buildShouldFail(List matchers) { | 225 void buildShouldFail(List matchers) { |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 } | 513 } |
| 512 | 514 |
| 513 MockProvider(assets, {Iterable<String> staticPackages, | 515 MockProvider(assets, {Iterable<String> staticPackages, |
| 514 Iterable<String> additionalPackages}) | 516 Iterable<String> additionalPackages}) |
| 515 : staticPackages = staticPackages == null ? new Set() : | 517 : staticPackages = staticPackages == null ? new Set() : |
| 516 staticPackages.toSet(), | 518 staticPackages.toSet(), |
| 517 _assets = _normalizeAssets(assets, additionalPackages); | 519 _assets = _normalizeAssets(assets, additionalPackages); |
| 518 | 520 |
| 519 static Map<String, AssetSet> _normalizeAssets(assets, | 521 static Map<String, AssetSet> _normalizeAssets(assets, |
| 520 Iterable<String> additionalPackages) { | 522 Iterable<String> additionalPackages) { |
| 521 var assetList; | 523 Iterable<Asset> assetList; |
| 522 if (assets is Map) { | 524 if (assets is Map) { |
| 523 assetList = assets.keys.map((asset) { | 525 assetList = assets.keys.map((asset) { |
| 524 var id = new AssetId.parse(asset); | 526 var id = new AssetId.parse(asset); |
| 525 return new _MockAsset(id, assets[asset]); | 527 return new _MockAsset(id, assets[asset]); |
| 526 }); | 528 }); |
| 527 } else if (assets is Iterable) { | 529 } else if (assets is Iterable) { |
| 528 assetList = assets.map((asset) { | 530 assetList = assets.map((asset) { |
| 529 var id = new AssetId.parse(asset); | 531 var id = new AssetId.parse(asset); |
| 530 var contents = pathos.basenameWithoutExtension(id.path); | 532 var contents = pathos.basenameWithoutExtension(id.path); |
| 531 return new _MockAsset(id, contents); | 533 return new _MockAsset(id, contents); |
| 532 }); | 534 }); |
| 533 } | 535 } |
| 534 | 536 |
| 535 var assetMap = mapMapValues(groupBy(assetList, (asset) => asset.id.package), | 537 var assetMap = mapMapValues/*<String, List<Asset>, AssetSet>*/( |
|
Bob Nystrom
2016/05/13 21:07:50
Does the inference not cover this case? If not, it
nweiz
2016/05/17 17:27:46
Looks like it's working now!
| |
| 536 (package, assets) => new AssetSet.from(assets)); | 538 groupBy(assetList, (asset) => asset.id.package), |
| 539 (_, assets) => new AssetSet.from(assets)); | |
| 537 | 540 |
| 538 // Make sure that packages that have transformers but no assets are | 541 // Make sure that packages that have transformers but no assets are |
| 539 // considered by MockProvider to exist. | 542 // considered by MockProvider to exist. |
| 540 if (additionalPackages != null) { | 543 if (additionalPackages != null) { |
| 541 for (var package in additionalPackages) { | 544 for (var package in additionalPackages) { |
| 542 assetMap.putIfAbsent(package, () => new AssetSet()); | 545 assetMap.putIfAbsent(package, () => new AssetSet()); |
| 543 } | 546 } |
| 544 } | 547 } |
| 545 | 548 |
| 546 // If there are no assets or transformers, add a dummy package. This better | 549 // If there are no assets or transformers, add a dummy package. This better |
| 547 // simulates the real world, where there'll always be at least the | 550 // simulates the real world, where there'll always be at least the |
| 548 // entrypoint package. | 551 // entrypoint package. |
| 549 return assetMap.isEmpty ? {"app": new AssetSet()} : assetMap; | 552 return assetMap.isEmpty ? {"app": new AssetSet()} : assetMap; |
| 550 } | 553 } |
| 551 | 554 |
| 552 void _modifyAsset(String name, String contents) { | 555 void _modifyAsset(String name, String contents) { |
| 553 var id = new AssetId.parse(name); | 556 var id = new AssetId.parse(name); |
| 554 _errors.remove(id); | 557 _errors.remove(id); |
| 555 _syncErrors.remove(id); | 558 _syncErrors.remove(id); |
| 556 (_assets[id.package][id] as _MockAsset).contents = contents; | 559 (_assets[id.package][id] as _MockAsset).contents = contents; |
| 557 } | 560 } |
| 558 | 561 |
| 559 void _setAssetError(String name, bool async) { | 562 void _setAssetError(String name, bool async) { |
| 560 (async ? _errors : _syncErrors).add(new AssetId.parse(name)); | 563 (async ? _errors : _syncErrors).add(new AssetId.parse(name)); |
| 561 } | 564 } |
| 562 | 565 |
| 563 Stream<AssetId> getAllAssetIds(String package) => | 566 Stream<AssetId> getAllAssetIds(String package) => |
| 564 new Stream.fromIterable(_assets[package].map((asset) => asset.id)); | 567 new Stream.fromIterable(_assets[package].map((asset) => asset.id)); |
| 565 | 568 |
| 566 Future<Asset> getAsset(AssetId id) { | 569 Future<Asset> getAsset(AssetId id) async { |
| 567 // Eagerly load the asset so we can test an asset's value changing between | 570 // Eagerly load the asset so we can test an asset's value changing between |
| 568 // when a load starts and when it finishes. | 571 // when a load starts and when it finishes. |
| 569 var assets = _assets[id.package]; | 572 var assets = _assets[id.package]; |
| 570 var asset; | 573 var asset; |
| 571 if (assets != null) asset = assets[id]; | 574 if (assets != null) asset = assets[id]; |
| 572 | 575 |
| 573 if (_syncErrors.contains(id)) throw new MockLoadException(id); | 576 if (_syncErrors.contains(id)) throw new MockLoadException(id); |
| 574 var hasError = _errors.contains(id); | 577 var hasError = _errors.contains(id); |
| 575 | 578 |
| 576 var future; | 579 if (_pauseCompleter != null) await _pauseCompleter.future; |
| 577 if (_pauseCompleter != null) { | |
| 578 future = _pauseCompleter.future; | |
| 579 } else { | |
| 580 future = new Future.value(); | |
| 581 } | |
| 582 | 580 |
| 583 return future.then((_) { | 581 if (hasError) throw new MockLoadException(id); |
| 584 if (hasError) throw new MockLoadException(id); | 582 if (asset == null) throw new AssetNotFoundException(id); |
| 585 if (asset == null) throw new AssetNotFoundException(id); | 583 return asset; |
| 586 return asset; | |
| 587 }); | |
| 588 } | 584 } |
| 589 } | 585 } |
| 590 | 586 |
| 591 /// Error thrown for assets with [setAssetError] set. | 587 /// Error thrown for assets with [setAssetError] set. |
| 592 class MockLoadException implements Exception { | 588 class MockLoadException implements Exception { |
| 593 final AssetId id; | 589 final AssetId id; |
| 594 | 590 |
| 595 MockLoadException(this.id); | 591 MockLoadException(this.id); |
| 596 | 592 |
| 597 String toString() => "Error loading $id."; | 593 String toString() => "Error loading $id."; |
| 598 } | 594 } |
| 599 | 595 |
| 600 /// An implementation of [Asset] that never hits the file system. | 596 /// An implementation of [Asset] that never hits the file system. |
| 601 class _MockAsset implements Asset { | 597 class _MockAsset implements Asset { |
| 602 final AssetId id; | 598 final AssetId id; |
| 603 String contents; | 599 String contents; |
| 604 | 600 |
| 605 _MockAsset(this.id, this.contents); | 601 _MockAsset(this.id, this.contents); |
| 606 | 602 |
| 607 Future<String> readAsString({Encoding encoding}) => | 603 Future<String> readAsString({Encoding encoding}) => |
| 608 new Future.value(contents); | 604 new Future.value(contents); |
| 609 | 605 |
| 610 Stream<List<int>> read() => throw new UnimplementedError(); | 606 Stream<List<int>> read() => throw new UnimplementedError(); |
| 611 | 607 |
| 612 String toString() => "MockAsset $id $contents"; | 608 String toString() => "MockAsset $id $contents"; |
| 613 } | 609 } |
| OLD | NEW |