f1f368d927
R=rnystrom@google.com Review URL: https://codereview.chromium.org//23201013 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@26330 260f80e4-7a28-3924-810f-c04153c831b5
334 lines
9.8 KiB
Dart
334 lines
9.8 KiB
Dart
// 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.package_graph.source_test;
|
|
|
|
import 'package:barback/src/utils.dart';
|
|
import 'package:scheduled_test/scheduled_test.dart';
|
|
|
|
import '../utils.dart';
|
|
|
|
main() {
|
|
initConfig();
|
|
|
|
test("errors if two transformers output the same file", () {
|
|
initGraph(["app|foo.a"], {"app": [
|
|
[
|
|
new RewriteTransformer("a", "b"),
|
|
new RewriteTransformer("a", "b")
|
|
]
|
|
]});
|
|
updateSources(["app|foo.a"]);
|
|
|
|
buildShouldFail([isAssetCollisionException("app|foo.b")]);
|
|
});
|
|
|
|
test("errors if a new transformer outputs the same file as an old "
|
|
"transformer", () {
|
|
initGraph(["app|foo.a", "app|foo.b"], {"app": [
|
|
[
|
|
new RewriteTransformer("a", "c"),
|
|
new RewriteTransformer("b", "c")
|
|
]
|
|
]});
|
|
updateSources(["app|foo.a"]);
|
|
expectAsset("app|foo.c", "foo.c");
|
|
buildShouldSucceed();
|
|
|
|
updateSources(["app|foo.b"]);
|
|
buildShouldFail([isAssetCollisionException("app|foo.c")]);
|
|
});
|
|
|
|
test("does not report asset not found errors in results", () {
|
|
initGraph(["app|bar.txt"]);
|
|
|
|
// Trigger a build.
|
|
updateSources(["app|bar.txt"]);
|
|
|
|
expectNoAsset("app|foo.txt");
|
|
buildShouldSucceed();
|
|
});
|
|
|
|
test("reports an error for an unprovided package", () {
|
|
initGraph();
|
|
expect(() => updateSourcesSync(["unknown|foo.txt"]), throwsArgumentError);
|
|
});
|
|
|
|
test("reports an error for an unprovided source", () {
|
|
initGraph(["app|known.txt"]);
|
|
updateSources(["app|unknown.txt"]);
|
|
|
|
buildShouldFail([
|
|
isAssetLoadException("app|unknown.txt",
|
|
isAssetNotFoundException("app|unknown.txt"))
|
|
]);
|
|
});
|
|
|
|
test("reports missing input errors in results", () {
|
|
initGraph({"app|a.txt": "a.inc"}, {"app": [
|
|
[new ManyToOneTransformer("txt")]
|
|
]});
|
|
|
|
updateSources(["app|a.txt"]);
|
|
expectNoAsset("app|a.out");
|
|
buildShouldFail([isMissingInputException("app|a.inc")]);
|
|
});
|
|
|
|
test("reports an error if a transformer emits an asset for another package",
|
|
() {
|
|
initGraph(["app|foo.txt"], {
|
|
"app": [[new CreateAssetTransformer("wrong|foo.txt")]]
|
|
});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
buildShouldFail([isInvalidOutputException("wrong|foo.txt")]);
|
|
});
|
|
|
|
test("fails if a non-primary input is removed", () {
|
|
initGraph({
|
|
"app|a.txt": "a.inc,b.inc,c.inc",
|
|
"app|a.inc": "a",
|
|
"app|b.inc": "b",
|
|
"app|c.inc": "c"
|
|
}, {"app": [
|
|
[new ManyToOneTransformer("txt")]
|
|
]});
|
|
|
|
updateSources(["app|a.txt", "app|a.inc", "app|b.inc", "app|c.inc"]);
|
|
expectAsset("app|a.out", "abc");
|
|
buildShouldSucceed();
|
|
|
|
removeSources(["app|b.inc"]);
|
|
buildShouldFail([isMissingInputException("app|b.inc")]);
|
|
expectNoAsset("app|a.out");
|
|
});
|
|
|
|
test("catches transformer exceptions and reports them", () {
|
|
initGraph(["app|foo.txt"], {"app": [
|
|
[new BadTransformer(["app|foo.out"])]
|
|
]});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
expectNoAsset("app|foo.out");
|
|
buildShouldFail([isTransformerException(equals(BadTransformer.ERROR))]);
|
|
});
|
|
|
|
test("doesn't yield a source if a transform fails on it", () {
|
|
initGraph(["app|foo.txt"], {"app": [
|
|
[new BadTransformer(["app|foo.txt"])]
|
|
]});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
expectNoAsset("app|foo.txt");
|
|
});
|
|
|
|
test("catches errors even if nothing is waiting for process results", () {
|
|
initGraph(["app|foo.txt"], {"app": [[new BadTransformer([])]]});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
// Note: No asset requests here.
|
|
buildShouldFail([isTransformerException(equals(BadTransformer.ERROR))]);
|
|
});
|
|
|
|
test("discards outputs from failed transforms", () {
|
|
initGraph(["app|foo.txt"], {"app": [
|
|
[new BadTransformer(["a.out", "b.out"])]
|
|
]});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
expectNoAsset("app|a.out");
|
|
});
|
|
|
|
test("fails if only one package fails", () {
|
|
initGraph(["pkg1|foo.txt", "pkg2|foo.txt"],
|
|
{"pkg1": [[new BadTransformer([])]]});
|
|
|
|
updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
|
|
expectAsset("pkg2|foo.txt", "foo");
|
|
buildShouldFail([isTransformerException(equals(BadTransformer.ERROR))]);
|
|
});
|
|
|
|
test("emits multiple failures if multiple packages fail", () {
|
|
initGraph(["pkg1|foo.txt", "pkg2|foo.txt"], {
|
|
"pkg1": [[new BadTransformer([])]],
|
|
"pkg2": [[new BadTransformer([])]]
|
|
});
|
|
|
|
updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
|
|
buildShouldFail([
|
|
isTransformerException(equals(BadTransformer.ERROR)),
|
|
isTransformerException(equals(BadTransformer.ERROR))
|
|
]);
|
|
});
|
|
|
|
test("an error loading an asset removes the asset from the graph", () {
|
|
initGraph(["app|foo.txt"]);
|
|
|
|
setAssetError("app|foo.txt");
|
|
updateSources(["app|foo.txt"]);
|
|
expectNoAsset("app|foo.txt");
|
|
buildShouldFail([
|
|
isAssetLoadException("app|foo.txt", isMockLoadException("app|foo.txt"))
|
|
]);
|
|
});
|
|
|
|
test("a collision returns the first-produced output", () {
|
|
var rewrite1 = new RewriteTransformer("one", "out");
|
|
var rewrite2 = new RewriteTransformer("two", "out");
|
|
initGraph({
|
|
"app|foo.one": "one",
|
|
"app|foo.two": "two"
|
|
}, {"app": [[rewrite1, rewrite2]]});
|
|
|
|
rewrite1.pauseApply();
|
|
updateSources(["app|foo.one", "app|foo.two"]);
|
|
// Wait long enough to ensure that rewrite2 has completed.
|
|
schedule(pumpEventQueue);
|
|
|
|
rewrite1.resumeApply();
|
|
expectAsset("app|foo.out", "two.out");
|
|
buildShouldFail([isAssetCollisionException("app|foo.out")]);
|
|
|
|
// Even after the collision is discovered, the first-produced output should
|
|
// be returned.
|
|
expectAsset("app|foo.out", "two.out");
|
|
|
|
// Even if the other output is updated more recently, the first output
|
|
// should continue to take precedence.
|
|
updateSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "two.out");
|
|
});
|
|
|
|
test("a collision that is later resolved produces an output", () {
|
|
initGraph({
|
|
"app|foo.one": "one",
|
|
"app|foo.two": "two"
|
|
}, {"app": [
|
|
[
|
|
new RewriteTransformer("one", "out"),
|
|
new RewriteTransformer("two", "out")
|
|
]
|
|
]});
|
|
|
|
updateSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "one.out");
|
|
buildShouldSucceed();
|
|
|
|
updateSources(["app|foo.two"]);
|
|
expectAsset("app|foo.out", "one.out");
|
|
buildShouldFail([isAssetCollisionException("app|foo.out")]);
|
|
|
|
removeSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "two.out");
|
|
buildShouldSucceed();
|
|
});
|
|
|
|
test("a collision that is later resolved runs transforms", () {
|
|
initGraph({
|
|
"app|foo.one": "one",
|
|
"app|foo.two": "two"
|
|
}, {"app": [
|
|
[
|
|
new RewriteTransformer("one", "mid"),
|
|
new RewriteTransformer("two", "mid")
|
|
],
|
|
[new RewriteTransformer("mid", "out")]
|
|
]});
|
|
|
|
updateSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "one.mid.out");
|
|
buildShouldSucceed();
|
|
|
|
updateSources(["app|foo.two"]);
|
|
expectAsset("app|foo.out", "one.mid.out");
|
|
buildShouldFail([isAssetCollisionException("app|foo.mid")]);
|
|
|
|
removeSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "two.mid.out");
|
|
buildShouldSucceed();
|
|
});
|
|
|
|
test("a collision that is partially resolved returns the second completed "
|
|
"output", () {
|
|
var rewrite1 = new RewriteTransformer("one", "out");
|
|
var rewrite2 = new RewriteTransformer("two", "out");
|
|
var rewrite3 = new RewriteTransformer("three", "out");
|
|
initGraph({
|
|
"app|foo.one": "one",
|
|
"app|foo.two": "two",
|
|
"app|foo.three": "three"
|
|
}, {"app": [[rewrite1, rewrite2, rewrite3]]});
|
|
|
|
// Make rewrite3 the most-recently-completed transformer from the first run.
|
|
rewrite2.pauseApply();
|
|
rewrite3.pauseApply();
|
|
updateSources(["app|foo.one", "app|foo.two", "app|foo.three"]);
|
|
schedule(pumpEventQueue);
|
|
rewrite2.resumeApply();
|
|
schedule(pumpEventQueue);
|
|
rewrite3.resumeApply();
|
|
buildShouldFail([isAssetCollisionException("app|foo.out")]);
|
|
|
|
// Then update rewrite3 in a separate build. rewrite2 should still be the
|
|
// next version of foo.out in line.
|
|
// TODO(nweiz): Should this emit a collision error as well? Or should they
|
|
// only be emitted when a file is added or removed?
|
|
updateSources(["app|foo.three"]);
|
|
buildShouldSucceed();
|
|
|
|
removeSources(["app|foo.one"]);
|
|
expectAsset("app|foo.out", "two.out");
|
|
buildShouldFail([isAssetCollisionException("app|foo.out")]);
|
|
});
|
|
|
|
test("a collision with a pass-through asset returns the pass-through asset",
|
|
() {
|
|
initGraph([
|
|
"app|foo.txt",
|
|
"app|foo.in"
|
|
], {"app": [
|
|
[new RewriteTransformer("in", "txt")]
|
|
]});
|
|
|
|
updateSources(["app|foo.txt", "app|foo.in"]);
|
|
expectAsset("app|foo.txt", "foo");
|
|
buildShouldFail([isAssetCollisionException("app|foo.txt")]);
|
|
});
|
|
|
|
test("a new pass-through asset that collides returns the previous asset", () {
|
|
initGraph([
|
|
"app|foo.txt",
|
|
"app|foo.in"
|
|
], {"app": [
|
|
[new RewriteTransformer("in", "txt")]
|
|
]});
|
|
|
|
updateSources(["app|foo.in"]);
|
|
expectAsset("app|foo.txt", "foo.txt");
|
|
buildShouldSucceed();
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
expectAsset("app|foo.txt", "foo.txt");
|
|
buildShouldFail([isAssetCollisionException("app|foo.txt")]);
|
|
});
|
|
|
|
test("a new transform output that collides with a pass-through asset returns "
|
|
"the pass-through asset", () {
|
|
initGraph([
|
|
"app|foo.txt",
|
|
"app|foo.in"
|
|
], {"app": [
|
|
[new RewriteTransformer("in", "txt")]
|
|
]});
|
|
|
|
updateSources(["app|foo.txt"]);
|
|
expectAsset("app|foo.txt", "foo");
|
|
buildShouldSucceed();
|
|
|
|
updateSources(["app|foo.in"]);
|
|
expectAsset("app|foo.txt", "foo");
|
|
buildShouldFail([isAssetCollisionException("app|foo.txt")]);
|
|
});
|
|
}
|