Allow steps to declare more than one result
Change-Id: Ifd2a19f8ff771d464737bb27e22cf05a43cc2a9f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103020
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/modular_test/lib/src/io_pipeline.dart b/pkg/modular_test/lib/src/io_pipeline.dart
index 6ce6d42..ed77f2d 100644
--- a/pkg/modular_test/lib/src/io_pipeline.dart
+++ b/pkg/modular_test/lib/src/io_pipeline.dart
@@ -53,40 +53,47 @@
@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;
+ // Since data ids are unique throughout the pipeline, we use the first
+ // result data id as a hint for the name of the temporary folder of a step.
+ var stepFolder;
+ for (var dataId in step.resultData) {
+ stepFolder ??=
+ await Directory.systemTemp.createTemp('modular_test_${dataId}-');
+ _tmpFolders[dataId] ??=
+ (await Directory.systemTemp.createTemp('modular_test_${dataId}_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());
+ .copy(stepFolder.uri.resolve(filename).toFilePath());
}
}
if (step.needsSources) {
for (var uri in module.sources) {
var originalUri = module.rootUri.resolveUri(uri);
- var copyUri = folder.uri.resolveUri(uri);
+ var copyUri = stepFolder.uri.resolveUri(uri);
await File.fromUri(copyUri).create(recursive: true);
await File.fromUri(originalUri).copy(copyUri.toFilePath());
}
}
- await step.execute(module, folder.uri,
+ await step.execute(module, stepFolder.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");
+ for (var dataId in step.resultData) {
+ var outputFile =
+ File.fromUri(stepFolder.uri.resolve("${module.name}.${dataId.name}"));
+ if (!await outputFile.exists()) {
+ throw StateError(
+ "Step '${step.runtimeType}' didn't produce an output file");
+ }
+ await outputFile.copy(_tmpFolders[dataId]
+ .resolve("${module.name}.${dataId.name}")
+ .toFilePath());
}
- await outputFile.copy(_tmpFolders[step.resultId]
- .resolve("${module.name}.${step.resultId.name}")
- .toFilePath());
- await folder.delete(recursive: true);
+ await stepFolder.delete(recursive: true);
}
}
diff --git a/pkg/modular_test/lib/src/memory_pipeline.dart b/pkg/modular_test/lib/src/memory_pipeline.dart
index 27ecbe9..9ad5c43 100644
--- a/pkg/modular_test/lib/src/memory_pipeline.dart
+++ b/pkg/modular_test/lib/src/memory_pipeline.dart
@@ -13,8 +13,8 @@
typedef SourceProvider = String Function(Uri);
abstract class MemoryModularStep extends ModularStep {
- Future<Object> execute(Module module, SourceProvider sourceProvider,
- ModuleDataProvider dataProvider);
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider);
}
class MemoryPipeline extends Pipeline<MemoryModularStep> {
@@ -55,8 +55,12 @@
inputSources[uri] = _sources[uri];
});
}
- Object result = await step.execute(module, (Uri uri) => inputSources[uri],
+ Map<DataId, Object> result = await step.execute(
+ module,
+ (Uri uri) => inputSources[uri],
(Module m, DataId id) => inputData[m][id]);
- (_results[module] ??= {})[step.resultId] = result;
+ for (var dataId in step.resultData) {
+ (_results[module] ??= {})[dataId] = result[dataId];
+ }
}
}
diff --git a/pkg/modular_test/lib/src/pipeline.dart b/pkg/modular_test/lib/src/pipeline.dart
index f20d1be..64e08a7 100644
--- a/pkg/modular_test/lib/src/pipeline.dart
+++ b/pkg/modular_test/lib/src/pipeline.dart
@@ -25,19 +25,19 @@
/// This can be data produced on a previous stage of the pipeline
/// or produced by this same step when it was run on a dependency.
///
- /// If this list includes [resultId], then the modular-step has to be run on
- /// dependencies before it is run on a module. Otherwise, it could be run in
- /// parallel.
+ /// If this list includes any data from [resultData], then the modular-step
+ /// has to be run on dependencies before it is run on a module. Otherwise, it
+ /// could be run in parallel.
final List<DataId> dependencyDataNeeded;
/// Data that this step needs to read about the module itself.
///
/// This is meant to be data produced in earlier stages of the modular
- /// pipeline. It is an error to include [resultId] in this list.
+ /// pipeline. It is an error to include any id from [resultData] in this list.
final List<DataId> moduleDataNeeded;
/// Data that this step produces.
- final DataId resultId;
+ final List<DataId> resultData;
/// Whether this step is only executed on the main module.
final bool onlyOnMain;
@@ -46,7 +46,7 @@
{this.needsSources: true,
this.dependencyDataNeeded: const [],
this.moduleDataNeeded: const [],
- this.resultId,
+ this.resultData,
this.onlyOnMain: false});
}
@@ -74,30 +74,35 @@
// or by the same step on a dependency.
Map<DataId, S> previousKinds = {};
for (var step in steps) {
- var resultKind = step.resultId;
- if (previousKinds.containsKey(resultKind)) {
- _validationError("Cannot produce the same data on two modular steps."
- " '$resultKind' was previously produced by "
- "'${previousKinds[resultKind].runtimeType}' but "
- "'${step.runtimeType}' also produces the same data.");
+ if (step.resultData == null || step.resultData.isEmpty) {
+ _validationError(
+ "'${step.runtimeType}' needs to declare what data it produces.");
}
- previousKinds[resultKind] = step;
- for (var dataId in step.dependencyDataNeeded) {
- if (!previousKinds.containsKey(dataId)) {
- _validationError(
- "Step '${step.runtimeType}' needs data '${dataId}', but the data"
- " is not produced by this or a preceding step.");
+ for (var resultKind in step.resultData) {
+ if (previousKinds.containsKey(resultKind)) {
+ _validationError("Cannot produce the same data on two modular steps."
+ " '$resultKind' was previously produced by "
+ "'${previousKinds[resultKind].runtimeType}' but "
+ "'${step.runtimeType}' also produces the same data.");
}
- }
- for (var dataId in step.moduleDataNeeded) {
- if (!previousKinds.containsKey(dataId)) {
- _validationError(
- "Step '${step.runtimeType}' needs data '${dataId}', but the data"
- " is not produced by a preceding step.");
+ previousKinds[resultKind] = step;
+ for (var dataId in step.dependencyDataNeeded) {
+ if (!previousKinds.containsKey(dataId)) {
+ _validationError(
+ "Step '${step.runtimeType}' needs data '${dataId}', but the "
+ "data is not produced by this or a preceding step.");
+ }
}
- if (dataId == resultKind) {
- _validationError(
- "Circular dependency on '$dataId' in step '${step.runtimeType}'");
+ for (var dataId in step.moduleDataNeeded) {
+ if (!previousKinds.containsKey(dataId)) {
+ _validationError(
+ "Step '${step.runtimeType}' needs data '${dataId}', but the "
+ "data is not produced by a preceding step.");
+ }
+ if (dataId == resultKind) {
+ _validationError("Circular dependency on '$dataId' "
+ "in step '${step.runtimeType}'");
+ }
}
}
}
@@ -147,7 +152,7 @@
}
}
await runStep(step, module, visibleData);
- (computedData[module] ??= {}).add(step.resultId);
+ (computedData[module] ??= {}).addAll(step.resultData);
}
Future<void> runStep(
diff --git a/pkg/modular_test/test/io_pipeline_test.dart b/pkg/modular_test/test/io_pipeline_test.dart
index 6e26e91..dd3d01f 100644
--- a/pkg/modular_test/test/io_pipeline_test.dart
+++ b/pkg/modular_test/test/io_pipeline_test.dart
@@ -73,6 +73,15 @@
MainOnlyStep(action, inputId, depId, resultId, requestDependenciesData);
@override
+ IOModularStep createTwoOutputStep(
+ {String Function(String) action1,
+ String Function(String) action2,
+ DataId inputId,
+ DataId result1Id,
+ DataId result2Id}) =>
+ TwoOutputStep(action1, action2, inputId, result1Id, result2Id);
+
+ @override
String getResult(covariant IOPipeline pipeline, Module m, DataId dataId) {
var folderUri = pipeline.tmpFoldersForTesting[dataId];
var file = File.fromUri(folderUri.resolve("${m.name}.${dataId.name}"));
@@ -95,6 +104,7 @@
final bool needsSources;
List<DataId> get dependencyDataNeeded => const [];
List<DataId> get moduleDataNeeded => const [];
+ List<DataId> get resultData => [resultId];
bool get onlyOnMain => false;
SourceOnlyStep(this.action, this.resultId, this.needsSources);
@@ -119,6 +129,7 @@
bool get needsSources => false;
List<DataId> get dependencyDataNeeded => const [];
final List<DataId> moduleDataNeeded;
+ List<DataId> get resultData => [resultId];
final DataId resultId;
final DataId inputId;
bool get onlyOnMain => false;
@@ -137,10 +148,41 @@
}
}
+class TwoOutputStep implements IOModularStep {
+ final String Function(String) action1;
+ final String Function(String) action2;
+ bool get needsSources => false;
+ List<DataId> get dependencyDataNeeded => const [];
+ List<DataId> get moduleDataNeeded => [inputId];
+ List<DataId> get resultData => [result1Id, result2Id];
+ final DataId result1Id;
+ final DataId result2Id;
+ final DataId inputId;
+ bool get onlyOnMain => false;
+
+ TwoOutputStep(
+ this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
+
+ @override
+ Future<void> execute(
+ Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ var inputData = await _readHelper(module, root, inputId, toUri);
+ var result1 =
+ inputData == null ? "data for $module was null" : action1(inputData);
+ var result2 =
+ inputData == null ? "data for $module was null" : action2(inputData);
+ await File.fromUri(root.resolveUri(toUri(module, result1Id)))
+ .writeAsString(result1);
+ await File.fromUri(root.resolveUri(toUri(module, result2Id)))
+ .writeAsString(result2);
+ }
+}
+
class LinkStep implements IOModularStep {
bool get needsSources => false;
final List<DataId> dependencyDataNeeded;
List<DataId> get moduleDataNeeded => [inputId];
+ List<DataId> get resultData => [resultId];
final String Function(String, List<String>) action;
final DataId inputId;
final DataId depId;
@@ -169,6 +211,7 @@
bool get needsSources => false;
final List<DataId> dependencyDataNeeded;
List<DataId> get moduleDataNeeded => [inputId];
+ List<DataId> get resultData => [resultId];
final String Function(String, List<String>) action;
final DataId inputId;
final DataId depId;
diff --git a/pkg/modular_test/test/memory_pipeline_test.dart b/pkg/modular_test/test/memory_pipeline_test.dart
index 94e53dd..ba406e1 100644
--- a/pkg/modular_test/test/memory_pipeline_test.dart
+++ b/pkg/modular_test/test/memory_pipeline_test.dart
@@ -60,6 +60,15 @@
MainOnlyStep(action, inputId, depId, resultId, requestDependenciesData);
@override
+ MemoryModularStep createTwoOutputStep(
+ {String Function(String) action1,
+ String Function(String) action2,
+ DataId inputId,
+ DataId result1Id,
+ DataId result2Id}) =>
+ TwoOutputStep(action1, action2, inputId, result1Id, result2Id);
+
+ @override
String getResult(covariant MemoryPipeline pipeline, Module m, DataId dataId) {
return pipeline.resultsForTesting[m][dataId];
}
@@ -73,17 +82,18 @@
final bool needsSources;
List<DataId> get dependencyDataNeeded => const [];
List<DataId> get moduleDataNeeded => const [];
+ List<DataId> get resultData => [resultId];
bool get onlyOnMain => false;
SourceOnlyStep(this.action, this.resultId, this.needsSources);
- Future<Object> execute(Module module, SourceProvider sourceProvider,
- ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
Map<Uri, String> sources = {};
for (var uri in module.sources) {
sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
}
- return Future.value(action(sources));
+ return Future.value({resultId: action(sources)});
}
}
@@ -92,6 +102,7 @@
bool get needsSources => false;
List<DataId> get dependencyDataNeeded => const [];
final List<DataId> moduleDataNeeded;
+ List<DataId> get resultData => [resultId];
final DataId resultId;
final DataId inputId;
bool get onlyOnMain => false;
@@ -99,11 +110,40 @@
ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
: moduleDataNeeded = requestInput ? [inputId] : [];
- Future<Object> execute(Module module, SourceProvider sourceProvider,
- ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
var inputData = dataProvider(module, inputId) as String;
- if (inputData == null) return Future.value("data for $module was null");
- return Future.value(action(inputData));
+ if (inputData == null)
+ return Future.value({resultId: "data for $module was null"});
+ return Future.value({resultId: action(inputData)});
+ }
+}
+
+class TwoOutputStep implements MemoryModularStep {
+ final String Function(String) action1;
+ final String Function(String) action2;
+ bool get needsSources => false;
+ List<DataId> get dependencyDataNeeded => const [];
+ List<DataId> get moduleDataNeeded => [inputId];
+ List<DataId> get resultData => [result1Id, result2Id];
+ final DataId result1Id;
+ final DataId result2Id;
+ final DataId inputId;
+ bool get onlyOnMain => false;
+
+ TwoOutputStep(
+ this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
+
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ var inputData = dataProvider(module, inputId) as String;
+ if (inputData == null)
+ return Future.value({
+ result1Id: "data for $module was null",
+ result2Id: "data for $module was null",
+ });
+ return Future.value(
+ {result1Id: action1(inputData), result2Id: action2(inputData)});
}
}
@@ -115,19 +155,20 @@
final DataId inputId;
final DataId depId;
final DataId resultId;
+ List<DataId> get resultData => [resultId];
bool get onlyOnMain => false;
LinkStep(this.action, this.inputId, this.depId, this.resultId,
bool requestDependencies)
: dependencyDataNeeded = requestDependencies ? [depId] : [];
- Future<Object> execute(Module module, SourceProvider sourceProvider,
- ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
List<String> depsData = module.dependencies
.map((d) => dataProvider(d, depId) as String)
.toList();
var inputData = dataProvider(module, inputId) as String;
- return Future.value(action(inputData, depsData));
+ return Future.value({resultId: action(inputData, depsData)});
}
}
@@ -139,18 +180,19 @@
final DataId inputId;
final DataId depId;
final DataId resultId;
+ List<DataId> get resultData => [resultId];
bool get onlyOnMain => true;
MainOnlyStep(this.action, this.inputId, this.depId, this.resultId,
bool requestDependencies)
: dependencyDataNeeded = requestDependencies ? [depId] : [];
- Future<Object> execute(Module module, SourceProvider sourceProvider,
- ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(Module module,
+ SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
List<String> depsData = computeTransitiveDependencies(module)
.map((d) => dataProvider(d, depId) as String)
.toList();
var inputData = dataProvider(module, inputId) as String;
- return Future.value(action(inputData, depsData));
+ return Future.value({resultId: action(inputData, depsData)});
}
}
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
index ceb2a3a..b09e611 100644
--- a/pkg/modular_test/test/pipeline_common.dart
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -70,6 +70,15 @@
DataId resultId,
bool requestDependenciesData: true});
+ /// Create a step that applies [action1] and [action2] on the module [inputId]
+ /// data, and emits two results with the given [result1Id] and [result2Id].
+ S createTwoOutputStep(
+ {String Function(String) action1,
+ String Function(String) action2,
+ DataId inputId,
+ DataId result1Id,
+ DataId result2Id});
+
/// Return the result data produced by a modular step.
String getResult(Pipeline<S> pipeline, Module m, DataId dataId);
@@ -104,7 +113,7 @@
testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
await pipeline.run(singleModuleInput);
- expect(testStrategy.getResult(pipeline, m1, concatStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _concatId),
"a1.dart: A1\na2.dart: A2\n");
await testStrategy.cleanup(pipeline);
});
@@ -114,7 +123,7 @@
action: _concat, resultId: _concatId, requestSources: false);
var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
await pipeline.run(singleModuleInput);
- expect(testStrategy.getResult(pipeline, m1, concatStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _concatId),
"a1.dart: null\na2.dart: null\n");
await testStrategy.cleanup(pipeline);
});
@@ -124,9 +133,9 @@
testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
var pipeline = await testStrategy.createPipeline(sources, <S>[concatStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, concatStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _concatId),
"a1.dart: A1\na2.dart: A2\n");
- expect(testStrategy.getResult(pipeline, m2, concatStep.resultId),
+ expect(testStrategy.getResult(pipeline, m2, _concatId),
"b/b1.dart: B1\nb/b2.dart: B2\n");
await testStrategy.cleanup(pipeline);
});
@@ -139,9 +148,9 @@
var pipeline = await testStrategy
.createPipeline(sources, <S>[concatStep, lowercaseStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, lowercaseStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _lowercaseId),
"a1.dart: a1\na2.dart: a2\n");
- expect(testStrategy.getResult(pipeline, m2, lowercaseStep.resultId),
+ expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
"b/b1.dart: b1\nb/b2.dart: b2\n");
await testStrategy.cleanup(pipeline);
});
@@ -157,13 +166,32 @@
var pipeline = await testStrategy
.createPipeline(sources, <S>[concatStep, lowercaseStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, lowercaseStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _lowercaseId),
"data for [module a] was null");
- expect(testStrategy.getResult(pipeline, m2, lowercaseStep.resultId),
+ expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
"data for [module b] was null");
await testStrategy.cleanup(pipeline);
});
+ test('all outputs of a step are created together', () async {
+ var concatStep =
+ testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
+ var twoOutputStep = testStrategy.createTwoOutputStep(
+ action1: _lowercase,
+ action2: _uppercase,
+ inputId: _concatId,
+ result1Id: _lowercaseId,
+ result2Id: _uppercaseId);
+ var pipeline = await testStrategy
+ .createPipeline(sources, <S>[concatStep, twoOutputStep]);
+ await pipeline.run(twoModuleInput);
+ expect(testStrategy.getResult(pipeline, m2, _lowercaseId),
+ "b/b1.dart: b1\nb/b2.dart: b2\n");
+ expect(testStrategy.getResult(pipeline, m2, _uppercaseId),
+ "B/B1.DART: B1\nB/B2.DART: B2\n");
+ await testStrategy.cleanup(pipeline);
+ });
+
test('can read same-step results of dependencies if requested', () async {
var concatStep =
testStrategy.createSourceOnlyStep(action: _concat, resultId: _concatId);
@@ -177,9 +205,8 @@
var pipeline = await testStrategy.createPipeline(
sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
- "a1 a1\na2 a2\n");
- expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+ expect(testStrategy.getResult(pipeline, m2, _joinId),
"a1 a1\na2 a2\n\nb/b1 b1\nb/b2 b2\n");
await testStrategy.cleanup(pipeline);
});
@@ -199,9 +226,8 @@
var pipeline = await testStrategy.createPipeline(
sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
- "a1 a1\na2 a2\n");
- expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+ expect(testStrategy.getResult(pipeline, m2, _joinId),
"null\nb/b1 b1\nb/b2 b2\n");
await testStrategy.cleanup(pipeline);
});
@@ -219,9 +245,8 @@
var pipeline = await testStrategy.createPipeline(
sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
- "a1 a1\na2 a2\n");
- expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+ expect(testStrategy.getResult(pipeline, m2, _joinId),
"a1.dart: a1\na2.dart: a2\n\nb/b1 b1\nb/b2 b2\n");
await testStrategy.cleanup(pipeline);
});
@@ -241,9 +266,8 @@
var pipeline = await testStrategy.createPipeline(
sources, <S>[concatStep, lowercaseStep, replaceJoinStep]);
await pipeline.run(twoModuleInput);
- expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
- "a1 a1\na2 a2\n");
- expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+ expect(testStrategy.getResult(pipeline, m1, _joinId), "a1 a1\na2 a2\n");
+ expect(testStrategy.getResult(pipeline, m2, _joinId),
"null\nb/b1 b1\nb/b2 b2\n");
await testStrategy.cleanup(pipeline);
});
@@ -290,6 +314,7 @@
DataId _concatId = const DataId("concat");
DataId _lowercaseId = const DataId("lowercase");
+DataId _uppercaseId = const DataId("uppercase");
DataId _joinId = const DataId("join");
String _concat(Map<Uri, String> sources) {
@@ -301,6 +326,7 @@
}
String _lowercase(String contents) => contents.toLowerCase();
+String _uppercase(String contents) => contents.toUpperCase();
String _replaceAndJoin(String moduleData, List<String> depContents) {
var buffer = new StringBuffer();
diff --git a/pkg/modular_test/test/validate_test.dart b/pkg/modular_test/test/validate_test.dart
index 152271a..8394dfe 100644
--- a/pkg/modular_test/test/validate_test.dart
+++ b/pkg/modular_test/test/validate_test.dart
@@ -18,12 +18,12 @@
var id3 = DataId("data_c");
validateSteps([
ModularStep(
- needsSources: true, dependencyDataNeeded: [id1], resultId: id1),
- ModularStep(moduleDataNeeded: [id1], resultId: id2),
+ needsSources: true, dependencyDataNeeded: [id1], resultData: [id1]),
+ ModularStep(moduleDataNeeded: [id1], resultData: [id2]),
ModularStep(
moduleDataNeeded: [id2],
dependencyDataNeeded: [id1, id3],
- resultId: id3),
+ resultData: [id3]),
]);
});
@@ -31,23 +31,31 @@
var id1 = DataId("data_a");
expect(
() => validateSteps([
- ModularStep(moduleDataNeeded: [id1], resultId: id1),
+ ModularStep(moduleDataNeeded: [id1], resultData: [id1]),
]),
throwsA(TypeMatcher<InvalidPipelineError>()));
});
+ test('some results must be declared', () {
+ expect(() => validateSteps([ModularStep()]),
+ throwsA(TypeMatcher<InvalidPipelineError>()));
+ expect(() => validateSteps([ModularStep(resultData: [])]),
+ throwsA(TypeMatcher<InvalidPipelineError>()));
+ });
+
test('out of order dependencies are not allowed', () {
var id1 = DataId("data_a");
var id2 = DataId("data_b");
validateSteps([
- ModularStep(resultId: id1), // id1 must be produced before it is consumed.
- ModularStep(dependencyDataNeeded: [id1], resultId: id2),
+ // id1 must be produced before it is consumed.
+ ModularStep(resultData: [id1]),
+ ModularStep(dependencyDataNeeded: [id1], resultData: [id2]),
]);
expect(
() => validateSteps([
- ModularStep(dependencyDataNeeded: [id1], resultId: id2),
- ModularStep(resultId: id1),
+ ModularStep(dependencyDataNeeded: [id1], resultData: [id2]),
+ ModularStep(resultData: [id1]),
]),
throwsA(TypeMatcher<InvalidPipelineError>()));
});
@@ -56,8 +64,8 @@
var id1 = DataId("data_a");
expect(
() => validateSteps([
- ModularStep(resultId: id1),
- ModularStep(resultId: id1),
+ ModularStep(resultData: [id1]),
+ ModularStep(resultData: [id1]),
]),
throwsA(TypeMatcher<InvalidPipelineError>()));
});
diff --git a/tests/compiler/dart2js/modular/modular_test.dart b/tests/compiler/dart2js/modular/modular_test.dart
index 2f98259..eb7c1d7 100644
--- a/tests/compiler/dart2js/modular/modular_test.dart
+++ b/tests/compiler/dart2js/modular/modular_test.dart
@@ -52,11 +52,12 @@
const dillId = const DataId("dill");
const jsId = const DataId("js");
+const txtId = const DataId("txt");
// Step that compiles sources in a module to a .dill file.
class SourceToDillStep implements IOModularStep {
@override
- DataId get resultId => dillId;
+ List<DataId> get resultData => const [dillId];
@override
bool get needsSources => true;
@@ -155,7 +156,7 @@
// all transitive modules as inputs.
class CompileFromDillStep implements IOModularStep {
@override
- DataId get resultId => jsId;
+ List<DataId> get resultData => const [jsId];
@override
bool get needsSources => false;
@@ -182,7 +183,7 @@
'package:compiler/src/dart2js.dart',
'${toUri(module, dillId)}',
'--dill-dependencies=${dillDependencies.join(',')}',
- '--out=${toUri(module, resultId)}',
+ '--out=${toUri(module, jsId)}',
];
var result =
await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
@@ -194,7 +195,7 @@
/// Step that runs the output of dart2js in d8 and saves the output.
class RunD8 implements IOModularStep {
@override
- DataId get resultId => const DataId("txt");
+ List<DataId> get resultData => const [txtId];
@override
bool get needsSources => false;
@@ -224,7 +225,7 @@
_checkExitCode(result, this, module);
- await File.fromUri(root.resolveUri(toUri(module, resultId)))
+ await File.fromUri(root.resolveUri(toUri(module, txtId)))
.writeAsString(result.stdout);
}
}