| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 /// This library contains tests for transformer behavior that relates to actions | 5 /// This library contains tests for transformer behavior that relates to actions |
| 6 /// happening concurrently or other complex asynchronous timing behavior. | 6 /// happening concurrently or other complex asynchronous timing behavior. |
| 7 library barback.test.package_graph.transform.concurrency_test; | 7 library barback.test.package_graph.transform.concurrency_test; |
| 8 | 8 |
| 9 import 'package:barback/src/utils.dart'; | 9 import 'package:barback/src/utils.dart'; |
| 10 import 'package:scheduled_test/scheduled_test.dart'; | 10 import 'package:scheduled_test/scheduled_test.dart'; |
| 11 | 11 |
| 12 import '../../utils.dart'; | 12 import '../../utils.dart'; |
| 13 | 13 |
| 14 main() { | 14 main() { |
| 15 initConfig(); | 15 initConfig(); |
| 16 test("runs transforms in the same phase in parallel", () { | 16 test("runs transforms in the same phase in parallel", () { |
| 17 var transformerA = new RewriteTransformer("txt", "a"); | 17 var transformerA = new RewriteTransformer("txt", "a"); |
| 18 var transformerB = new RewriteTransformer("txt", "b"); | 18 var transformerB = new RewriteTransformer("txt", "b"); |
| 19 initGraph(["app|foo.txt"], {"app": [[transformerA, transformerB]]}); | 19 initGraph([ |
| 20 "app|foo.txt" |
| 21 ], { |
| 22 "app": [ |
| 23 [transformerA, transformerB] |
| 24 ] |
| 25 }); |
| 20 | 26 |
| 21 transformerA.pauseApply(); | 27 transformerA.pauseApply(); |
| 22 transformerB.pauseApply(); | 28 transformerB.pauseApply(); |
| 23 | 29 |
| 24 updateSources(["app|foo.txt"]); | 30 updateSources(["app|foo.txt"]); |
| 25 | 31 |
| 26 transformerA.waitUntilStarted(); | 32 transformerA.waitUntilStarted(); |
| 27 transformerB.waitUntilStarted(); | 33 transformerB.waitUntilStarted(); |
| 28 | 34 |
| 29 // They should both still be running. | 35 // They should both still be running. |
| 30 expect(transformerA.isRunning, completion(isTrue)); | 36 expect(transformerA.isRunning, completion(isTrue)); |
| 31 expect(transformerB.isRunning, completion(isTrue)); | 37 expect(transformerB.isRunning, completion(isTrue)); |
| 32 | 38 |
| 33 transformerA.resumeApply(); | 39 transformerA.resumeApply(); |
| 34 transformerB.resumeApply(); | 40 transformerB.resumeApply(); |
| 35 | 41 |
| 36 expectAsset("app|foo.a", "foo.a"); | 42 expectAsset("app|foo.a", "foo.a"); |
| 37 expectAsset("app|foo.b", "foo.b"); | 43 expectAsset("app|foo.b", "foo.b"); |
| 38 buildShouldSucceed(); | 44 buildShouldSucceed(); |
| 39 }); | 45 }); |
| 40 | 46 |
| 41 test("discards outputs from a transform whose primary input is removed " | 47 test( |
| 48 "discards outputs from a transform whose primary input is removed " |
| 42 "during processing", () { | 49 "during processing", () { |
| 43 var rewrite = new RewriteTransformer("txt", "out"); | 50 var rewrite = new RewriteTransformer("txt", "out"); |
| 44 initGraph(["app|foo.txt"], {"app": [[rewrite]]}); | 51 initGraph([ |
| 52 "app|foo.txt" |
| 53 ], { |
| 54 "app": [ |
| 55 [rewrite] |
| 56 ] |
| 57 }); |
| 45 | 58 |
| 46 rewrite.pauseApply(); | 59 rewrite.pauseApply(); |
| 47 updateSources(["app|foo.txt"]); | 60 updateSources(["app|foo.txt"]); |
| 48 rewrite.waitUntilStarted(); | 61 rewrite.waitUntilStarted(); |
| 49 | 62 |
| 50 removeSources(["app|foo.txt"]); | 63 removeSources(["app|foo.txt"]); |
| 51 rewrite.resumeApply(); | 64 rewrite.resumeApply(); |
| 52 expectNoAsset("app|foo.out"); | 65 expectNoAsset("app|foo.out"); |
| 53 buildShouldSucceed(); | 66 buildShouldSucceed(); |
| 54 }); | 67 }); |
| 55 | 68 |
| 56 test("applies the correct transform if an asset is modified during isPrimary", | 69 test("applies the correct transform if an asset is modified during isPrimary", |
| 57 () { | 70 () { |
| 58 var check1 = new CheckContentTransformer("first", "#1"); | 71 var check1 = new CheckContentTransformer("first", "#1"); |
| 59 var check2 = new CheckContentTransformer("second", "#2"); | 72 var check2 = new CheckContentTransformer("second", "#2"); |
| 60 initGraph({ | 73 initGraph({ |
| 61 "app|foo.txt": "first", | 74 "app|foo.txt": "first", |
| 62 }, {"app": [[check1, check2]]}); | 75 }, { |
| 76 "app": [ |
| 77 [check1, check2] |
| 78 ] |
| 79 }); |
| 63 | 80 |
| 64 check1.pauseIsPrimary("app|foo.txt"); | 81 check1.pauseIsPrimary("app|foo.txt"); |
| 65 updateSources(["app|foo.txt"]); | 82 updateSources(["app|foo.txt"]); |
| 66 // Ensure that we're waiting on check1's isPrimary. | 83 // Ensure that we're waiting on check1's isPrimary. |
| 67 schedule(pumpEventQueue); | 84 schedule(pumpEventQueue); |
| 68 | 85 |
| 69 modifyAsset("app|foo.txt", "second"); | 86 modifyAsset("app|foo.txt", "second"); |
| 70 updateSources(["app|foo.txt"]); | 87 updateSources(["app|foo.txt"]); |
| 71 check1.resumeIsPrimary("app|foo.txt"); | 88 check1.resumeIsPrimary("app|foo.txt"); |
| 72 | 89 |
| 73 expectAsset("app|foo.txt", "second#2"); | 90 expectAsset("app|foo.txt", "second#2"); |
| 74 buildShouldSucceed(); | 91 buildShouldSucceed(); |
| 75 }); | 92 }); |
| 76 | 93 |
| 77 test("applies the correct transform if an asset is removed and added during " | 94 test( |
| 95 "applies the correct transform if an asset is removed and added during " |
| 78 "isPrimary", () { | 96 "isPrimary", () { |
| 79 var check1 = new CheckContentTransformer("first", "#1"); | 97 var check1 = new CheckContentTransformer("first", "#1"); |
| 80 var check2 = new CheckContentTransformer("second", "#2"); | 98 var check2 = new CheckContentTransformer("second", "#2"); |
| 81 initGraph({ | 99 initGraph({ |
| 82 "app|foo.txt": "first", | 100 "app|foo.txt": "first", |
| 83 }, {"app": [[check1, check2]]}); | 101 }, { |
| 102 "app": [ |
| 103 [check1, check2] |
| 104 ] |
| 105 }); |
| 84 | 106 |
| 85 check1.pauseIsPrimary("app|foo.txt"); | 107 check1.pauseIsPrimary("app|foo.txt"); |
| 86 updateSources(["app|foo.txt"]); | 108 updateSources(["app|foo.txt"]); |
| 87 // Ensure that we're waiting on check1's isPrimary. | 109 // Ensure that we're waiting on check1's isPrimary. |
| 88 schedule(pumpEventQueue); | 110 schedule(pumpEventQueue); |
| 89 | 111 |
| 90 removeSources(["app|foo.txt"]); | 112 removeSources(["app|foo.txt"]); |
| 91 modifyAsset("app|foo.txt", "second"); | 113 modifyAsset("app|foo.txt", "second"); |
| 92 updateSources(["app|foo.txt"]); | 114 updateSources(["app|foo.txt"]); |
| 93 check1.resumeIsPrimary("app|foo.txt"); | 115 check1.resumeIsPrimary("app|foo.txt"); |
| 94 | 116 |
| 95 expectAsset("app|foo.txt", "second#2"); | 117 expectAsset("app|foo.txt", "second#2"); |
| 96 buildShouldSucceed(); | 118 buildShouldSucceed(); |
| 97 }); | 119 }); |
| 98 | 120 |
| 99 test("restarts processing if a change occurs during processing", () { | 121 test("restarts processing if a change occurs during processing", () { |
| 100 var transformer = new RewriteTransformer("txt", "out"); | 122 var transformer = new RewriteTransformer("txt", "out"); |
| 101 initGraph(["app|foo.txt"], {"app": [[transformer]]}); | 123 initGraph([ |
| 124 "app|foo.txt" |
| 125 ], { |
| 126 "app": [ |
| 127 [transformer] |
| 128 ] |
| 129 }); |
| 102 | 130 |
| 103 transformer.pauseApply(); | 131 transformer.pauseApply(); |
| 104 | 132 |
| 105 updateSources(["app|foo.txt"]); | 133 updateSources(["app|foo.txt"]); |
| 106 transformer.waitUntilStarted(); | 134 transformer.waitUntilStarted(); |
| 107 | 135 |
| 108 // Now update the graph during it. | 136 // Now update the graph during it. |
| 109 updateSources(["app|foo.txt"]); | 137 updateSources(["app|foo.txt"]); |
| 110 transformer.resumeApply(); | 138 transformer.resumeApply(); |
| 111 | 139 |
| 112 expectAsset("app|foo.out", "foo.out"); | 140 expectAsset("app|foo.out", "foo.out"); |
| 113 buildShouldSucceed(); | 141 buildShouldSucceed(); |
| 114 | 142 |
| 115 expect(transformer.numRuns, completion(equals(2))); | 143 expect(transformer.numRuns, completion(equals(2))); |
| 116 }); | 144 }); |
| 117 | 145 |
| 118 test("aborts processing if the primary input is removed during processing", | 146 test("aborts processing if the primary input is removed during processing", |
| 119 () { | 147 () { |
| 120 var transformer = new RewriteTransformer("txt", "out"); | 148 var transformer = new RewriteTransformer("txt", "out"); |
| 121 initGraph(["app|foo.txt"], {"app": [[transformer]]}); | 149 initGraph([ |
| 150 "app|foo.txt" |
| 151 ], { |
| 152 "app": [ |
| 153 [transformer] |
| 154 ] |
| 155 }); |
| 122 | 156 |
| 123 transformer.pauseApply(); | 157 transformer.pauseApply(); |
| 124 | 158 |
| 125 updateSources(["app|foo.txt"]); | 159 updateSources(["app|foo.txt"]); |
| 126 transformer.waitUntilStarted(); | 160 transformer.waitUntilStarted(); |
| 127 | 161 |
| 128 // Now remove its primary input while it's running. | 162 // Now remove its primary input while it's running. |
| 129 removeSources(["app|foo.txt"]); | 163 removeSources(["app|foo.txt"]); |
| 130 transformer.resumeApply(); | 164 transformer.resumeApply(); |
| 131 | 165 |
| 132 expectNoAsset("app|foo.out"); | 166 expectNoAsset("app|foo.out"); |
| 133 buildShouldSucceed(); | 167 buildShouldSucceed(); |
| 134 | 168 |
| 135 expect(transformer.numRuns, completion(equals(1))); | 169 expect(transformer.numRuns, completion(equals(1))); |
| 136 }); | 170 }); |
| 137 | 171 |
| 138 test("restarts processing if a change to a new secondary input occurs during " | 172 test( |
| 173 "restarts processing if a change to a new secondary input occurs during " |
| 139 "processing", () { | 174 "processing", () { |
| 140 var transformer = new ManyToOneTransformer("txt"); | 175 var transformer = new ManyToOneTransformer("txt"); |
| 141 initGraph({ | 176 initGraph({ |
| 142 "app|foo.txt": "bar.inc", | 177 "app|foo.txt": "bar.inc", |
| 143 "app|bar.inc": "bar" | 178 "app|bar.inc": "bar" |
| 144 }, {"app": [[transformer]]}); | 179 }, { |
| 180 "app": [ |
| 181 [transformer] |
| 182 ] |
| 183 }); |
| 145 | 184 |
| 146 transformer.pauseApply(); | 185 transformer.pauseApply(); |
| 147 | 186 |
| 148 updateSources(["app|foo.txt", "app|bar.inc"]); | 187 updateSources(["app|foo.txt", "app|bar.inc"]); |
| 149 transformer.waitUntilStarted(); | 188 transformer.waitUntilStarted(); |
| 150 | 189 |
| 151 // Give the transform time to load bar.inc the first time. | 190 // Give the transform time to load bar.inc the first time. |
| 152 schedule(pumpEventQueue); | 191 schedule(pumpEventQueue); |
| 153 | 192 |
| 154 // Now update the secondary input before the transform finishes. | 193 // Now update the secondary input before the transform finishes. |
| 155 modifyAsset("app|bar.inc", "baz"); | 194 modifyAsset("app|bar.inc", "baz"); |
| 156 updateSources(["app|bar.inc"]); | 195 updateSources(["app|bar.inc"]); |
| 157 // Give bar.inc enough time to be loaded and marked available before the | 196 // Give bar.inc enough time to be loaded and marked available before the |
| 158 // transformer completes. | 197 // transformer completes. |
| 159 schedule(pumpEventQueue); | 198 schedule(pumpEventQueue); |
| 160 | 199 |
| 161 transformer.resumeApply(); | 200 transformer.resumeApply(); |
| 162 | 201 |
| 163 expectAsset("app|foo.out", "baz"); | 202 expectAsset("app|foo.out", "baz"); |
| 164 buildShouldSucceed(); | 203 buildShouldSucceed(); |
| 165 | 204 |
| 166 expect(transformer.numRuns, completion(equals(2))); | 205 expect(transformer.numRuns, completion(equals(2))); |
| 167 }); | 206 }); |
| 168 | 207 |
| 169 test("doesn't restart processing if a change to an old secondary input " | 208 test( |
| 209 "doesn't restart processing if a change to an old secondary input " |
| 170 "occurs during processing", () { | 210 "occurs during processing", () { |
| 171 var transformer = new ManyToOneTransformer("txt"); | 211 var transformer = new ManyToOneTransformer("txt"); |
| 172 initGraph({ | 212 initGraph({ |
| 173 "app|foo.txt": "bar.inc", | 213 "app|foo.txt": "bar.inc", |
| 174 "app|bar.inc": "bar", | 214 "app|bar.inc": "bar", |
| 175 "app|baz.inc": "baz" | 215 "app|baz.inc": "baz" |
| 176 }, {"app": [[transformer]]}); | 216 }, { |
| 217 "app": [ |
| 218 [transformer] |
| 219 ] |
| 220 }); |
| 177 | 221 |
| 178 updateSources(["app|foo.txt", "app|bar.inc", "app|baz.inc"]); | 222 updateSources(["app|foo.txt", "app|bar.inc", "app|baz.inc"]); |
| 179 expectAsset("app|foo.out", "bar"); | 223 expectAsset("app|foo.out", "bar"); |
| 180 buildShouldSucceed(); | 224 buildShouldSucceed(); |
| 181 | 225 |
| 182 transformer.pauseApply(); | 226 transformer.pauseApply(); |
| 183 modifyAsset("app|foo.txt", "baz.inc"); | 227 modifyAsset("app|foo.txt", "baz.inc"); |
| 184 updateSources(["app|foo.txt"]); | 228 updateSources(["app|foo.txt"]); |
| 185 transformer.waitUntilStarted(); | 229 transformer.waitUntilStarted(); |
| 186 | 230 |
| 187 // Now update the old secondary input before the transform finishes. | 231 // Now update the old secondary input before the transform finishes. |
| 188 modifyAsset("app|bar.inc", "new bar"); | 232 modifyAsset("app|bar.inc", "new bar"); |
| 189 updateSources(["app|bar.inc"]); | 233 updateSources(["app|bar.inc"]); |
| 190 // Give bar.inc enough time to be loaded and marked available before the | 234 // Give bar.inc enough time to be loaded and marked available before the |
| 191 // transformer completes. | 235 // transformer completes. |
| 192 schedule(pumpEventQueue); | 236 schedule(pumpEventQueue); |
| 193 | 237 |
| 194 transformer.resumeApply(); | 238 transformer.resumeApply(); |
| 195 expectAsset("app|foo.out", "baz"); | 239 expectAsset("app|foo.out", "baz"); |
| 196 buildShouldSucceed(); | 240 buildShouldSucceed(); |
| 197 | 241 |
| 198 // Should have run once the first time, then again when switching to | 242 // Should have run once the first time, then again when switching to |
| 199 // baz.inc. Should not run a third time because of bar.inc being modified. | 243 // baz.inc. Should not run a third time because of bar.inc being modified. |
| 200 expect(transformer.numRuns, completion(equals(2))); | 244 expect(transformer.numRuns, completion(equals(2))); |
| 201 }); | 245 }); |
| 202 | 246 |
| 203 test("restarts before finishing later phases when a change occurs", () { | 247 test("restarts before finishing later phases when a change occurs", () { |
| 204 var txtToInt = new RewriteTransformer("txt", "int"); | 248 var txtToInt = new RewriteTransformer("txt", "int"); |
| 205 var intToOut = new RewriteTransformer("int", "out"); | 249 var intToOut = new RewriteTransformer("int", "out"); |
| 206 initGraph(["app|foo.txt", "app|bar.txt"], | 250 initGraph([ |
| 207 {"app": [[txtToInt], [intToOut]]}); | 251 "app|foo.txt", |
| 252 "app|bar.txt" |
| 253 ], { |
| 254 "app": [ |
| 255 [txtToInt], |
| 256 [intToOut] |
| 257 ] |
| 258 }); |
| 208 | 259 |
| 209 txtToInt.pauseApply(); | 260 txtToInt.pauseApply(); |
| 210 | 261 |
| 211 updateSources(["app|foo.txt"]); | 262 updateSources(["app|foo.txt"]); |
| 212 txtToInt.waitUntilStarted(); | 263 txtToInt.waitUntilStarted(); |
| 213 | 264 |
| 214 // Now update the graph during it. | 265 // Now update the graph during it. |
| 215 updateSources(["app|bar.txt"]); | 266 updateSources(["app|bar.txt"]); |
| 216 txtToInt.resumeApply(); | 267 txtToInt.resumeApply(); |
| 217 | 268 |
| 218 expectAsset("app|foo.out", "foo.int.out"); | 269 expectAsset("app|foo.out", "foo.int.out"); |
| 219 expectAsset("app|bar.out", "bar.int.out"); | 270 expectAsset("app|bar.out", "bar.int.out"); |
| 220 buildShouldSucceed(); | 271 buildShouldSucceed(); |
| 221 | 272 |
| 222 // Should only have run each transform once for each primary. | 273 // Should only have run each transform once for each primary. |
| 223 expect(txtToInt.numRuns, completion(equals(2))); | 274 expect(txtToInt.numRuns, completion(equals(2))); |
| 224 expect(intToOut.numRuns, completion(equals(2))); | 275 expect(intToOut.numRuns, completion(equals(2))); |
| 225 }); | 276 }); |
| 226 | 277 |
| 227 test("doesn't return an asset until it's finished rebuilding", () { | 278 test("doesn't return an asset until it's finished rebuilding", () { |
| 228 initGraph(["app|foo.in"], {"app": [ | 279 initGraph([ |
| 229 [new RewriteTransformer("in", "mid")], | 280 "app|foo.in" |
| 230 [new RewriteTransformer("mid", "out")] | 281 ], { |
| 231 ]}); | 282 "app": [ |
| 283 [new RewriteTransformer("in", "mid")], |
| 284 [new RewriteTransformer("mid", "out")] |
| 285 ] |
| 286 }); |
| 232 | 287 |
| 233 updateSources(["app|foo.in"]); | 288 updateSources(["app|foo.in"]); |
| 234 expectAsset("app|foo.out", "foo.mid.out"); | 289 expectAsset("app|foo.out", "foo.mid.out"); |
| 235 buildShouldSucceed(); | 290 buildShouldSucceed(); |
| 236 | 291 |
| 237 pauseProvider(); | 292 pauseProvider(); |
| 238 modifyAsset("app|foo.in", "new"); | 293 modifyAsset("app|foo.in", "new"); |
| 239 updateSources(["app|foo.in"]); | 294 updateSources(["app|foo.in"]); |
| 240 expectAssetDoesNotComplete("app|foo.out"); | 295 expectAssetDoesNotComplete("app|foo.out"); |
| 241 buildShouldNotBeDone(); | 296 buildShouldNotBeDone(); |
| 242 | 297 |
| 243 resumeProvider(); | 298 resumeProvider(); |
| 244 expectAsset("app|foo.out", "new.mid.out"); | 299 expectAsset("app|foo.out", "new.mid.out"); |
| 245 buildShouldSucceed(); | 300 buildShouldSucceed(); |
| 246 }); | 301 }); |
| 247 | 302 |
| 248 test("doesn't return an asset until its in-place transform is done", () { | 303 test("doesn't return an asset until its in-place transform is done", () { |
| 249 var rewrite = new RewriteTransformer("txt", "txt"); | 304 var rewrite = new RewriteTransformer("txt", "txt"); |
| 250 initGraph(["app|foo.txt"], {"app": [[rewrite]]}); | 305 initGraph([ |
| 306 "app|foo.txt" |
| 307 ], { |
| 308 "app": [ |
| 309 [rewrite] |
| 310 ] |
| 311 }); |
| 251 | 312 |
| 252 rewrite.pauseApply(); | 313 rewrite.pauseApply(); |
| 253 updateSources(["app|foo.txt"]); | 314 updateSources(["app|foo.txt"]); |
| 254 expectAssetDoesNotComplete("app|foo.txt"); | 315 expectAssetDoesNotComplete("app|foo.txt"); |
| 255 | 316 |
| 256 rewrite.resumeApply(); | 317 rewrite.resumeApply(); |
| 257 expectAsset("app|foo.txt", "foo.txt"); | 318 expectAsset("app|foo.txt", "foo.txt"); |
| 258 buildShouldSucceed(); | 319 buildShouldSucceed(); |
| 259 }); | 320 }); |
| 260 | 321 |
| 261 test("doesn't return an asset that's removed during isPrimary", () { | 322 test("doesn't return an asset that's removed during isPrimary", () { |
| 262 var rewrite = new RewriteTransformer("txt", "txt"); | 323 var rewrite = new RewriteTransformer("txt", "txt"); |
| 263 initGraph(["app|foo.txt"], {"app": [[rewrite]]}); | 324 initGraph([ |
| 325 "app|foo.txt" |
| 326 ], { |
| 327 "app": [ |
| 328 [rewrite] |
| 329 ] |
| 330 }); |
| 264 | 331 |
| 265 rewrite.pauseIsPrimary("app|foo.txt"); | 332 rewrite.pauseIsPrimary("app|foo.txt"); |
| 266 updateSources(["app|foo.txt"]); | 333 updateSources(["app|foo.txt"]); |
| 267 // Make sure we're waiting on isPrimary. | 334 // Make sure we're waiting on isPrimary. |
| 268 schedule(pumpEventQueue); | 335 schedule(pumpEventQueue); |
| 269 | 336 |
| 270 removeSources(["app|foo.txt"]); | 337 removeSources(["app|foo.txt"]); |
| 271 rewrite.resumeIsPrimary("app|foo.txt"); | 338 rewrite.resumeIsPrimary("app|foo.txt"); |
| 272 expectNoAsset("app|foo.txt"); | 339 expectNoAsset("app|foo.txt"); |
| 273 buildShouldSucceed(); | 340 buildShouldSucceed(); |
| 274 }); | 341 }); |
| 275 | 342 |
| 276 test("doesn't transform an asset that goes from primary to non-primary " | 343 test( |
| 344 "doesn't transform an asset that goes from primary to non-primary " |
| 277 "during isPrimary", () { | 345 "during isPrimary", () { |
| 278 var check = new CheckContentTransformer(new RegExp(r"^do$"), "ne"); | 346 var check = new CheckContentTransformer(new RegExp(r"^do$"), "ne"); |
| 279 initGraph({ | 347 initGraph({ |
| 280 "app|foo.txt": "do" | 348 "app|foo.txt": "do" |
| 281 }, {"app": [[check]]}); | 349 }, { |
| 350 "app": [ |
| 351 [check] |
| 352 ] |
| 353 }); |
| 282 | 354 |
| 283 check.pauseIsPrimary("app|foo.txt"); | 355 check.pauseIsPrimary("app|foo.txt"); |
| 284 updateSources(["app|foo.txt"]); | 356 updateSources(["app|foo.txt"]); |
| 285 // Make sure we're waiting on isPrimary. | 357 // Make sure we're waiting on isPrimary. |
| 286 schedule(pumpEventQueue); | 358 schedule(pumpEventQueue); |
| 287 | 359 |
| 288 modifyAsset("app|foo.txt", "don't"); | 360 modifyAsset("app|foo.txt", "don't"); |
| 289 updateSources(["app|foo.txt"]); | 361 updateSources(["app|foo.txt"]); |
| 290 check.resumeIsPrimary("app|foo.txt"); | 362 check.resumeIsPrimary("app|foo.txt"); |
| 291 | 363 |
| 292 expectAsset("app|foo.txt", "don't"); | 364 expectAsset("app|foo.txt", "don't"); |
| 293 buildShouldSucceed(); | 365 buildShouldSucceed(); |
| 294 }); | 366 }); |
| 295 | 367 |
| 296 test("transforms an asset that goes from non-primary to primary " | 368 test( |
| 369 "transforms an asset that goes from non-primary to primary " |
| 297 "during isPrimary", () { | 370 "during isPrimary", () { |
| 298 var check = new CheckContentTransformer("do", "ne"); | 371 var check = new CheckContentTransformer("do", "ne"); |
| 299 initGraph({ | 372 initGraph({ |
| 300 "app|foo.txt": "don't" | 373 "app|foo.txt": "don't" |
| 301 }, {"app": [[check]]}); | 374 }, { |
| 375 "app": [ |
| 376 [check] |
| 377 ] |
| 378 }); |
| 302 | 379 |
| 303 check.pauseIsPrimary("app|foo.txt"); | 380 check.pauseIsPrimary("app|foo.txt"); |
| 304 updateSources(["app|foo.txt"]); | 381 updateSources(["app|foo.txt"]); |
| 305 // Make sure we're waiting on isPrimary. | 382 // Make sure we're waiting on isPrimary. |
| 306 schedule(pumpEventQueue); | 383 schedule(pumpEventQueue); |
| 307 | 384 |
| 308 modifyAsset("app|foo.txt", "do"); | 385 modifyAsset("app|foo.txt", "do"); |
| 309 updateSources(["app|foo.txt"]); | 386 updateSources(["app|foo.txt"]); |
| 310 check.resumeIsPrimary("app|foo.txt"); | 387 check.resumeIsPrimary("app|foo.txt"); |
| 311 | 388 |
| 312 expectAsset("app|foo.txt", "done"); | 389 expectAsset("app|foo.txt", "done"); |
| 313 buildShouldSucceed(); | 390 buildShouldSucceed(); |
| 314 }); | 391 }); |
| 315 | 392 |
| 316 test("doesn't return an asset that's removed during another transformer's " | 393 test( |
| 394 "doesn't return an asset that's removed during another transformer's " |
| 317 "isPrimary", () { | 395 "isPrimary", () { |
| 318 var rewrite1 = new RewriteTransformer("txt", "txt"); | 396 var rewrite1 = new RewriteTransformer("txt", "txt"); |
| 319 var rewrite2 = new RewriteTransformer("md", "md"); | 397 var rewrite2 = new RewriteTransformer("md", "md"); |
| 320 initGraph(["app|foo.txt", "app|foo.md"], {"app": [[rewrite1, rewrite2]]}); | 398 initGraph([ |
| 399 "app|foo.txt", |
| 400 "app|foo.md" |
| 401 ], { |
| 402 "app": [ |
| 403 [rewrite1, rewrite2] |
| 404 ] |
| 405 }); |
| 321 | 406 |
| 322 rewrite2.pauseIsPrimary("app|foo.md"); | 407 rewrite2.pauseIsPrimary("app|foo.md"); |
| 323 updateSources(["app|foo.txt", "app|foo.md"]); | 408 updateSources(["app|foo.txt", "app|foo.md"]); |
| 324 // Make sure we're waiting on the correct isPrimary. | 409 // Make sure we're waiting on the correct isPrimary. |
| 325 schedule(pumpEventQueue); | 410 schedule(pumpEventQueue); |
| 326 | 411 |
| 327 removeSources(["app|foo.txt"]); | 412 removeSources(["app|foo.txt"]); |
| 328 rewrite2.resumeIsPrimary("app|foo.md"); | 413 rewrite2.resumeIsPrimary("app|foo.md"); |
| 329 expectNoAsset("app|foo.txt"); | 414 expectNoAsset("app|foo.txt"); |
| 330 expectAsset("app|foo.md", "foo.md"); | 415 expectAsset("app|foo.md", "foo.md"); |
| 331 buildShouldSucceed(); | 416 buildShouldSucceed(); |
| 332 }); | 417 }); |
| 333 | 418 |
| 334 test("doesn't transform an asset that goes from primary to non-primary " | 419 test( |
| 420 "doesn't transform an asset that goes from primary to non-primary " |
| 335 "during another transformer's isPrimary", () { | 421 "during another transformer's isPrimary", () { |
| 336 var rewrite = new RewriteTransformer("md", "md"); | 422 var rewrite = new RewriteTransformer("md", "md"); |
| 337 var check = new CheckContentTransformer(new RegExp(r"^do$"), "ne"); | 423 var check = new CheckContentTransformer(new RegExp(r"^do$"), "ne"); |
| 338 initGraph({ | 424 initGraph({ |
| 339 "app|foo.txt": "do", | 425 "app|foo.txt": "do", |
| 340 "app|foo.md": "foo" | 426 "app|foo.md": "foo" |
| 341 }, {"app": [[rewrite, check]]}); | 427 }, { |
| 428 "app": [ |
| 429 [rewrite, check] |
| 430 ] |
| 431 }); |
| 342 | 432 |
| 343 rewrite.pauseIsPrimary("app|foo.md"); | 433 rewrite.pauseIsPrimary("app|foo.md"); |
| 344 updateSources(["app|foo.txt", "app|foo.md"]); | 434 updateSources(["app|foo.txt", "app|foo.md"]); |
| 345 // Make sure we're waiting on the correct isPrimary. | 435 // Make sure we're waiting on the correct isPrimary. |
| 346 schedule(pumpEventQueue); | 436 schedule(pumpEventQueue); |
| 347 | 437 |
| 348 modifyAsset("app|foo.txt", "don't"); | 438 modifyAsset("app|foo.txt", "don't"); |
| 349 updateSources(["app|foo.txt"]); | 439 updateSources(["app|foo.txt"]); |
| 350 rewrite.resumeIsPrimary("app|foo.md"); | 440 rewrite.resumeIsPrimary("app|foo.md"); |
| 351 | 441 |
| 352 expectAsset("app|foo.txt", "don't"); | 442 expectAsset("app|foo.txt", "don't"); |
| 353 expectAsset("app|foo.md", "foo.md"); | 443 expectAsset("app|foo.md", "foo.md"); |
| 354 buildShouldSucceed(); | 444 buildShouldSucceed(); |
| 355 }); | 445 }); |
| 356 | 446 |
| 357 test("transforms an asset that goes from non-primary to primary " | 447 test( |
| 448 "transforms an asset that goes from non-primary to primary " |
| 358 "during another transformer's isPrimary", () { | 449 "during another transformer's isPrimary", () { |
| 359 var rewrite = new RewriteTransformer("md", "md"); | 450 var rewrite = new RewriteTransformer("md", "md"); |
| 360 var check = new CheckContentTransformer("do", "ne"); | 451 var check = new CheckContentTransformer("do", "ne"); |
| 361 initGraph({ | 452 initGraph({ |
| 362 "app|foo.txt": "don't", | 453 "app|foo.txt": "don't", |
| 363 "app|foo.md": "foo" | 454 "app|foo.md": "foo" |
| 364 }, {"app": [[rewrite, check]]}); | 455 }, { |
| 456 "app": [ |
| 457 [rewrite, check] |
| 458 ] |
| 459 }); |
| 365 | 460 |
| 366 rewrite.pauseIsPrimary("app|foo.md"); | 461 rewrite.pauseIsPrimary("app|foo.md"); |
| 367 updateSources(["app|foo.txt", "app|foo.md"]); | 462 updateSources(["app|foo.txt", "app|foo.md"]); |
| 368 // Make sure we're waiting on the correct isPrimary. | 463 // Make sure we're waiting on the correct isPrimary. |
| 369 schedule(pumpEventQueue); | 464 schedule(pumpEventQueue); |
| 370 | 465 |
| 371 modifyAsset("app|foo.txt", "do"); | 466 modifyAsset("app|foo.txt", "do"); |
| 372 updateSources(["app|foo.txt"]); | 467 updateSources(["app|foo.txt"]); |
| 373 rewrite.resumeIsPrimary("app|foo.md"); | 468 rewrite.resumeIsPrimary("app|foo.md"); |
| 374 | 469 |
| 375 expectAsset("app|foo.txt", "done"); | 470 expectAsset("app|foo.txt", "done"); |
| 376 expectAsset("app|foo.md", "foo.md"); | 471 expectAsset("app|foo.md", "foo.md"); |
| 377 buildShouldSucceed(); | 472 buildShouldSucceed(); |
| 378 }); | 473 }); |
| 379 | 474 |
| 380 test("returns an asset even if an unrelated build is running", () { | 475 test("returns an asset even if an unrelated build is running", () { |
| 381 initGraph([ | 476 initGraph([ |
| 382 "app|foo.in", | 477 "app|foo.in", |
| 383 "app|bar.in", | 478 "app|bar.in", |
| 384 ], {"app": [[new RewriteTransformer("in", "out")]]}); | 479 ], { |
| 480 "app": [ |
| 481 [new RewriteTransformer("in", "out")] |
| 482 ] |
| 483 }); |
| 385 | 484 |
| 386 updateSources(["app|foo.in", "app|bar.in"]); | 485 updateSources(["app|foo.in", "app|bar.in"]); |
| 387 expectAsset("app|foo.out", "foo.out"); | 486 expectAsset("app|foo.out", "foo.out"); |
| 388 expectAsset("app|bar.out", "bar.out"); | 487 expectAsset("app|bar.out", "bar.out"); |
| 389 buildShouldSucceed(); | 488 buildShouldSucceed(); |
| 390 | 489 |
| 391 pauseProvider(); | 490 pauseProvider(); |
| 392 modifyAsset("app|foo.in", "new"); | 491 modifyAsset("app|foo.in", "new"); |
| 393 updateSources(["app|foo.in"]); | 492 updateSources(["app|foo.in"]); |
| 394 expectAssetDoesNotComplete("app|foo.out"); | 493 expectAssetDoesNotComplete("app|foo.out"); |
| 395 expectAsset("app|bar.out", "bar.out"); | 494 expectAsset("app|bar.out", "bar.out"); |
| 396 buildShouldNotBeDone(); | 495 buildShouldNotBeDone(); |
| 397 | 496 |
| 398 resumeProvider(); | 497 resumeProvider(); |
| 399 expectAsset("app|foo.out", "new.out"); | 498 expectAsset("app|foo.out", "new.out"); |
| 400 buildShouldSucceed(); | 499 buildShouldSucceed(); |
| 401 }); | 500 }); |
| 402 | 501 |
| 403 test("doesn't report AssetNotFound until all builds are finished", () { | 502 test("doesn't report AssetNotFound until all builds are finished", () { |
| 404 initGraph([ | 503 initGraph([ |
| 405 "app|foo.in", | 504 "app|foo.in", |
| 406 ], {"app": [[new RewriteTransformer("in", "out")]]}); | 505 ], { |
| 506 "app": [ |
| 507 [new RewriteTransformer("in", "out")] |
| 508 ] |
| 509 }); |
| 407 | 510 |
| 408 updateSources(["app|foo.in"]); | 511 updateSources(["app|foo.in"]); |
| 409 expectAsset("app|foo.out", "foo.out"); | 512 expectAsset("app|foo.out", "foo.out"); |
| 410 buildShouldSucceed(); | 513 buildShouldSucceed(); |
| 411 | 514 |
| 412 pauseProvider(); | 515 pauseProvider(); |
| 413 updateSources(["app|foo.in"]); | 516 updateSources(["app|foo.in"]); |
| 414 expectAssetDoesNotComplete("app|foo.out"); | 517 expectAssetDoesNotComplete("app|foo.out"); |
| 415 expectAssetDoesNotComplete("app|non-existent.out"); | 518 expectAssetDoesNotComplete("app|non-existent.out"); |
| 416 buildShouldNotBeDone(); | 519 buildShouldNotBeDone(); |
| 417 | 520 |
| 418 resumeProvider(); | 521 resumeProvider(); |
| 419 expectAsset("app|foo.out", "foo.out"); | 522 expectAsset("app|foo.out", "foo.out"); |
| 420 expectNoAsset("app|non-existent.out"); | 523 expectNoAsset("app|non-existent.out"); |
| 421 buildShouldSucceed(); | 524 buildShouldSucceed(); |
| 422 }); | 525 }); |
| 423 | 526 |
| 424 test("doesn't emit a result until all builds are finished", () { | 527 test("doesn't emit a result until all builds are finished", () { |
| 425 var rewrite = new RewriteTransformer("txt", "out"); | 528 var rewrite = new RewriteTransformer("txt", "out"); |
| 426 initGraph([ | 529 initGraph([ |
| 427 "pkg1|foo.txt", | 530 "pkg1|foo.txt", |
| 428 "pkg2|foo.txt" | 531 "pkg2|foo.txt" |
| 429 ], {"pkg1": [[rewrite]], "pkg2": [[rewrite]]}); | 532 ], { |
| 533 "pkg1": [ |
| 534 [rewrite] |
| 535 ], |
| 536 "pkg2": [ |
| 537 [rewrite] |
| 538 ] |
| 539 }); |
| 430 | 540 |
| 431 // First, run both packages' transformers so both packages are successful. | 541 // First, run both packages' transformers so both packages are successful. |
| 432 updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]); | 542 updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]); |
| 433 expectAsset("pkg1|foo.out", "foo.out"); | 543 expectAsset("pkg1|foo.out", "foo.out"); |
| 434 expectAsset("pkg2|foo.out", "foo.out"); | 544 expectAsset("pkg2|foo.out", "foo.out"); |
| 435 buildShouldSucceed(); | 545 buildShouldSucceed(); |
| 436 | 546 |
| 437 // pkg1 is still successful, but pkg2 is waiting on the provider, so the | 547 // pkg1 is still successful, but pkg2 is waiting on the provider, so the |
| 438 // overall build shouldn't finish. | 548 // overall build shouldn't finish. |
| 439 pauseProvider(); | 549 pauseProvider(); |
| 440 updateSources(["pkg2|foo.txt"]); | 550 updateSources(["pkg2|foo.txt"]); |
| 441 expectAsset("pkg1|foo.out", "foo.out"); | 551 expectAsset("pkg1|foo.out", "foo.out"); |
| 442 buildShouldNotBeDone(); | 552 buildShouldNotBeDone(); |
| 443 | 553 |
| 444 // Now that the provider is unpaused, pkg2's transforms finish and the | 554 // Now that the provider is unpaused, pkg2's transforms finish and the |
| 445 // overall build succeeds. | 555 // overall build succeeds. |
| 446 resumeProvider(); | 556 resumeProvider(); |
| 447 buildShouldSucceed(); | 557 buildShouldSucceed(); |
| 448 }); | 558 }); |
| 449 | 559 |
| 450 test("one transformer takes a long time while the other finishes, then " | 560 test( |
| 561 "one transformer takes a long time while the other finishes, then " |
| 451 "the input is removed", () { | 562 "the input is removed", () { |
| 452 var rewrite1 = new RewriteTransformer("txt", "out1"); | 563 var rewrite1 = new RewriteTransformer("txt", "out1"); |
| 453 var rewrite2 = new RewriteTransformer("txt", "out2"); | 564 var rewrite2 = new RewriteTransformer("txt", "out2"); |
| 454 initGraph(["app|foo.txt"], {"app": [[rewrite1, rewrite2]]}); | 565 initGraph([ |
| 566 "app|foo.txt" |
| 567 ], { |
| 568 "app": [ |
| 569 [rewrite1, rewrite2] |
| 570 ] |
| 571 }); |
| 455 | 572 |
| 456 rewrite1.pauseApply(); | 573 rewrite1.pauseApply(); |
| 457 | 574 |
| 458 updateSources(["app|foo.txt"]); | 575 updateSources(["app|foo.txt"]); |
| 459 | 576 |
| 460 // Wait for rewrite1 to pause and rewrite2 to finish. | 577 // Wait for rewrite1 to pause and rewrite2 to finish. |
| 461 schedule(pumpEventQueue); | 578 schedule(pumpEventQueue); |
| 462 | 579 |
| 463 removeSources(["app|foo.txt"]); | 580 removeSources(["app|foo.txt"]); |
| 464 | 581 |
| 465 // Make sure the removal is processed completely before we restart rewrite2. | 582 // Make sure the removal is processed completely before we restart rewrite2. |
| 466 schedule(pumpEventQueue); | 583 schedule(pumpEventQueue); |
| 467 rewrite1.resumeApply(); | 584 rewrite1.resumeApply(); |
| 468 | 585 |
| 469 buildShouldSucceed(); | 586 buildShouldSucceed(); |
| 470 expectNoAsset("app|foo.out1"); | 587 expectNoAsset("app|foo.out1"); |
| 471 expectNoAsset("app|foo.out2"); | 588 expectNoAsset("app|foo.out2"); |
| 472 }); | 589 }); |
| 473 | 590 |
| 474 test("a transformer in a later phase gets a slow secondary input from an " | 591 test( |
| 592 "a transformer in a later phase gets a slow secondary input from an " |
| 475 "earlier phase", () { | 593 "earlier phase", () { |
| 476 var rewrite = new RewriteTransformer("in", "in"); | 594 var rewrite = new RewriteTransformer("in", "in"); |
| 477 initGraph({ | 595 initGraph({ |
| 478 "app|foo.in": "foo", | 596 "app|foo.in": "foo", |
| 479 "app|bar.txt": "foo.in" | 597 "app|bar.txt": "foo.in" |
| 480 }, {"app": [ | 598 }, { |
| 481 [rewrite], | 599 "app": [ |
| 482 [new ManyToOneTransformer("txt")] | 600 [rewrite], |
| 483 ]}); | 601 [new ManyToOneTransformer("txt")] |
| 602 ] |
| 603 }); |
| 484 | 604 |
| 485 rewrite.pauseApply(); | 605 rewrite.pauseApply(); |
| 486 updateSources(["app|foo.in", "app|bar.txt"]); | 606 updateSources(["app|foo.in", "app|bar.txt"]); |
| 487 expectAssetDoesNotComplete("app|bar.out"); | 607 expectAssetDoesNotComplete("app|bar.out"); |
| 488 | 608 |
| 489 rewrite.resumeApply(); | 609 rewrite.resumeApply(); |
| 490 expectAsset("app|bar.out", "foo.in"); | 610 expectAsset("app|bar.out", "foo.in"); |
| 491 buildShouldSucceed(); | 611 buildShouldSucceed(); |
| 492 }); | 612 }); |
| 493 | 613 |
| 494 test("materializes a passed-through asset that was emitted before it was " | 614 test( |
| 615 "materializes a passed-through asset that was emitted before it was " |
| 495 "available", () { | 616 "available", () { |
| 496 initGraph(["app|foo.in"], {"app": [ | 617 initGraph([ |
| 497 [new RewriteTransformer("txt", "txt")] | 618 "app|foo.in" |
| 498 ]}); | 619 ], { |
| 620 "app": [ |
| 621 [new RewriteTransformer("txt", "txt")] |
| 622 ] |
| 623 }); |
| 499 | 624 |
| 500 pauseProvider(); | 625 pauseProvider(); |
| 501 updateSources(["app|foo.in"]); | 626 updateSources(["app|foo.in"]); |
| 502 expectAssetDoesNotComplete("app|foo.in"); | 627 expectAssetDoesNotComplete("app|foo.in"); |
| 503 | 628 |
| 504 resumeProvider(); | 629 resumeProvider(); |
| 505 expectAsset("app|foo.in", "foo"); | 630 expectAsset("app|foo.in", "foo"); |
| 506 buildShouldSucceed(); | 631 buildShouldSucceed(); |
| 507 }); | 632 }); |
| 508 | 633 |
| 509 test("re-runs if the primary input is invalidated before accessing", () { | 634 test("re-runs if the primary input is invalidated before accessing", () { |
| 510 var transformer1 = new RewriteTransformer("txt", "mid"); | 635 var transformer1 = new RewriteTransformer("txt", "mid"); |
| 511 var transformer2 = new RewriteTransformer("mid", "out"); | 636 var transformer2 = new RewriteTransformer("mid", "out"); |
| 512 | 637 |
| 513 initGraph([ | 638 initGraph([ |
| 514 "app|foo.txt" | 639 "app|foo.txt" |
| 515 ], {"app": [ | 640 ], { |
| 516 [transformer1], | 641 "app": [ |
| 517 [transformer2] | 642 [transformer1], |
| 518 ]}); | 643 [transformer2] |
| 644 ] |
| 645 }); |
| 519 | 646 |
| 520 transformer2.pausePrimaryInput(); | 647 transformer2.pausePrimaryInput(); |
| 521 updateSources(["app|foo.txt"]); | 648 updateSources(["app|foo.txt"]); |
| 522 | 649 |
| 523 // Wait long enough to ensure that transformer1 has completed and | 650 // Wait long enough to ensure that transformer1 has completed and |
| 524 // transformer2 has started. | 651 // transformer2 has started. |
| 525 schedule(pumpEventQueue); | 652 schedule(pumpEventQueue); |
| 526 | 653 |
| 527 // Update the source again so that transformer1 invalidates the primary | 654 // Update the source again so that transformer1 invalidates the primary |
| 528 // input of transformer2. | 655 // input of transformer2. |
| 529 transformer1.pauseApply(); | 656 transformer1.pauseApply(); |
| 530 modifyAsset("app|foo.txt", "new foo"); | 657 modifyAsset("app|foo.txt", "new foo"); |
| 531 updateSources(["app|foo.txt"]); | 658 updateSources(["app|foo.txt"]); |
| 532 | 659 |
| 533 transformer2.resumePrimaryInput(); | 660 transformer2.resumePrimaryInput(); |
| 534 transformer1.resumeApply(); | 661 transformer1.resumeApply(); |
| 535 | 662 |
| 536 expectAsset("app|foo.out", "new foo.mid.out"); | 663 expectAsset("app|foo.out", "new foo.mid.out"); |
| 537 buildShouldSucceed(); | 664 buildShouldSucceed(); |
| 538 | 665 |
| 539 expect(transformer1.numRuns, completion(equals(2))); | 666 expect(transformer1.numRuns, completion(equals(2))); |
| 540 expect(transformer2.numRuns, completion(equals(2))); | 667 expect(transformer2.numRuns, completion(equals(2))); |
| 541 }); | 668 }); |
| 542 | 669 |
| 543 // Regression test for issue 19038. | 670 // Regression test for issue 19038. |
| 544 test("a secondary input that's marked dirty followed by the primary input " | 671 test( |
| 672 "a secondary input that's marked dirty followed by the primary input " |
| 545 "being synchronously marked dirty re-runs a transformer", () { | 673 "being synchronously marked dirty re-runs a transformer", () { |
| 546 // Issue 19038 was caused by the following sequence of events: | 674 // Issue 19038 was caused by the following sequence of events: |
| 547 // | 675 // |
| 548 // * Several inputs are marked dirty at once, causing dirty events to | 676 // * Several inputs are marked dirty at once, causing dirty events to |
| 549 // propagate synchronously throughout the transform graph. | 677 // propagate synchronously throughout the transform graph. |
| 550 // | 678 // |
| 551 // * A transform (ManyToOneTransformer in this test case) has a secondary | 679 // * A transform (ManyToOneTransformer in this test case) has a secondary |
| 552 // input ("one.in") and a primary input ("foo.txt") that will both be | 680 // input ("one.in") and a primary input ("foo.txt") that will both be |
| 553 // marked dirty. | 681 // marked dirty. |
| 554 // | 682 // |
| 555 // * The secondary input is marked dirty before the primary input. This | 683 // * The secondary input is marked dirty before the primary input. This |
| 556 // causes the transform to start running `apply`. Since as far as it knows | 684 // causes the transform to start running `apply`. Since as far as it knows |
| 557 // its primary input is still available, it passes that input to `apply`. | 685 // its primary input is still available, it passes that input to `apply`. |
| 558 // | 686 // |
| 559 // * Now the primary input is marked dirty. The transform node checks to see | 687 // * Now the primary input is marked dirty. The transform node checks to see |
| 560 // if this primary input has already been added to the transform | 688 // if this primary input has already been added to the transform |
| 561 // controller. This is where the bug existed: the answer to this was | 689 // controller. This is where the bug existed: the answer to this was |
| 562 // incorrectly "no" until after some asynchronous processing occurred. | 690 // incorrectly "no" until after some asynchronous processing occurred. |
| 563 // | 691 // |
| 564 // * Since the transform thought the primary input hadn't yet been passed to | 692 // * Since the transform thought the primary input hadn't yet been passed to |
| 565 // the transform controller, it didn't bother restarting the transform, | 693 // the transform controller, it didn't bother restarting the transform, |
| 566 // causing the old output to be preserved incorrectly. | 694 // causing the old output to be preserved incorrectly. |
| 567 initGraph({ | 695 initGraph({ |
| 568 "app|foo.txt": "one", | 696 "app|foo.txt": "one", |
| 569 "app|one.in": "1", | 697 "app|one.in": "1", |
| 570 "app|two.in": "2" | 698 "app|two.in": "2" |
| 571 }, {"app": [ | 699 }, { |
| 572 // We need to use CheckContentTransformer here so that | 700 "app": [ |
| 573 // ManyToOneTransformer reads its primary input from memory rather than | 701 // We need to use CheckContentTransformer here so that |
| 574 // from the filesystem. If it read from the filesystem, it might | 702 // ManyToOneTransformer reads its primary input from memory rather than |
| 575 // accidentally get the correct output despite accessing the incorrect | 703 // from the filesystem. If it read from the filesystem, it might |
| 576 // asset, which would cause false positives for the test. | 704 // accidentally get the correct output despite accessing the incorrect |
| 577 [new CheckContentTransformer(new RegExp("one|two"), ".in")], | 705 // asset, which would cause false positives for the test. |
| 578 [new ManyToOneTransformer("txt")] | 706 [new CheckContentTransformer(new RegExp("one|two"), ".in")], |
| 579 ]}); | 707 [new ManyToOneTransformer("txt")] |
| 708 ] |
| 709 }); |
| 580 | 710 |
| 581 updateSources(["app|foo.txt", "app|one.in", "app|two.in"]); | 711 updateSources(["app|foo.txt", "app|one.in", "app|two.in"]); |
| 582 expectAsset("app|foo.out", "1"); | 712 expectAsset("app|foo.out", "1"); |
| 583 buildShouldSucceed(); | 713 buildShouldSucceed(); |
| 584 | 714 |
| 585 modifyAsset("app|foo.txt", "two"); | 715 modifyAsset("app|foo.txt", "two"); |
| 586 | 716 |
| 587 // It's important that "one.in" come first in this list, since | 717 // It's important that "one.in" come first in this list, since |
| 588 // ManyToOneTransformer needs to see its secondary input change first. | 718 // ManyToOneTransformer needs to see its secondary input change first. |
| 589 updateSources(["app|one.in", "app|foo.txt"]); | 719 updateSources(["app|one.in", "app|foo.txt"]); |
| 590 | 720 |
| 591 expectAsset("app|foo.out", "2"); | 721 expectAsset("app|foo.out", "2"); |
| 592 buildShouldSucceed(); | 722 buildShouldSucceed(); |
| 593 }); | 723 }); |
| 594 } | 724 } |
| OLD | NEW |