Index: lib/src/runner/loader.dart |
diff --git a/lib/src/runner/loader.dart b/lib/src/runner/loader.dart |
index b148e73c1c3a40342e44668da00332f8cc921aa8..afff40a5544d3fd99a3228a7d783c15ee01628e4 100644 |
--- a/lib/src/runner/loader.dart |
+++ b/lib/src/runner/loader.dart |
@@ -80,24 +80,29 @@ class Loader { |
/// Loads all test suites in [dir]. |
/// |
- /// This will load tests from files that end in "_test.dart". |
- Future<List<Suite>> loadDir(String dir) { |
- return Future.wait(new Directory(dir).listSync(recursive: true) |
+ /// This will load tests from files that end in "_test.dart". Any tests that |
+ /// fail to load will be emitted as [LoadException]s. |
+ Stream<Suite> loadDir(String dir) { |
+ return mergeStreams(new Directory(dir).listSync(recursive: true) |
.map((entry) { |
- if (entry is! File) return new Future.value([]); |
- if (!entry.path.endsWith("_test.dart")) return new Future.value([]); |
- if (p.split(entry.path).contains('packages')) return new Future.value([]); |
+ if (entry is! File) return new Stream.fromIterable([]); |
+ |
+ if (!entry.path.endsWith("_test.dart")) { |
+ return new Stream.fromIterable([]); |
+ } |
+ |
+ if (p.split(entry.path).contains('packages')) { |
+ return new Stream.fromIterable([]); |
+ } |
- // TODO(nweiz): Provide a way for the caller to gracefully handle some |
- // suites failing to load without stopping the rest. |
return loadFile(entry.path); |
- })).then((suites) => flatten(suites)); |
+ })); |
} |
/// Loads a test suite from the file at [path]. |
/// |
- /// This will throw a [LoadException] if the file fails to load. |
- Future<List<Suite>> loadFile(String path) { |
+ /// This will emit a [LoadException] if the file fails to load. |
+ Stream<Suite> loadFile(String path) { |
var metadata; |
try { |
metadata = parseMetadata(path); |
@@ -105,14 +110,18 @@ class Loader { |
// Ignore the analyzer's error, since its formatting is much worse than |
// the VM's or dart2js's. |
metadata = new Metadata(); |
- } on FormatException catch (error) { |
- throw new LoadException(path, error); |
+ } on FormatException catch (error, stackTrace) { |
+ return new Stream.fromFuture( |
+ new Future.error(new LoadException(path, error), stackTrace)); |
} |
- return Future.wait(_platforms.map((platform) { |
- return new Future.sync(() { |
- if (!metadata.testOn.evaluate(platform, os: currentOS)) return null; |
+ var controller = new StreamController(); |
+ Future.forEach(_platforms, (platform) { |
+ if (!metadata.testOn.evaluate(platform, os: currentOS)) { |
+ return new Future.value(); |
+ } |
+ return new Future.sync(() { |
if (_pubServeUrl != null && !p.isWithin('test', path)) { |
throw new LoadException(path, |
'When using "pub serve", all test files must be in test/.'); |
@@ -122,10 +131,14 @@ class Loader { |
assert(platform == TestPlatform.vm); |
return _loadVmFile(path); |
}).then((suite) { |
- if (suite == null) return null; |
- return suite.change(metadata: metadata).filter(platform, os: currentOS); |
- }); |
- })).then((suites) => suites.where((suite) => suite != null).toList()); |
+ if (suite == null) return; |
+ |
+ controller.add(suite |
+ .change(metadata: metadata).filter(platform, os: currentOS)); |
+ }).catchError(controller.addError); |
+ }).then((_) => controller.close()); |
+ |
+ return controller.stream; |
} |
/// Load the test suite at [path] in a browser. |