Skip to content

Commit 6081a48

Browse files
committed
add BuildStepImpl tests
1 parent d8e0093 commit 6081a48

11 files changed

+273
-0
lines changed

lib/build.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44
export 'src/asset/asset.dart';
5+
export 'src/asset/exceptions.dart';
56
export 'src/asset/id.dart';
7+
export 'src/asset/reader.dart';
8+
export 'src/asset/writer.dart';
69
export 'src/builder/build_step.dart';
710
export 'src/builder/builder.dart';
11+
export 'src/builder/exceptions.dart';
812
export 'src/generate/build_result.dart';
913
export 'src/generate/build.dart';
1014
export 'src/generate/input_set.dart';

lib/src/asset/exceptions.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2016, 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+
import 'id.dart';
5+
6+
class AssetNotFoundException implements Exception {
7+
final AssetId assetId;
8+
9+
AssetNotFoundException(this.assetId);
10+
11+
@override
12+
String toString() => 'AssetNotFoundException: $assetId';
13+
}

lib/src/builder/build_step_impl.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../asset/id.dart';
1010
import '../asset/reader.dart';
1111
import '../asset/writer.dart';
1212
import 'build_step.dart';
13+
import 'exceptions.dart';
1314

1415
/// A single step in the build processes. This represents a single input and
1516
/// its expected and real outputs. It also handles tracking of dependencies.
@@ -61,8 +62,14 @@ class BuildStepImpl implements BuildStep {
6162

6263
/// Outputs an [Asset] using the current [AssetWriter], and adds [asset] to
6364
/// [outputs].
65+
///
66+
/// Throws an [UnexpectedOutputException] if [asset] is not in
67+
/// [expectedOutputs].
6468
@override
6569
void writeAsString(Asset asset, {Encoding encoding: UTF8}) {
70+
if (!expectedOutputs.any((id) => id == asset.id)) {
71+
throw new UnexpectedOutputException(asset);
72+
}
6673
_outputs.add(asset);
6774
var done = _writer.writeAsString(asset, encoding: encoding);
6875
_outputsCompleted = _outputsCompleted.then((_) => done);

lib/src/builder/exceptions.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2016, 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+
import '../asset/asset.dart';
5+
6+
class UnexpectedOutputException implements Exception {
7+
final Asset asset;
8+
9+
UnexpectedOutputException(this.asset);
10+
11+
@override
12+
String toString() => 'UnexpectedOutputException: $asset';
13+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) 2016, 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+
@TestOn('vm')
5+
import 'package:test/test.dart';
6+
7+
import 'package:build/build.dart';
8+
import 'package:build/src/builder/build_step_impl.dart';
9+
10+
import '../common/common.dart';
11+
12+
main() {
13+
group('BuildStepImpl ', () {
14+
AssetWriter writer;
15+
AssetReader reader;
16+
17+
group('with reader/writer stub', () {
18+
Asset primary;
19+
BuildStepImpl buildStep;
20+
21+
setUp(() {
22+
reader = new StubAssetReader();
23+
writer = new StubAssetWriter();
24+
primary = makeAsset();
25+
buildStep = new BuildStepImpl(primary, [], reader, writer);
26+
});
27+
28+
test('tracks dependencies on read', () async {
29+
expect(buildStep.dependencies, [primary.id]);
30+
31+
var a1 = makeAssetId();
32+
await buildStep.readAsString(a1);
33+
expect(buildStep.dependencies, [primary.id, a1]);
34+
35+
var a2 = makeAssetId();
36+
await buildStep.readAsString(a2);
37+
expect(buildStep.dependencies, [primary.id, a1, a2]);
38+
});
39+
40+
test('addDependency adds dependencies', () {
41+
expect(buildStep.dependencies, [primary.id]);
42+
43+
var a1 = makeAssetId();
44+
buildStep.addDependency(a1);
45+
expect(buildStep.dependencies, [primary.id, a1]);
46+
47+
var a2 = makeAssetId();
48+
buildStep.addDependency(a2);
49+
expect(buildStep.dependencies, [primary.id, a1, a2]);
50+
});
51+
52+
test('tracks outputs', () async {
53+
var a1 = makeAsset();
54+
var a2 = makeAsset();
55+
buildStep = new BuildStepImpl(primary, [a1.id, a2.id], reader, writer);
56+
57+
buildStep.writeAsString(a1);
58+
expect(buildStep.outputs, [a1]);
59+
60+
buildStep.writeAsString(a2);
61+
expect(buildStep.outputs, [a1, a2]);
62+
63+
expect(buildStep.outputsCompleted, completes);
64+
});
65+
66+
test('doesnt allow non-expected outputs', () {
67+
var asset = makeAsset();
68+
expect(() => buildStep.writeAsString(asset),
69+
throwsA(new isInstanceOf<UnexpectedOutputException>()));
70+
});
71+
});
72+
73+
group('with in memory file system', () {
74+
InMemoryAssetWriter writer;
75+
InMemoryAssetReader reader;
76+
77+
setUp(() {
78+
writer = new InMemoryAssetWriter();
79+
reader = new InMemoryAssetReader(writer.assets);
80+
});
81+
82+
test('tracks dependencies and outputs when used by a builder', () async {
83+
var fileCombiner = new FileCombinerBuilder();
84+
var primary = 'a|web/primary.txt';
85+
var unUsed = 'a|web/not_used.txt';
86+
var inputs = makeAssets({
87+
primary: 'a|web/a.txt\na|web/b.txt',
88+
'a|web/a.txt': 'A',
89+
'a|web/b.txt': 'B',
90+
unUsed: 'C',
91+
});
92+
addAssets(inputs.values, writer);
93+
var outputId = new AssetId.parse('$primary.combined');
94+
var buildStep = new BuildStepImpl(
95+
inputs[new AssetId.parse(primary)], [outputId], reader, writer);
96+
97+
await fileCombiner.build(buildStep);
98+
await buildStep.outputsCompleted;
99+
100+
// All the assets should be read and marked as deps, except [unUsed].
101+
expect(buildStep.dependencies,
102+
inputs.keys.where((k) => k != new AssetId.parse(unUsed)));
103+
104+
// One output.
105+
expect(buildStep.outputs[0].id, outputId);
106+
expect(buildStep.outputs[0].stringContents, 'AB');
107+
expect(writer.assets[outputId], 'AB');
108+
});
109+
});
110+
});
111+
}

test/common/common.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
4+
import 'package:build/build.dart';
5+
6+
import 'in_memory_writer.dart';
7+
48
export 'copy_builder.dart';
9+
export 'file_combiner_builder.dart';
10+
export 'in_memory_reader.dart';
11+
export 'in_memory_writer.dart';
512
export 'generic_builder_transformer.dart';
13+
export 'stub_reader.dart';
14+
export 'stub_writer.dart';
15+
16+
int _nextId = 0;
17+
AssetId makeAssetId([String assetIdString]) {
18+
if (assetIdString == null) {
19+
assetIdString = 'a|web/asset_$_nextId.txt';
20+
_nextId++;
21+
}
22+
return new AssetId.parse(assetIdString);
23+
}
24+
25+
Asset makeAsset([String assetIdString, String contents]) {
26+
var id = makeAssetId(assetIdString);
27+
return new Asset(id, contents ?? '$id');
28+
}
29+
30+
Map<AssetId, Asset> makeAssets(Map<String, String> assetsMap) {
31+
var assets = <AssetId, Asset>{};
32+
assetsMap.forEach((idString, content) {
33+
var asset = makeAsset(idString, content);
34+
assets[asset.id] = asset;
35+
});
36+
return assets;
37+
}
38+
39+
void addAssets(Iterable<Asset> assets, InMemoryAssetWriter writer) {
40+
for (var asset in assets) {
41+
writer.assets[asset.id] = asset.stringContents;
42+
}
43+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2016, 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+
import 'dart:async';
5+
6+
import 'package:build/build.dart';
7+
8+
/// Takes an input file which points at a bunch of other files, and then it
9+
/// writes an `$input.combined` file which concats all the files.
10+
class FileCombinerBuilder implements Builder {
11+
Future build(BuildStep buildStep) async {
12+
var lines = buildStep.input.stringContents.split('\n');
13+
var content = new StringBuffer();
14+
for (var line in lines) {
15+
content.write(await buildStep.readAsString(new AssetId.parse(line)));
16+
}
17+
18+
var outputId = _combinedAssetId(buildStep.input.id);
19+
buildStep.writeAsString(new Asset(outputId, content.toString()));
20+
}
21+
22+
List<AssetId> declareOutputs(AssetId input) {
23+
return [_combinedAssetId(input)];
24+
}
25+
}
26+
27+
AssetId _combinedAssetId(AssetId inputId) =>
28+
inputId.addExtension('.combined');

test/common/in_memory_reader.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2016, 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+
import 'dart:async';
5+
import 'dart:convert';
6+
7+
import 'package:build/build.dart';
8+
9+
class InMemoryAssetReader implements AssetReader {
10+
final Map<AssetId, String> assets;
11+
12+
InMemoryAssetReader(this.assets);
13+
14+
Future<String> readAsString(AssetId id, {Encoding encoding: UTF8}) async {
15+
if (!assets.containsKey(id)) throw new AssetNotFoundException(id);
16+
return assets[id];
17+
}
18+
}

test/common/in_memory_writer.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2016, 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+
import 'dart:async';
5+
import 'dart:convert';
6+
7+
import 'package:build/build.dart';
8+
9+
class InMemoryAssetWriter implements AssetWriter {
10+
final Map<AssetId, String> assets = {};
11+
12+
InMemoryAssetWriter();
13+
14+
Future writeAsString(Asset asset, {Encoding encoding: UTF8}) async {
15+
assets[asset.id] = asset.stringContents;
16+
}
17+
}

test/common/stub_reader.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2016, 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+
import 'dart:async';
5+
import 'dart:convert';
6+
7+
import 'package:build/build.dart';
8+
9+
class StubAssetReader implements AssetReader {
10+
Future<String> readAsString(AssetId id, {Encoding encoding: UTF8}) =>
11+
new Future.value(null);
12+
}

test/common/stub_writer.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2016, 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+
import 'dart:async';
5+
import 'dart:convert';
6+
7+
import 'package:build/build.dart';
8+
9+
class StubAssetWriter implements AssetWriter {
10+
Future writeAsString(Asset asset, {Encoding encoding: UTF8}) =>
11+
new Future.value(null);
12+
}

0 commit comments

Comments
 (0)