Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions lib/src/io_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,25 +122,26 @@ class MultiFutureTracker<T> {
/// Wait until fewer or equal to this many Futures are outstanding.
Future<void> _waitUntil(int max) async {
while (_trackedFutures.length > max) {
try {
await Future.any(_trackedFutures);
// The empty catch is OK because we're just counting future completions
// and we don't care about errors (the original caller of
// addFutureToClosure is responsible for those).
} catch (e) {} // ignore: empty_catches
await Future.any(_trackedFutures);
}
}

/// Generates a [Future] from the given closure and adds it to the queue,
/// once the queue is sufficiently empty. The returned future completes
/// when the generated [Future] has been added to the queue.
///
/// If the closure does not handle its own exceptions, other calls to
/// [addFutureFromClosure] or [wait] may trigger an exception.
Future<void> addFutureFromClosure(Future<T> Function() closure) async {
await _waitUntil(parallel - 1);
Future<void> future = closure();
_trackedFutures.add(future);
// ignore: unawaited_futures
future.then((f) => _trackedFutures.remove(future),
onError: (s, e) => _trackedFutures.remove(future));
future.then((f) {
_trackedFutures.remove(future);
}, onError: (s, e) {
_trackedFutures.remove(future);
});
}

/// Wait until all futures added so far have completed.
Expand Down
3 changes: 2 additions & 1 deletion lib/src/model_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ bool matchGlobs(List<String> globs, String fullName, {bool isWindows}) {
}

return filteredGlobs.any((g) =>
Glob(g, context: isWindows ? path.windows : null).matches(fullName));
Glob(g, context: isWindows ? path.windows : path.posix)
.matches(fullName));
}

/// Returns the [AstNode] for a given [Element].
Expand Down
45 changes: 31 additions & 14 deletions test/io_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,31 @@ void main() {
/// [MultiFutureTracker.addFutureFromClosure].
test('no deadlock when delayed exceptions fire in closures', () async {
var sharedTracker = MultiFutureTracker(2);
var t =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => t);
expect(t, throwsA(const TypeMatcher<Exception>()));
var u =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => u);
expect(u, throwsA(const TypeMatcher<Exception>()));
var v =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => v);
expect(v, throwsA(const TypeMatcher<Exception>()));
expect(() async {
var t =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => t);
return t;
}, throwsA(const TypeMatcher<Exception>()));
expect(() async {
var t =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => t);
return t;
}, throwsA(const TypeMatcher<Exception>()));
expect(() async {
var t =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
// ignore: empty_catches
await sharedTracker.addFutureFromClosure(() => t);
return t;
}, throwsA(const TypeMatcher<Exception>()));
expect(() async {
var t =
Future.delayed(Duration(milliseconds: 10), () => throw Exception());
await sharedTracker.addFutureFromClosure(() => t);
return t;
}, throwsA(const TypeMatcher<Exception>()));

/// We deadlock here if the exception is not handled properly.
await sharedTracker.wait();
Expand All @@ -55,8 +68,12 @@ void main() {
var completed = <int>{};
var tracker = MultiFutureTracker(1);
await tracker.addFutureFromClosure(() async => completed.add(0));
await tracker.addFutureFromClosure(() async => throw Exception());
await tracker.addFutureFromClosure(() async => throw Exception());
await tracker
.addFutureFromClosure(() async => throw Exception())
.catchError((e) {});
await tracker
.addFutureFromClosure(() async => throw Exception())
.catchError((e) {});
await tracker.addFutureFromClosure(() async => completed.add(3));
await tracker.wait();
expect(completed.length, equals(2));
Expand Down
2 changes: 2 additions & 0 deletions testing/sky_engine/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: sky_engine
description: package with embedder yaml
version: 0.0.1
environment:
sdk: '>=2.0.0 <3.0.0'
2 changes: 2 additions & 0 deletions testing/test_package_bad/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: test_package_bad
description: Best package ever.
version: 0.0.1
environment:
sdk: '>=2.0.0 <3.0.0'
2 changes: 2 additions & 0 deletions testing/test_package_custom_templates/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: test_package_custom_templates
version: 0.0.1
description: A simple console application.
environment:
sdk: '>=2.0.0 <3.0.0'
#dependencies:
# foo_bar: '>=1.0.0 <2.0.0'
2 changes: 1 addition & 1 deletion testing/test_package_doc_errors/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ name: test_package_doc_errors
version: 0.0.1
description: A simple console application.
environment:
sdk: <=3.0.0
sdk: '>=2.0.0 <3.0.0'
3 changes: 2 additions & 1 deletion testing/test_package_experiments/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: test_package_experiments
version: 0.0.1
sdk: '>=2.9.0-dev.0 <2.10.0'
environment:
sdk: '>=2.10.0-0 <3.0.0'
description: Experimental flags are tested here.
2 changes: 1 addition & 1 deletion testing/test_package_export_error/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ name: test_package_export_error
version: 0.0.1
description: A simple console application.
environment:
sdk: <=3.0.0
sdk: '>=2.0.0 <3.0.0'
2 changes: 1 addition & 1 deletion testing/test_package_extensions/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ name: test_package_extensions
version: 0.0.1
description: A simple console application.
environment:
sdk: <=3.0.0
sdk: '>=2.0.0 <3.0.0'
2 changes: 1 addition & 1 deletion testing/test_package_import_export_error/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: test_package_import_export_error
version: 0.0.1
description: A simple console application.
environment:
sdk: <=3.0.0
sdk: '>=2.0.0 <3.0.0'

dependencies:
test_package_export_error:
Expand Down
2 changes: 2 additions & 0 deletions testing/test_package_include_exclude/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
name: test_package_include_exclude
version: 0.0.1
environment:
sdk: '>=2.0.0 <3.0.0'
2 changes: 2 additions & 0 deletions testing/test_package_minimum/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ name: test_package_minimum
homepage: http://github.com/dart-lang
description: The only package with no bugs.
version: 0.0.3
environment:
sdk: '>=2.0.0 <3.0.0'
2 changes: 1 addition & 1 deletion testing/test_package_tool_error/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ name: test_package_tool_error
version: 0.0.1
description: A simple console application.
environment:
sdk: <=3.0.0
sdk: '>=2.0.0 <3.0.0'
2 changes: 1 addition & 1 deletion tool/grind.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ Future<void> testDart2(Iterable<File> tests) async {
}

return CoverageSubprocessLauncher.generateCoverageToFile(
PhysicalResourceProvider.INSTANCE.getFile('lcov.info'),
PhysicalResourceProvider.INSTANCE.getFile(path.canonicalize('lcov.info')),
PhysicalResourceProvider.INSTANCE);
}

Expand Down