Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2063)

Unified Diff: pkg/barback/test/utils.dart

Issue 5695057915019264: Make barback more package-aware. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/barback/test/asset_graph/transform_test.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/barback/test/utils.dart
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
index f14ff3d4595d5cabd5a0503ab3205d82bf4a2862..7f5a4bf3a70a3bbbc673d565af76c84b5d292870 100644
--- a/pkg/barback/test/utils.dart
+++ b/pkg/barback/test/utils.dart
@@ -10,8 +10,11 @@ import 'dart:io';
import 'package:barback/barback.dart';
import 'package:barback/src/asset_graph.dart';
+import 'package:barback/src/asset_graph_manager.dart';
+import 'package:barback/src/utils.dart';
import 'package:pathos/path.dart' as pathos;
import 'package:scheduled_test/scheduled_test.dart';
+import 'package:stack_trace/stack_trace.dart';
// TODO(rnystrom): Get rid of this or find a better path for it.
import '../../../sdk/lib/_internal/pub/test/command_line_config.dart';
@@ -19,7 +22,7 @@ import '../../../sdk/lib/_internal/pub/test/command_line_config.dart';
var _configured = false;
MockProvider _provider;
-AssetGraph _graph;
+AssetGraphManager _graphManager;
/// Calls to [buildShouldSucceed] and [buildShouldFail] set expectations on
/// successive [BuildResult]s from [_graph]. This keeps track of how many calls
@@ -44,12 +47,16 @@ void initConfig() {
/// one. If it's a [Map], each key should be a string that can be parsed to an
/// [AssetId] and the value should be a string defining the contents of that
/// asset.
-void initGraph([assets, Iterable<Iterable<Transformer>> transformers]) {
+///
+/// [transformers] is a map from package names to the transformers for each
+/// package.
+void initGraph([assets,
+ Map<String, Iterable<Iterable<Transformer>>> transformers]) {
if (assets == null) assets = [];
- if (transformers == null) transformers = [];
+ if (transformers == null) transformers = {};
- _provider = new MockProvider(assets);
- _graph = new AssetGraph(_provider, transformers);
+ _provider = new MockProvider(assets, transformers);
+ _graphManager = new AssetGraphManager(_provider);
_nextBuildResult = 0;
}
@@ -64,7 +71,7 @@ void updateSources(Iterable assets) {
return asset;
});
- _graph.updateSources(assets);
+ _graphManager.updateSources(assets);
}
/// Removes [assets] from the current [AssetProvider].
@@ -78,7 +85,7 @@ void removeSources(Iterable assets) {
return asset;
});
- _graph.removeSources(assets);
+ _graphManager.removeSources(assets);
}
/// Schedules a change to the contents of an asset identified by [name] to
@@ -96,7 +103,7 @@ void modifyAsset(String name, String contents) {
/// All asset requests that the [AssetGraph] makes to the provider after this
/// will not complete until [resumeProvider] is called.
void pauseProvider() {
- schedule(() =>_provider._pause(), "pause provider");
+ schedule(() => _provider._pause(), "pause provider");
}
/// Schedules an unpause of the provider after a call to [pauseProvider] and
@@ -105,9 +112,38 @@ void resumeProvider() {
schedule(() => _provider._resume(), "resume provider");
}
+/// Asserts that the current build step shouldn't have finished by this point in
+/// the schedule.
+///
+/// This uses the same build counter as [buildShouldSucceed] and
+/// [buildShouldFail], so those can be used to validate build results before and
+/// after this.
+void buildShouldNotBeDone() {
+ var resultAllowed = false;
+ var trace = new Trace.current();
+ _graphManager.results.elementAt(_nextBuildResult).then((result) {
+ if (resultAllowed) return;
+
+ currentSchedule.signalError(
+ new Exception("Expected build not to terminate "
+ "here, but it terminated with result: $result"), trace);
+ }).catchError((error) {
+ if (resultAllowed) return;
+ currentSchedule.signalError(error);
+ });
+
+ schedule(() {
+ // Pump the event queue in case the build completes out-of-band after we get
+ // here. If it does, we want to signal an error.
+ return pumpEventQueue().then((_) {
+ resultAllowed = true;
+ });
+ }, "ensuring build doesn't terminate");
+}
+
/// Expects that the next [BuildResult] is a build success.
void buildShouldSucceed() {
- expect(_graph.results.elementAt(_nextBuildResult++).then((result) {
+ expect(_getNextBuildResult().then((result) {
expect(result.succeeded, isTrue);
}), completes);
}
@@ -118,7 +154,7 @@ void buildShouldSucceed() {
/// build to fail. Every matcher is expected to match an error, but the order of
/// matchers is unimportant.
void buildShouldFail(List matchers) {
- expect(_graph.results.elementAt(_nextBuildResult++).then((result) {
+ expect(_getNextBuildResult().then((result) {
expect(result.succeeded, isFalse);
expect(result.errors.length, equals(matchers.length));
for (var matcher in matchers) {
@@ -127,12 +163,15 @@ void buildShouldFail(List matchers) {
}), completes);
}
+Future<BuildResult> _getNextBuildResult() =>
+ _graphManager.results.elementAt(_nextBuildResult++);
+
/// Pauses the schedule until the currently running build completes.
///
/// Validates that the build completed successfully.
void waitForBuild() {
schedule(() {
- return _graph.results.first.then((result) {
+ return _graphManager.results.first.then((result) {
expect(result.succeeded, isTrue);
});
}, "wait for build");
@@ -151,7 +190,7 @@ void expectAsset(String name, [String contents]) {
}
schedule(() {
- return _graph.getAssetById(id).then((asset) {
+ return _graphManager.getAssetById(id).then((asset) {
// TODO(rnystrom): Make an actual Matcher class for this.
expect(asset, new isInstanceOf<MockAsset>());
expect(asset.id, equals(id));
@@ -167,7 +206,7 @@ void expectNoAsset(String name) {
// Make sure the future gets the error.
schedule(() {
- return _graph.getAssetById(id).then((asset) {
+ return _graphManager.getAssetById(id).then((asset) {
fail("Should have thrown error but got $asset.");
}).catchError((error) {
expect(error, new isInstanceOf<AssetNotFoundException>());
@@ -176,22 +215,6 @@ void expectNoAsset(String name) {
}, "get asset $name");
}
-/// Schedules an expectation that [graph] will have an error on an asset
-/// matching [name] for missing [input].
-Future expectMissingInput(AssetGraph graph, String name, String input) {
- var missing = new AssetId.parse(input);
-
- // Make sure the future gets the error.
- schedule(() {
- return graph.getAssetById(new AssetId.parse(name)).then((asset) {
- fail("Should have thrown error but got $asset.");
- }).catchError((error) {
- expect(error, new isInstanceOf<MissingInputException>());
- expect(error.id, equals(missing));
- });
- }, "get missing input on $name");
-}
-
/// Returns a matcher for an [AssetNotFoundException] with the given [id].
Matcher isAssetNotFoundException(String name) {
var id = new AssetId.parse(name);
@@ -216,11 +239,21 @@ Matcher isMissingInputException(String name) {
predicate((error) => error.id == id, 'id is $name'));
}
+/// Returns a matcher for an [InvalidOutputException] with the given id and
+/// package name.
+Matcher isInvalidOutputException(String package, String name) {
+ var id = new AssetId.parse(name);
+ return allOf(
+ new isInstanceOf<InvalidOutputException>(),
+ predicate((error) => error.package == package, 'package is $package'),
+ predicate((error) => error.id == id, 'id is $name'));
+}
+
/// An [AssetProvider] that provides the given set of assets.
class MockProvider implements AssetProvider {
Iterable<String> get packages => _packages.keys;
- final _packages = new Map<String, List<MockAsset>>();
+ Map<String, _MockPackage> _packages;
/// The completer that [getAsset()] is waiting on to complete when paused.
///
@@ -240,26 +273,38 @@ class MockProvider implements AssetProvider {
_pauseCompleter = null;
}
- MockProvider(assets) {
+ MockProvider(assets,
+ Map<String, Iterable<Iterable<Transformer>>> transformers) {
+ var assetList;
if (assets is Map) {
- assets.forEach((asset, contents) {
+ assetList = assets.keys.map((asset) {
var id = new AssetId.parse(asset);
- var package = _packages.putIfAbsent(id.package, () => []);
- package.add(new MockAsset(id, contents));
+ return new MockAsset(id, assets[asset]);
});
} else if (assets is Iterable) {
- for (var asset in assets) {
+ assetList = assets.map((asset) {
var id = new AssetId.parse(asset);
- var package = _packages.putIfAbsent(id.package, () => []);
var contents = pathos.basenameWithoutExtension(id.path);
- package.add(new MockAsset(id, contents));
- }
+ return new MockAsset(id, contents);
+ });
}
+
+ _packages = mapMapValues(groupBy(assetList, (asset) => asset.id.package),
+ (package, assets) {
+ var packageTransformers = transformers[package];
+ if (packageTransformers == null) packageTransformers = [];
+ return new _MockPackage(assets, packageTransformers.toList());
+ });
+
+ // If there are no assets or transformers, add a dummy package. This better
+ // simulates the real world, where there'll always be at least the
+ // entrypoint package.
+ if (_packages.isEmpty) _packages = {"app": new _MockPackage([], [])};
}
void _modifyAsset(String name, String contents) {
var id = new AssetId.parse(name);
- var asset = _packages[id.package].firstWhere((a) => a.id == id);
+ var asset = _packages[id.package].assets.firstWhere((a) => a.id == id);
asset.contents = contents;
}
@@ -268,7 +313,15 @@ class MockProvider implements AssetProvider {
throw new UnimplementedError("Doesn't handle 'within' yet.");
}
- return _packages[package].map((asset) => asset.id);
+ return _packages[package].assets.map((asset) => asset.id);
+ }
+
+ Iterable<Iterable<Transformer>> getTransformers(String package) {
+ var mockPackage = _packages[package];
+ if (mockPackage == null) {
+ throw new ArgumentError("No package named $package.");
+ }
+ return mockPackage.transformers;
}
Future<Asset> getAsset(AssetId id) {
@@ -283,12 +336,22 @@ class MockProvider implements AssetProvider {
var package = _packages[id.package];
if (package == null) throw new AssetNotFoundException(id);
- return package.firstWhere((asset) => asset.id == id,
+ return package.assets.firstWhere((asset) => asset.id == id,
orElse: () => throw new AssetNotFoundException(id));
});
}
}
+/// Used by [MockProvider] to keep track of which assets and transformers exist
+/// for each package.
+class _MockPackage {
+ final List<MockAsset> assets;
+ final List<List<Transformer>> transformers;
+
+ _MockPackage(this.assets, Iterable<Iterable<Transformer>> transformers)
+ : transformers = transformers.map((phase) => phase.toList()).toList();
+}
+
/// A [Transformer] that takes assets ending with one extension and generates
/// assets with a given extension.
///
@@ -468,6 +531,21 @@ class BadTransformer extends Transformer {
}
}
+/// A transformer that outputs an asset with the given id.
+class CreateAssetTransformer extends Transformer {
+ final String output;
+
+ CreateAssetTransformer(this.output);
+
+ Future<bool> isPrimary(Asset asset) => new Future.value(true);
+
+ Future apply(Transform transform) {
+ return new Future(() {
+ transform.addOutput(new MockAsset(new AssetId.parse(output), output));
+ });
+ }
+}
+
/// An implementation of [Asset] that never hits the file system.
class MockAsset implements Asset {
final AssetId id;
« no previous file with comments | « pkg/barback/test/asset_graph/transform_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698