| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library barback.test.transformer.mock; |
| |
| import 'dart:async'; |
| |
| import 'package:barback/barback.dart'; |
| import 'package:barback/src/utils.dart'; |
| import 'package:scheduled_test/scheduled_test.dart'; |
| |
| /// The abstract base class for transformers used to test barback. |
| /// |
| /// This adds the ability to pause and resume different components of the |
| /// transformers, and to tell whether they're running, when they start running, |
| /// and how many times they've run. |
| /// |
| /// Transformers extending this should override [doIsPrimary] and [doApply] |
| /// rather than [isPrimary] and [apply], and they should use [getInput] and |
| /// [getPrimary] rather than [transform.getInput] and [transform.primaryInput]. |
| abstract class MockTransformer extends Transformer { |
| /// The number of times the transformer has been applied. |
| /// |
| /// This is scheduled. The Future will complete at the point in the schedule |
| /// that this is called. |
| Future<int> get numRuns => schedule(() => _numRuns); |
| var _numRuns = 0; |
| |
| /// The number of currently running transforms. |
| int _runningTransforms = 0; |
| |
| // A completer for pausing the transformer before it finishes running [apply]. |
| Completer _apply; |
| |
| // Completers for pausing the transformer before it finishes running |
| // [isPrimary]. |
| final _isPrimary = new Map<AssetId, Completer>(); |
| |
| // Completers for pausing the transformer before it finishes getting inputs |
| // the [Transform]. |
| final _getInput = new Map<AssetId, Completer>(); |
| |
| /// A completer that completes once this transformer begins running. |
| /// |
| /// Once this transformer finishes running, this is reset to a new completer, |
| /// so it can be used multiple times. |
| var _started = new Completer(); |
| |
| /// `true` if any transforms are currently running. |
| /// |
| /// This is scheduled. The Future will complete at the point in the schedule |
| /// that this is called. |
| Future<bool> get isRunning => schedule(() => _runningTransforms > 0); |
| |
| /// Pauses the schedule until this transformer begins running. |
| void waitUntilStarted() { |
| schedule(() => _started.future, "wait until $this starts"); |
| } |
| |
| /// Causes the transformer to pause after running [apply] but before the |
| /// returned Future completes. |
| /// |
| /// This can be resumed by calling [resumeApply]. This operation is scheduled. |
| void pauseApply() { |
| schedule(() { |
| _apply = new Completer(); |
| }, "pause apply for $this"); |
| } |
| |
| /// Resumes the transformer's [apply] call after [pauseApply] was called. |
| /// |
| /// This operation is scheduled. |
| void resumeApply() { |
| schedule(() { |
| _apply.complete(); |
| _apply = null; |
| }, "resume apply for $this"); |
| } |
| |
| /// Causes the transformer to pause after running [isPrimary] on the asset |
| /// with the given [name], but before the returned Future completes. |
| /// |
| /// This can be resumed by calling [resumeIsPrimary]. This operation is |
| /// scheduled. |
| void pauseIsPrimary(String name) { |
| schedule(() { |
| _isPrimary[new AssetId.parse(name)] = new Completer(); |
| }, "pause isPrimary($name) for $this"); |
| } |
| |
| /// Resumes the transformer's [isPrimary] call on the asset with the given |
| /// [name] after [pauseIsPrimary] was called. |
| /// |
| /// This operation is scheduled. |
| void resumeIsPrimary(String name) { |
| schedule(() { |
| _isPrimary.remove(new AssetId.parse(name)).complete(); |
| }, "resume isPrimary($name) for $this"); |
| } |
| |
| /// Causes the transformer to pause while loading the input with the given |
| /// [name]. This can be the primary input or a secondary input. |
| /// |
| /// This can be resumed by calling [resumeGetInput]. This operation is |
| /// scheduled. |
| void pauseGetInput(String name) { |
| schedule(() { |
| _getInput[new AssetId.parse(name)] = new Completer(); |
| }, "pause getInput($name) for $this"); |
| } |
| |
| /// Resumes the transformer's loading of the input with the given [name] after |
| /// [pauseGetInput] was called. |
| /// |
| /// This operation is scheduled. |
| void resumeGetInput(String name) { |
| schedule(() { |
| _getInput.remove(new AssetId.parse(name)).complete(); |
| }, "resume getInput($name) for $this"); |
| } |
| |
| /// Like [Transform.getInput], but respects [pauseGetInput]. |
| /// |
| /// This is intended for use by subclasses of [MockTransformer]. |
| Future<Asset> getInput(Transform transform, AssetId id) { |
| return newFuture(() { |
| if (_getInput.containsKey(id)) return _getInput[id].future; |
| }).then((_) => transform.getInput(id)); |
| } |
| |
| /// Like [Transform.primaryInput], but respects [pauseGetInput]. |
| /// |
| /// This is intended for use by subclasses of [MockTransformer]. |
| Future<Asset> getPrimary(Transform transform) => |
| getInput(transform, transform.primaryId); |
| |
| Future<bool> isPrimary(Asset asset) { |
| return newFuture(() => doIsPrimary(asset)).then((result) { |
| return newFuture(() { |
| if (_isPrimary.containsKey(asset.id)) { |
| return _isPrimary[asset.id].future; |
| } |
| }).then((_) => result); |
| }); |
| } |
| |
| Future apply(Transform transform) { |
| _numRuns++; |
| if (_runningTransforms == 0) _started.complete(); |
| _runningTransforms++; |
| return newFuture(() => doApply(transform)).then((_) { |
| if (_apply != null) return _apply.future; |
| }).whenComplete(() { |
| _runningTransforms--; |
| if (_runningTransforms == 0) _started = new Completer(); |
| }); |
| } |
| |
| /// The wrapped version of [isPrimary] for subclasses to override. |
| Future<bool> doIsPrimary(Asset asset); |
| |
| /// The wrapped version of [doApply] for subclasses to override. |
| Future doApply(Transform transform); |
| } |