Ensure subfolders in input sources paths are created first

Change-Id: I35db42f4fc396f33445528bea6e7c9bcc8f8c10e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102141
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 b5bba4f..6ce6d42 100644
--- a/pkg/modular_test/lib/src/io_pipeline.dart
+++ b/pkg/modular_test/lib/src/io_pipeline.dart
@@ -69,8 +69,9 @@
     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());
+        var copyUri = folder.uri.resolveUri(uri);
+        await File.fromUri(copyUri).create(recursive: true);
+        await File.fromUri(originalUri).copy(copyUri.toFilePath());
       }
     }
 
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
index d99e687..e3d6eb6 100644
--- a/pkg/modular_test/test/pipeline_common.dart
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -76,8 +76,8 @@
 
   var m1 = Module("a", const [], testStrategy.testRootUri,
       [Uri.parse("a1.dart"), Uri.parse("a2.dart")]);
-  var m2 = Module("b", [m1], testStrategy.testRootUri.resolve('b/'),
-      [Uri.parse("b1.dart"), Uri.parse("b2.dart")]);
+  var m2 = Module("b", [m1], testStrategy.testRootUri,
+      [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")]);
 
   var singleModuleInput = ModularTest([m1], m1);
   var multipleModulesInput = ModularTest([m1, m2], m2);
@@ -110,7 +110,7 @@
     expect(testStrategy.getResult(pipeline, m1, concatStep.resultId),
         "a1.dart: A1\na2.dart: A2\n");
     expect(testStrategy.getResult(pipeline, m2, concatStep.resultId),
-        "b1.dart: B1\nb2.dart: B2\n");
+        "b/b1.dart: B1\nb/b2.dart: B2\n");
     await testStrategy.cleanup(pipeline);
   });
 
@@ -125,7 +125,7 @@
     expect(testStrategy.getResult(pipeline, m1, lowercaseStep.resultId),
         "a1.dart: a1\na2.dart: a2\n");
     expect(testStrategy.getResult(pipeline, m2, lowercaseStep.resultId),
-        "b1.dart: b1\nb2.dart: b2\n");
+        "b/b1.dart: b1\nb/b2.dart: b2\n");
     await testStrategy.cleanup(pipeline);
   });
 
@@ -163,7 +163,7 @@
     expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
         "a1 a1\na2 a2\n");
     expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
-        "a1 a1\na2 a2\n\nb1 b1\nb2 b2\n");
+        "a1 a1\na2 a2\n\nb/b1 b1\nb/b2 b2\n");
     await testStrategy.cleanup(pipeline);
   });
 
@@ -185,7 +185,7 @@
     expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
         "a1 a1\na2 a2\n");
     expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
-        "null\nb1 b1\nb2 b2\n");
+        "null\nb/b1 b1\nb/b2 b2\n");
     await testStrategy.cleanup(pipeline);
   });
 
@@ -205,7 +205,7 @@
     expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
         "a1 a1\na2 a2\n");
     expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
-        "a1.dart: a1\na2.dart: a2\n\nb1 b1\nb2 b2\n");
+        "a1.dart: a1\na2.dart: a2\n\nb/b1 b1\nb/b2 b2\n");
     await testStrategy.cleanup(pipeline);
   });
 
@@ -227,7 +227,7 @@
     expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
         "a1 a1\na2 a2\n");
     expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
-        "null\nb1 b1\nb2 b2\n");
+        "null\nb/b1 b1\nb/b2 b2\n");
     await testStrategy.cleanup(pipeline);
   });
 }