| OLD | NEW |
| (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 |
| 5 import 'dart:async'; |
| 6 |
| 7 import 'package:barback/barback.dart'; |
| 8 import 'package:barback/transformer.dart'; |
| 9 import 'package:barback/src/asset_graph.dart'; |
| 10 import 'package:scheduled_test/scheduled_test.dart'; |
| 11 |
| 12 // TODO(rnystrom): Get rid of this or find a better path for it. |
| 13 import '../../../sdk/lib/_internal/pub/test/command_line_config.dart'; |
| 14 |
| 15 var configured = false; |
| 16 void initConfig() { |
| 17 if (configured) return; |
| 18 configured = true; |
| 19 unittestConfiguration = new CommandLineConfiguration(); |
| 20 } |
| 21 |
| 22 /// Expects that [graph] will return an asset matching [name] and [contents]. |
| 23 void expectAsset(AssetGraph graph, String name, [String contents = ""]) { |
| 24 var id = AssetId.parse(name); |
| 25 schedule(() { |
| 26 return graph.getAssetById(id).then((asset) { |
| 27 // TODO(rnystrom): Make an actual Matcher class for this. |
| 28 expect(asset is MockAsset, isTrue); |
| 29 expect(asset._id.package, equals(id.package)); |
| 30 expect(asset._id.path, equals(id.path)); |
| 31 expect(asset._contents, equals(contents)); |
| 32 }); |
| 33 }, "get asset $name"); |
| 34 } |
| 35 |
| 36 /// Expects that [graph] will not find an asset matching [name]. |
| 37 void expectNoAsset(AssetGraph graph, String name) { |
| 38 var id = AssetId.parse(name); |
| 39 |
| 40 // Make sure the future gets the error. |
| 41 schedule(() { |
| 42 return graph.getAssetById(id).then((asset) { |
| 43 fail("Should have thrown error but got $asset."); |
| 44 }).catchError((error) { |
| 45 expect(error is AssetNotFoundException, isTrue); |
| 46 expect(error.id, equals(id)); |
| 47 }); |
| 48 }, "get asset $name"); |
| 49 |
| 50 // And we get it from the build results too. |
| 51 schedule(() { |
| 52 return graph.results.first.then((result) { |
| 53 expect(result.error is AssetNotFoundException, isTrue); |
| 54 expect(result.error.id, equals(id)); |
| 55 }); |
| 56 }, "get build result for error"); |
| 57 } |
| 58 |
| 59 /// Expects that [graph] will have an output file collision error on an asset |
| 60 /// matching [name]. |
| 61 Future expectCollision(AssetGraph graph, String name) { |
| 62 var id = AssetId.parse(name); |
| 63 return schedule(() { |
| 64 return graph.results.first.then((result) { |
| 65 expect(result.error is AssetCollisionException, isTrue); |
| 66 expect(result.error.id, equals(id)); |
| 67 }); |
| 68 }, "get collision on $name"); |
| 69 } |
| 70 |
| 71 /// Expects that [graph] will have an error on an asset matching [name] for |
| 72 /// missing [input]. |
| 73 Future expectMissingInput(AssetGraph graph, String name, String input) { |
| 74 var missing = AssetId.parse(input); |
| 75 |
| 76 // Make sure the future gets the error. |
| 77 schedule(() { |
| 78 return graph.getAssetById(AssetId.parse(name)).then((asset) { |
| 79 fail("Should have thrown error but got $asset."); |
| 80 }).catchError((error) { |
| 81 expect(error is MissingInputException, isTrue); |
| 82 expect(error.id, equals(missing)); |
| 83 }); |
| 84 }, "get missing input on $name"); |
| 85 |
| 86 // And we get it from the build results too. |
| 87 return schedule(() { |
| 88 return graph.results.first.then((result) { |
| 89 expect(result.error is MissingInputException, isTrue); |
| 90 expect(result.error.id, equals(missing)); |
| 91 }); |
| 92 }, "get missing input on $name"); |
| 93 } |
| 94 |
| 95 /// An [AssetProvider] that provides the given set of assets. |
| 96 class MockProvider implements AssetProvider { |
| 97 Iterable<String> get packages => _packages.keys; |
| 98 |
| 99 final _packages = new Map<String, List<MockAsset>>(); |
| 100 |
| 101 MockProvider(assets) { |
| 102 if (assets is Map) { |
| 103 assets.forEach((asset, contents) { |
| 104 var id = AssetId.parse(asset); |
| 105 var package = _packages.putIfAbsent(id.package, () => []); |
| 106 package.add(new MockAsset(id, contents)); |
| 107 }); |
| 108 } else if (assets is Iterable) { |
| 109 for (var asset in assets) { |
| 110 var id = AssetId.parse(asset); |
| 111 var package = _packages.putIfAbsent(id.package, () => []); |
| 112 package.add(new MockAsset(id, "")); |
| 113 } |
| 114 } |
| 115 } |
| 116 |
| 117 void modifyAsset(String name, String contents) { |
| 118 var id = AssetId.parse(name); |
| 119 var asset = _packages[id.package].firstWhere((a) => a._id == id); |
| 120 asset._contents = contents; |
| 121 } |
| 122 |
| 123 List<String> listFiles(String package, {String within}) { |
| 124 if (within != null) { |
| 125 throw new UnimplementedError("Doesn't handle 'within' yet."); |
| 126 } |
| 127 |
| 128 return _packages[package].map((asset) => asset.path); |
| 129 } |
| 130 |
| 131 Future<Asset> loadAsset(AssetId id) { |
| 132 return new Future(() { |
| 133 var package = _packages[id.package]; |
| 134 if (package == null) throw new AssetNotFoundException(id); |
| 135 |
| 136 return package.firstWhere((asset) => asset._id == id, |
| 137 orElse: () => throw new AssetNotFoundException(id)); |
| 138 }); |
| 139 } |
| 140 } |
| 141 |
| 142 /// A [Transformer] that takes assets ending with one extension and generates |
| 143 /// assets with a given extension. Appends the output extension to the contents |
| 144 /// of the input file. |
| 145 class RewriteTransformer extends Transformer { |
| 146 final String from; |
| 147 final String to; |
| 148 |
| 149 /// The number of times the transformer has been applied. |
| 150 int numRuns = 0; |
| 151 |
| 152 /// Creates a transformer that rewrites assets whose extension is [from] to |
| 153 /// one whose extension is [to]. |
| 154 /// |
| 155 /// [to] may be a space-separated list in which case multiple outputs will be |
| 156 /// created for each input. |
| 157 RewriteTransformer(this.from, this.to); |
| 158 |
| 159 Future<bool> isPrimary(AssetId asset) { |
| 160 return new Future.value(asset.extension == ".$from"); |
| 161 } |
| 162 |
| 163 Future apply(Transform transform) { |
| 164 numRuns++; |
| 165 return transform.primaryInput.then((input) { |
| 166 for (var extension in to.split(" ")) { |
| 167 var id = transform.primaryId.changeExtension(".$extension"); |
| 168 var content = input.readAsString() + ".$extension"; |
| 169 transform.addOutput(id, new MockAsset(id, content)); |
| 170 } |
| 171 }); |
| 172 } |
| 173 |
| 174 String toString() => "$from->$to"; |
| 175 } |
| 176 |
| 177 /// A [Transformer] that takes an input asset that contains a comma-separated |
| 178 /// list of paths and outputs a file for each path. |
| 179 class OneToManyTransformer extends Transformer { |
| 180 final String extension; |
| 181 |
| 182 /// The number of times the transformer has been applied. |
| 183 int numRuns = 0; |
| 184 |
| 185 /// Creates a transformer that consumes assets with [extension]. That file |
| 186 /// contains a comma-separated list of paths and it will output files at |
| 187 /// each of those paths. |
| 188 OneToManyTransformer(this.extension); |
| 189 |
| 190 Future<bool> isPrimary(AssetId asset) { |
| 191 return new Future.value(asset.extension == ".$extension"); |
| 192 } |
| 193 |
| 194 Future apply(Transform transform) { |
| 195 numRuns++; |
| 196 return transform.primaryInput.then((input) { |
| 197 for (var line in input.readAsString().split(",")) { |
| 198 var id = new AssetId(transform.primaryId.package, line); |
| 199 transform.addOutput(id, new MockAsset(id, "spread $extension")); |
| 200 } |
| 201 }); |
| 202 } |
| 203 |
| 204 String toString() => "1->many $extension"; |
| 205 } |
| 206 |
| 207 /// A transformer that uses the contents of a file to define the other inputs. |
| 208 /// Outputs a file with the same name as the primary but with an "out" |
| 209 /// extension containing the concatenated contents of all non-primary inputs. |
| 210 class ManyToOneTransformer extends Transformer { |
| 211 final String extension; |
| 212 |
| 213 /// Creates a transformer that consumes assets with [extension]. That file |
| 214 /// contains a comma-separated list of paths and it will input files at |
| 215 /// each of those paths. |
| 216 ManyToOneTransformer(this.extension); |
| 217 |
| 218 Future<bool> isPrimary(AssetId asset) { |
| 219 return new Future.value(asset.extension == ".$extension"); |
| 220 } |
| 221 |
| 222 Future apply(Transform transform) { |
| 223 return transform.primaryInput.then((primary) { |
| 224 // Get all of the included inputs. |
| 225 var inputs = primary.readAsString().split(",").map((path) { |
| 226 var id = new AssetId(transform.primaryId.package, path); |
| 227 return transform.getInput(id); |
| 228 }); |
| 229 |
| 230 // Concatenate them to one output. |
| 231 return Future.wait(inputs).then((inputs) { |
| 232 var id = transform.primaryId.changeExtension(".out"); |
| 233 var contents = inputs.map((input) => input.readAsString()).join(); |
| 234 transform.addOutput(id, new MockAsset(id, contents)); |
| 235 }); |
| 236 }); |
| 237 } |
| 238 |
| 239 String toString() => "many->1 $extension"; |
| 240 } |
| 241 |
| 242 /// An implementation of [Asset] that never hits the file system. |
| 243 class MockAsset implements Asset { |
| 244 final AssetId _id; |
| 245 String _contents; |
| 246 |
| 247 MockAsset(this._id, this._contents); |
| 248 |
| 249 String readAsString() => _contents; |
| 250 Stream<List<int>> read() => throw new UnimplementedError(); |
| 251 |
| 252 serialize() => throw new UnimplementedError(); |
| 253 |
| 254 String toString() => "MockAsset $_id $_contents"; |
| 255 } |
| OLD | NEW |