blob: acc6144cd49cba943e224e8f3284cbabb547e318 [file] [log] [blame]
// Copyright (c) 2019, 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.
/// An implementation of [Pipeline] that runs using IO.
///
/// To define a step, implement [IOModularStep].
import 'dart:io';
import 'pipeline.dart';
import 'suite.dart';
/// Indicates where to read and write data produced by the pipeline.
typedef ModuleDataToRelativeUri = Uri Function(Module, DataId);
abstract class IOModularStep extends ModularStep {
/// Execute the step under [root].
///
/// The [root] folder will hold all inputs and will be used to emit the output
/// of this step.
///
/// Assets created on previous steps of the pipeline should be available under
/// `root.resolveUri(toUri(module, dataId))` and the output of this step
/// should be stored under `root.resolveUri(toUri(module, resultKind))`.
Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri);
}
class IOPipeline extends Pipeline<IOModularStep> {
/// A folder per step. The key is the data id produced by a specific step.
///
/// This contains internal state used during the run of the pipeline, but is
/// expected to be null before and after the pipeline is executed.
Map<DataId, Uri> _tmpFolders;
Map<DataId, Uri> get tmpFoldersForTesting => _tmpFolders;
bool saveFoldersForTesting;
IOPipeline(List<ModularStep> steps, {this.saveFoldersForTesting: false})
: super(steps);
@override
Future<void> run(ModularTest test) async {
assert(_tmpFolders == null);
_tmpFolders = {};
await super.run(test);
if (!saveFoldersForTesting) {
for (var folder in _tmpFolders.values) {
await Directory.fromUri(folder).delete(recursive: true);
}
_tmpFolders = null;
}
}
@override
Future<void> runStep(IOModularStep step, Module module,
Map<Module, Set<DataId>> visibleData) async {
var folder =
await Directory.systemTemp.createTemp('modular_test_${step.resultId}-');
_tmpFolders[step.resultId] ??= (await Directory.systemTemp
.createTemp('modular_test_${step.resultId}_res-'))
.uri;
for (var module in visibleData.keys) {
for (var dataId in visibleData[module]) {
var filename = "${module.name}.${dataId.name}";
var assetUri = _tmpFolders[dataId].resolve(filename);
await File.fromUri(assetUri)
.copy(folder.uri.resolve(filename).toFilePath());
}
}
if (step.needsSources) {
for (var uri in module.sources) {
var originalUri = module.rootUri.resolveUri(uri);
await File.fromUri(originalUri)
.copy(folder.uri.resolveUri(uri).toFilePath());
}
}
await step.execute(module, folder.uri,
(Module m, DataId id) => Uri.parse("${m.name}.${id.name}"));
var outputFile = File.fromUri(
folder.uri.resolve("${module.name}.${step.resultId.name}"));
if (!await outputFile.exists()) {
throw StateError(
"Step '${step.runtimeType}' didn't produce an output file");
}
await outputFile.copy(_tmpFolders[step.resultId]
.resolve("${module.name}.${step.resultId.name}")
.toFilePath());
await folder.delete(recursive: true);
}
}