Index: pkg/scheduled_test/test/utils.dart |
diff --git a/pkg/scheduled_test/test/utils.dart b/pkg/scheduled_test/test/utils.dart |
index 8f0bd2373f3bdcc232e4166f05d899f19acc035d..725087999097546bf56590e40bb6c83b24089307 100644 |
--- a/pkg/scheduled_test/test/utils.dart |
+++ b/pkg/scheduled_test/test/utils.dart |
@@ -4,6 +4,7 @@ |
library test_utils; |
+import 'dart:io'; |
import 'dart:async'; |
import '../lib/src/utils.dart'; |
@@ -44,3 +45,37 @@ Future sleep(int milliseconds) { |
}); |
return completer.future; |
} |
+ |
+// TODO(nweiz): Remove this when issue 9252 is fixed. |
+/// Asynchronously recursively deletes [dir]. Returns a [Future] that completes |
+/// when the deletion is done. |
+Future deleteDir(String dir) => |
+ _attemptRetryable(() => new Directory(dir).delete(recursive: true)); |
+ |
+/// On Windows, we sometimes get failures where the directory is still in use |
+/// when we try to do something with it. This is usually because the OS hasn't |
+/// noticed yet that a process using that directory has closed. To be a bit |
+/// more resilient, we wait and retry a few times. |
+/// |
+/// Takes a [callback] which returns a future for the operation being attempted. |
+/// If that future completes with an error, it will slepp and then [callback] |
+/// will be invoked again to retry the operation. It will try a few times before |
+/// giving up. |
+Future _attemptRetryable(Future callback()) { |
+ // Only do lame retry logic on Windows. |
+ if (Platform.operatingSystem != 'windows') return callback(); |
+ |
+ var attempts = 0; |
+ makeAttempt(_) { |
+ attempts++; |
+ return callback().catchError((e) { |
+ if (attempts >= 10) { |
+ throw 'Could not complete operation. Gave up after $attempts attempts.'; |
+ } |
+ |
+ return sleep(500).then(makeAttempt); |
+ }); |
+ } |
+ |
+ return makeAttempt(null); |
+} |