Skip to content

Commit

Permalink
add BuildStepImpl tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jakemac53 committed Jan 29, 2016
1 parent d8e0093 commit fd76acc
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/build.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
// 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.
export 'src/asset/asset.dart';
export 'src/asset/exceptions.dart';
export 'src/asset/id.dart';
export 'src/asset/reader.dart';
export 'src/asset/writer.dart';
export 'src/builder/build_step.dart';
export 'src/builder/builder.dart';
export 'src/builder/exceptions.dart';
export 'src/generate/build_result.dart';
export 'src/generate/build.dart';
export 'src/generate/input_set.dart';
Expand Down
12 changes: 12 additions & 0 deletions lib/src/asset/exceptions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2016, 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.
import 'id.dart';

class AssetNotFoundException implements Exception {
final AssetId assetId;

AssetNotFoundException(this.assetId);

String toString() => 'AssetNotFoundException: $assetId';
}
7 changes: 7 additions & 0 deletions lib/src/builder/build_step_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import '../asset/id.dart';
import '../asset/reader.dart';
import '../asset/writer.dart';
import 'build_step.dart';
import 'exceptions.dart';

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

/// Outputs an [Asset] using the current [AssetWriter], and adds [asset] to
/// [outputs].
///
/// Throws an [UnexpectedOutputException] if [asset] is not in
/// [expectedOutputs].
@override
void writeAsString(Asset asset, {Encoding encoding: UTF8}) {
if (!expectedOutputs.any((id) => id == asset.id)) {
throw new UnexpectedOutputException(asset);
}
_outputs.add(asset);
var done = _writer.writeAsString(asset, encoding: encoding);
_outputsCompleted = _outputsCompleted.then((_) => done);
Expand Down
12 changes: 12 additions & 0 deletions lib/src/builder/exceptions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2016, 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.
import '../asset/asset.dart';

class UnexpectedOutputException implements Exception {
final Asset asset;

UnexpectedOutputException(this.asset);

String toString() => 'UnexpectedOutputException: $asset';
}
111 changes: 111 additions & 0 deletions test/builder/build_step_impl_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) 2016, 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.
@TestOn('vm')
import 'package:test/test.dart';

import 'package:build/build.dart';
import 'package:build/src/builder/build_step_impl.dart';

import '../common/common.dart';

main() {
group('BuildStepImpl ', () {
AssetWriter writer;
AssetReader reader;

group('with reader/writer stub', () {
Asset primary;
BuildStepImpl buildStep;

setUp(() {
reader = new StubAssetReader();
writer = new StubAssetWriter();
primary = makeAsset();
buildStep = new BuildStepImpl(primary, [], reader, writer);
});

test('tracks dependencies on read', () async {
expect(buildStep.dependencies, [primary.id]);

var a1 = makeAssetId();
await buildStep.readAsString(a1);
expect(buildStep.dependencies, [primary.id, a1]);

var a2 = makeAssetId();
await buildStep.readAsString(a2);
expect(buildStep.dependencies, [primary.id, a1, a2]);
});

test('addDependency adds dependencies', () {
expect(buildStep.dependencies, [primary.id]);

var a1 = makeAssetId();
buildStep.addDependency(a1);
expect(buildStep.dependencies, [primary.id, a1]);

var a2 = makeAssetId();
buildStep.addDependency(a2);
expect(buildStep.dependencies, [primary.id, a1, a2]);
});

test('tracks outputs', () async {
var a1 = makeAsset();
var a2 = makeAsset();
buildStep = new BuildStepImpl(primary, [a1.id, a2.id], reader, writer);

buildStep.writeAsString(a1);
expect(buildStep.outputs, [a1]);

buildStep.writeAsString(a2);
expect(buildStep.outputs, [a1, a2]);

expect(buildStep.outputsCompleted, completes);
});

test('doesnt allow non-expected outputs', () {
var asset = makeAsset();
expect(() => buildStep.writeAsString(asset),
throwsA(new isInstanceOf<UnexpectedOutputException>()));
});
});

group('with in memory file system', () {
InMemoryAssetWriter writer;
InMemoryAssetReader reader;

setUp(() {
writer = new InMemoryAssetWriter();
reader = new InMemoryAssetReader(writer.assets);
});

test('tracks dependencies and outputs when used by a builder', () async {
var fileCombiner = new FileCombinerBuilder();
var primary = 'a|web/primary.txt';
var unUsed = 'a|web/not_used.txt';
var inputs = makeAssets({
primary: 'a|web/a.txt\na|web/b.txt',
'a|web/a.txt': 'A',
'a|web/b.txt': 'B',
unUsed: 'C',
});
addAssets(inputs.values, writer);
var outputId = new AssetId.parse('$primary.combined');
var buildStep = new BuildStepImpl(
inputs[new AssetId.parse(primary)], [outputId], reader, writer);

await fileCombiner.build(buildStep);
await buildStep.outputsCompleted;

// All the assets should be read and marked as deps, except [unUsed].
expect(buildStep.dependencies,
inputs.keys.where((k) => k != new AssetId.parse(unUsed)));

// One output.
expect(buildStep.outputs[0].id, outputId);
expect(buildStep.outputs[0].stringContents, 'AB');
expect(writer.assets[outputId], 'AB');
});
});
});
}
38 changes: 38 additions & 0 deletions test/common/common.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
// Copyright (c) 2016, 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.
import 'package:build/build.dart';

import 'in_memory_writer.dart';

export 'copy_builder.dart';
export 'file_combiner_builder.dart';
export 'in_memory_reader.dart';
export 'in_memory_writer.dart';
export 'generic_builder_transformer.dart';
export 'stub_reader.dart';
export 'stub_writer.dart';

int _nextId = 0;
AssetId makeAssetId([String assetIdString]) {
if (assetIdString == null) {
assetIdString = 'a|web/asset_$_nextId.txt';
_nextId++;
}
return new AssetId.parse(assetIdString);
}

Asset makeAsset([String assetIdString, String contents]) {
var id = makeAssetId(assetIdString);
return new Asset(id, contents ?? '$id');
}

Map<AssetId, Asset> makeAssets(Map<String, String> assetsMap) {
var assets = <AssetId, Asset>{};
assetsMap.forEach((idString, content) {
var asset = makeAsset(idString, content);
assets[asset.id] = asset;
});
return assets;
}

void addAssets(Iterable<Asset> assets, InMemoryAssetWriter writer) {
for (var asset in assets) {
writer.assets[asset.id] = asset.stringContents;
}
}
28 changes: 28 additions & 0 deletions test/common/file_combiner_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2016, 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.
import 'dart:async';

import 'package:build/build.dart';

/// Takes an input file which points at a bunch of other files, and then it
/// writes an `$input.combined` file which concats all the files.
class FileCombinerBuilder implements Builder {
Future build(BuildStep buildStep) async {
var lines = buildStep.input.stringContents.split('\n');
var content = new StringBuffer();
for (var line in lines) {
content.write(await buildStep.readAsString(new AssetId.parse(line)));
}

var outputId = _combinedAssetId(buildStep.input.id);
buildStep.writeAsString(new Asset(outputId, content.toString()));
}

List<AssetId> declareOutputs(AssetId input) {
return [_combinedAssetId(input)];
}
}

AssetId _combinedAssetId(AssetId inputId) =>
inputId.addExtension('.combined');
18 changes: 18 additions & 0 deletions test/common/in_memory_reader.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2016, 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.
import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';

class InMemoryAssetReader implements AssetReader {
final Map<AssetId, String> assets;

InMemoryAssetReader(this.assets);

Future<String> readAsString(AssetId id, {Encoding encoding: UTF8}) async {
if (!assets.containsKey(id)) throw new AssetNotFoundException(id);
return assets[id];
}
}
17 changes: 17 additions & 0 deletions test/common/in_memory_writer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2016, 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.
import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';

class InMemoryAssetWriter implements AssetWriter {
final Map<AssetId, String> assets = {};

InMemoryAssetWriter();

Future writeAsString(Asset asset, {Encoding encoding: UTF8}) async {
assets[asset.id] = asset.stringContents;
}
}
12 changes: 12 additions & 0 deletions test/common/stub_reader.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2016, 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.
import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';

class StubAssetReader implements AssetReader {
Future<String> readAsString(AssetId id, {Encoding encoding: UTF8}) =>
new Future.value(null);
}
12 changes: 12 additions & 0 deletions test/common/stub_writer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2016, 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.
import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';

class StubAssetWriter implements AssetWriter {
Future writeAsString(Asset asset, {Encoding encoding: UTF8}) =>
new Future.value(null);
}

0 comments on commit fd76acc

Please sign in to comment.