| 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 import 'dart:io'; | 9 import 'dart:io'; |
| 10 | 10 |
| 11 import 'package:barback/barback.dart'; | 11 import 'package:barback/barback.dart'; |
| 12 import 'package:barback/src/asset_cascade.dart'; | |
| 13 import 'package:barback/src/asset_set.dart'; | 12 import 'package:barback/src/asset_set.dart'; |
| 14 import 'package:barback/src/cancelable_future.dart'; | 13 import 'package:barback/src/cancelable_future.dart'; |
| 15 import 'package:barback/src/package_graph.dart'; | |
| 16 import 'package:barback/src/utils.dart'; | 14 import 'package:barback/src/utils.dart'; |
| 17 import 'package:path/path.dart' as pathos; | 15 import 'package:path/path.dart' as pathos; |
| 18 import 'package:scheduled_test/scheduled_test.dart'; | 16 import 'package:scheduled_test/scheduled_test.dart'; |
| 19 import 'package:stack_trace/stack_trace.dart'; | 17 import 'package:stack_trace/stack_trace.dart'; |
| 20 import 'package:unittest/compact_vm_config.dart'; | 18 import 'package:unittest/compact_vm_config.dart'; |
| 21 | 19 |
| 22 export 'transformer/bad.dart'; | 20 export 'transformer/bad.dart'; |
| 23 export 'transformer/check_content.dart'; | 21 export 'transformer/check_content.dart'; |
| 24 export 'transformer/create_asset.dart'; | 22 export 'transformer/create_asset.dart'; |
| 25 export 'transformer/many_to_one.dart'; | 23 export 'transformer/many_to_one.dart'; |
| 26 export 'transformer/mock.dart'; | 24 export 'transformer/mock.dart'; |
| 27 export 'transformer/one_to_many.dart'; | 25 export 'transformer/one_to_many.dart'; |
| 28 export 'transformer/rewrite.dart'; | 26 export 'transformer/rewrite.dart'; |
| 29 | 27 |
| 30 var _configured = false; | 28 var _configured = false; |
| 31 | 29 |
| 32 MockProvider _provider; | 30 MockProvider _provider; |
| 33 PackageGraph _graph; | 31 Barback _barback; |
| 34 | 32 |
| 35 /// Calls to [buildShouldSucceed] and [buildShouldFail] set expectations on | 33 /// Calls to [buildShouldSucceed] and [buildShouldFail] set expectations on |
| 36 /// successive [BuildResult]s from [_graph]. This keeps track of how many calls | 34 /// successive [BuildResult]s from [_barback]. This keeps track of how many |
| 37 /// have already been made so later calls know which result to look for. | 35 /// calls have already been made so later calls know which result to look for. |
| 38 int _nextBuildResult; | 36 int _nextBuildResult; |
| 39 | 37 |
| 40 void initConfig() { | 38 void initConfig() { |
| 41 if (_configured) return; | 39 if (_configured) return; |
| 42 _configured = true; | 40 _configured = true; |
| 43 useCompactVMConfiguration(); | 41 useCompactVMConfiguration(); |
| 44 } | 42 } |
| 45 | 43 |
| 46 /// Creates a new [PackageProvider] and [PackageGraph] with the given [assets] | 44 /// Creates a new [PackageProvider] and [PackageGraph] with the given [assets] |
| 47 /// and [transformers]. | 45 /// and [transformers]. |
| 48 /// | 46 /// |
| 49 /// This graph is used internally by most of the other functions in this | 47 /// This graph is used internally by most of the other functions in this |
| 50 /// library so you must call it in the test before calling any of the other | 48 /// library so you must call it in the test before calling any of the other |
| 51 /// functions. | 49 /// functions. |
| 52 /// | 50 /// |
| 53 /// [assets] may either be an [Iterable] or a [Map]. If it's an [Iterable], | 51 /// [assets] may either be an [Iterable] or a [Map]. If it's an [Iterable], |
| 54 /// each element may either be an [AssetId] or a string that can be parsed to | 52 /// each element may either be an [AssetId] or a string that can be parsed to |
| 55 /// one. If it's a [Map], each key should be a string that can be parsed to an | 53 /// one. If it's a [Map], each key should be a string that can be parsed to an |
| 56 /// [AssetId] and the value should be a string defining the contents of that | 54 /// [AssetId] and the value should be a string defining the contents of that |
| 57 /// asset. | 55 /// asset. |
| 58 /// | 56 /// |
| 59 /// [transformers] is a map from package names to the transformers for each | 57 /// [transformers] is a map from package names to the transformers for each |
| 60 /// package. | 58 /// package. |
| 61 void initGraph([assets, | 59 void initGraph([assets, |
| 62 Map<String, Iterable<Iterable<Transformer>>> transformers]) { | 60 Map<String, Iterable<Iterable<Transformer>>> transformers]) { |
| 63 if (assets == null) assets = []; | 61 if (assets == null) assets = []; |
| 64 if (transformers == null) transformers = {}; | 62 if (transformers == null) transformers = {}; |
| 65 | 63 |
| 66 _provider = new MockProvider(assets, transformers); | 64 _provider = new MockProvider(assets, transformers); |
| 67 _graph = new PackageGraph(_provider); | 65 _barback = new Barback(_provider); |
| 68 _nextBuildResult = 0; | 66 _nextBuildResult = 0; |
| 69 } | 67 } |
| 70 | 68 |
| 71 /// Updates [assets] in the current [PackageProvider]. | 69 /// Updates [assets] in the current [PackageProvider]. |
| 72 /// | 70 /// |
| 73 /// Each item in the list may either be an [AssetId] or a string that can be | 71 /// Each item in the list may either be an [AssetId] or a string that can be |
| 74 /// parsed as one. Note that this method is not automatically scheduled. | 72 /// parsed as one. Note that this method is not automatically scheduled. |
| 75 void updateSources(Iterable assets) { | 73 void updateSources(Iterable assets) { |
| 76 // Allow strings as asset IDs. | 74 // Allow strings as asset IDs. |
| 77 assets = assets.map((asset) { | 75 assets = assets.map((asset) { |
| 78 if (asset is String) return new AssetId.parse(asset); | 76 if (asset is String) return new AssetId.parse(asset); |
| 79 return asset; | 77 return asset; |
| 80 }); | 78 }); |
| 81 | 79 |
| 82 _graph.updateSources(assets); | 80 _barback.updateSources(assets); |
| 83 } | 81 } |
| 84 | 82 |
| 85 /// Removes [assets] from the current [PackageProvider]. | 83 /// Removes [assets] from the current [PackageProvider]. |
| 86 /// | 84 /// |
| 87 /// Each item in the list may either be an [AssetId] or a string that can be | 85 /// Each item in the list may either be an [AssetId] or a string that can be |
| 88 /// parsed as one. Note that this method is not automatically scheduled. | 86 /// parsed as one. Note that this method is not automatically scheduled. |
| 89 void removeSources(Iterable assets) { | 87 void removeSources(Iterable assets) { |
| 90 // Allow strings as asset IDs. | 88 // Allow strings as asset IDs. |
| 91 assets = assets.map((asset) { | 89 assets = assets.map((asset) { |
| 92 if (asset is String) return new AssetId.parse(asset); | 90 if (asset is String) return new AssetId.parse(asset); |
| 93 return asset; | 91 return asset; |
| 94 }); | 92 }); |
| 95 | 93 |
| 96 _graph.removeSources(assets); | 94 _barback.removeSources(assets); |
| 97 } | 95 } |
| 98 | 96 |
| 99 /// Schedules a change to the contents of an asset identified by [name] to | 97 /// Schedules a change to the contents of an asset identified by [name] to |
| 100 /// [contents]. | 98 /// [contents]. |
| 101 /// | 99 /// |
| 102 /// Does not update it in the graph. | 100 /// Does not update it in the graph. |
| 103 void modifyAsset(String name, String contents) { | 101 void modifyAsset(String name, String contents) { |
| 104 schedule(() { | 102 schedule(() { |
| 105 _provider._modifyAsset(name, contents); | 103 _provider._modifyAsset(name, contents); |
| 106 }, "modify asset $name"); | 104 }, "modify asset $name"); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 131 } | 129 } |
| 132 | 130 |
| 133 /// Asserts that the current build step shouldn't have finished by this point in | 131 /// Asserts that the current build step shouldn't have finished by this point in |
| 134 /// the schedule. | 132 /// the schedule. |
| 135 /// | 133 /// |
| 136 /// This uses the same build counter as [buildShouldSucceed] and | 134 /// This uses the same build counter as [buildShouldSucceed] and |
| 137 /// [buildShouldFail], so those can be used to validate build results before and | 135 /// [buildShouldFail], so those can be used to validate build results before and |
| 138 /// after this. | 136 /// after this. |
| 139 void buildShouldNotBeDone() { | 137 void buildShouldNotBeDone() { |
| 140 _futureShouldNotCompleteUntil( | 138 _futureShouldNotCompleteUntil( |
| 141 _graph.results.elementAt(_nextBuildResult), | 139 _barback.results.elementAt(_nextBuildResult), |
| 142 schedule(() => pumpEventQueue(), "build should not terminate"), | 140 schedule(() => pumpEventQueue(), "build should not terminate"), |
| 143 "build"); | 141 "build"); |
| 144 } | 142 } |
| 145 | 143 |
| 146 /// Expects that the next [BuildResult] is a build success. | 144 /// Expects that the next [BuildResult] is a build success. |
| 147 void buildShouldSucceed() { | 145 void buildShouldSucceed() { |
| 148 expect(_getNextBuildResult().then((result) { | 146 expect(_getNextBuildResult().then((result) { |
| 149 result.errors.forEach(currentSchedule.signalError); | 147 result.errors.forEach(currentSchedule.signalError); |
| 150 expect(result.succeeded, isTrue); | 148 expect(result.succeeded, isTrue); |
| 151 }), completes); | 149 }), completes); |
| 152 } | 150 } |
| 153 | 151 |
| 154 /// Expects that the next [BuildResult] emitted is a failure. | 152 /// Expects that the next [BuildResult] emitted is a failure. |
| 155 /// | 153 /// |
| 156 /// [matchers] is a list of matchers to match against the errors that caused the | 154 /// [matchers] is a list of matchers to match against the errors that caused the |
| 157 /// build to fail. Every matcher is expected to match an error, but the order of | 155 /// build to fail. Every matcher is expected to match an error, but the order of |
| 158 /// matchers is unimportant. | 156 /// matchers is unimportant. |
| 159 void buildShouldFail(List matchers) { | 157 void buildShouldFail(List matchers) { |
| 160 expect(_getNextBuildResult().then((result) { | 158 expect(_getNextBuildResult().then((result) { |
| 161 expect(result.succeeded, isFalse); | 159 expect(result.succeeded, isFalse); |
| 162 expect(result.errors.length, equals(matchers.length)); | 160 expect(result.errors.length, equals(matchers.length)); |
| 163 for (var matcher in matchers) { | 161 for (var matcher in matchers) { |
| 164 expect(result.errors, contains(matcher)); | 162 expect(result.errors, contains(matcher)); |
| 165 } | 163 } |
| 166 }), completes); | 164 }), completes); |
| 167 } | 165 } |
| 168 | 166 |
| 169 Future<BuildResult> _getNextBuildResult() => | 167 Future<BuildResult> _getNextBuildResult() => |
| 170 _graph.results.elementAt(_nextBuildResult++); | 168 _barback.results.elementAt(_nextBuildResult++); |
| 171 | 169 |
| 172 /// Pauses the schedule until the currently running build completes. | 170 /// Pauses the schedule until the currently running build completes. |
| 173 /// | 171 /// |
| 174 /// Validates that the build completed successfully. | 172 /// Validates that the build completed successfully. |
| 175 void waitForBuild() { | 173 void waitForBuild() { |
| 176 schedule(() { | 174 schedule(() { |
| 177 return _graph.results.first.then((result) { | 175 return _barback.results.first.then((result) { |
| 178 expect(result.succeeded, isTrue); | 176 expect(result.succeeded, isTrue); |
| 179 }); | 177 }); |
| 180 }, "wait for build"); | 178 }, "wait for build"); |
| 181 } | 179 } |
| 182 | 180 |
| 183 /// Schedules an expectation that the graph will deliver an asset matching | 181 /// Schedules an expectation that the graph will deliver an asset matching |
| 184 /// [name] and [contents]. | 182 /// [name] and [contents]. |
| 185 /// | 183 /// |
| 186 /// If [contents] is omitted, defaults to the asset's filename without an | 184 /// If [contents] is omitted, defaults to the asset's filename without an |
| 187 /// extension (which is the same default that [initGraph] uses). | 185 /// extension (which is the same default that [initGraph] uses). |
| 188 void expectAsset(String name, [String contents]) { | 186 void expectAsset(String name, [String contents]) { |
| 189 var id = new AssetId.parse(name); | 187 var id = new AssetId.parse(name); |
| 190 | 188 |
| 191 if (contents == null) { | 189 if (contents == null) { |
| 192 contents = pathos.basenameWithoutExtension(id.path); | 190 contents = pathos.basenameWithoutExtension(id.path); |
| 193 } | 191 } |
| 194 | 192 |
| 195 schedule(() { | 193 schedule(() { |
| 196 return _graph.getAssetById(id).then((asset) { | 194 return _barback.getAssetById(id).then((asset) { |
| 197 // TODO(rnystrom): Make an actual Matcher class for this. | 195 // TODO(rnystrom): Make an actual Matcher class for this. |
| 198 expect(asset.id, equals(id)); | 196 expect(asset.id, equals(id)); |
| 199 expect(asset.readAsString(), completion(equals(contents))); | 197 expect(asset.readAsString(), completion(equals(contents))); |
| 200 }); | 198 }); |
| 201 }, "get asset $name"); | 199 }, "get asset $name"); |
| 202 } | 200 } |
| 203 | 201 |
| 204 /// Schedules an expectation that the graph will not find an asset matching | 202 /// Schedules an expectation that the graph will not find an asset matching |
| 205 /// [name]. | 203 /// [name]. |
| 206 void expectNoAsset(String name) { | 204 void expectNoAsset(String name) { |
| 207 var id = new AssetId.parse(name); | 205 var id = new AssetId.parse(name); |
| 208 | 206 |
| 209 // Make sure the future gets the error. | 207 // Make sure the future gets the error. |
| 210 schedule(() { | 208 schedule(() { |
| 211 return _graph.getAssetById(id).then((asset) { | 209 return _barback.getAssetById(id).then((asset) { |
| 212 fail("Should have thrown error but got $asset."); | 210 fail("Should have thrown error but got $asset."); |
| 213 }).catchError((error) { | 211 }).catchError((error) { |
| 214 expect(error, new isInstanceOf<AssetNotFoundException>()); | 212 expect(error, new isInstanceOf<AssetNotFoundException>()); |
| 215 expect(error.id, equals(id)); | 213 expect(error.id, equals(id)); |
| 216 }); | 214 }); |
| 217 }, "get asset $name"); | 215 }, "get asset $name"); |
| 218 } | 216 } |
| 219 | 217 |
| 220 /// Schedules an expectation that a [getAssetById] call for the given asset | 218 /// Schedules an expectation that a [getAssetById] call for the given asset |
| 221 /// won't terminate at this point in the schedule. | 219 /// won't terminate at this point in the schedule. |
| 222 void expectAssetDoesNotComplete(String name) { | 220 void expectAssetDoesNotComplete(String name) { |
| 223 var id = new AssetId.parse(name); | 221 var id = new AssetId.parse(name); |
| 224 | 222 |
| 225 schedule(() { | 223 schedule(() { |
| 226 return _futureShouldNotCompleteUntil( | 224 return _futureShouldNotCompleteUntil( |
| 227 _graph.getAssetById(id), | 225 _barback.getAssetById(id), |
| 228 pumpEventQueue(), | 226 pumpEventQueue(), |
| 229 "asset $id"); | 227 "asset $id"); |
| 230 }, "asset $id should not complete"); | 228 }, "asset $id should not complete"); |
| 231 } | 229 } |
| 232 | 230 |
| 233 /// Returns a matcher for an [AssetNotFoundException] with the given [id]. | 231 /// Returns a matcher for an [AssetNotFoundException] with the given [id]. |
| 234 Matcher isAssetNotFoundException(String name) { | 232 Matcher isAssetNotFoundException(String name) { |
| 235 var id = new AssetId.parse(name); | 233 var id = new AssetId.parse(name); |
| 236 return allOf( | 234 return allOf( |
| 237 new isInstanceOf<AssetNotFoundException>(), | 235 new isInstanceOf<AssetNotFoundException>(), |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 | 426 |
| 429 _MockAsset(this.id, this.contents); | 427 _MockAsset(this.id, this.contents); |
| 430 | 428 |
| 431 Future<String> readAsString({Encoding encoding}) => | 429 Future<String> readAsString({Encoding encoding}) => |
| 432 new Future.value(contents); | 430 new Future.value(contents); |
| 433 | 431 |
| 434 Stream<List<int>> read() => throw new UnimplementedError(); | 432 Stream<List<int>> read() => throw new UnimplementedError(); |
| 435 | 433 |
| 436 String toString() => "MockAsset $id $contents"; | 434 String toString() => "MockAsset $id $contents"; |
| 437 } | 435 } |
| OLD | NEW |