Remove scheduled test (#44)
diff --git a/.travis.yml b/.travis.yml
index deb901b..4c8c5ff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,10 @@
language: dart
-dart:
- - dev
- - stable
+dart: dev
dart_task:
- - test
-
-matrix:
- include:
- - dart: dev
- dart_task: dartfmt
- # Only care about being analyzer clean for dev and stable
- - dart: dev
- dart_task: dartanalyzer
- - dart: stable
- dart_task: dartanalyzer
+ - test
+ - dartfmt
+ - dartanalyzer
# Only building master means that we don't run two builds for each pull request.
branches:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4ca0ba..5e6c3d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.9.7+6
+
+* Internal changes only, namely removing dep on scheduled test.
+
# 0.9.7+5
* Fix an analysis warning.
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index ef39eef..18b53c9 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -71,18 +71,6 @@
/// under the covers.
Future newFuture(callback()) => new Future.value().then((_) => callback());
-/// Returns a [Future] that completes after pumping the event queue [times]
-/// times. By default, this should pump the event queue enough times to allow
-/// any code to run, as long as it's not waiting on some external event.
-Future pumpEventQueue([int times = 20]) {
- if (times == 0) return new Future.value();
- // We use a delayed future to allow microtask events to finish. The
- // Future.value or Future() constructors use scheduleMicrotask themselves and
- // would therefore not wait for microtask callbacks that are scheduled after
- // invoking this method.
- return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
-}
-
/// A stream transformer that batches all events that are sent at the same time.
///
/// When multiple events are synchronously added to a stream controller, the
diff --git a/pubspec.yaml b/pubspec.yaml
index d1260d5..62abc69 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: watcher
-version: 0.9.7+6.dev
+version: 0.9.7+6
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/watcher
description: >
@@ -12,5 +12,5 @@
path: '>=0.9.0 <2.0.0'
dev_dependencies:
benchmark_harness: '^1.0.4'
- scheduled_test: '^0.12.0'
- test: '^0.12.18+1'
+ test: '^0.12.29'
+ test_descriptor: '^1.0.0'
diff --git a/test/directory_watcher/linux_test.dart b/test/directory_watcher/linux_test.dart
index 34e6896..25c5504 100644
--- a/test/directory_watcher/linux_test.dart
+++ b/test/directory_watcher/linux_test.dart
@@ -4,7 +4,7 @@
@TestOn('linux')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/linux.dart';
import 'package:watcher/watcher.dart';
@@ -14,8 +14,6 @@
void main() {
watcherFactory = (dir) => new LinuxDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () {
@@ -24,15 +22,15 @@
});
test('emits events for many nested files moved out then immediately back in',
- () {
+ () async {
withPermutations(
(i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt"));
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameDir("dir/sub", "sub");
renameDir("sub", "dir/sub");
- allowEither(() {
+ await allowEither(() {
inAnyOrder(withPermutations(
(i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")));
diff --git a/test/directory_watcher/mac_os_test.dart b/test/directory_watcher/mac_os_test.dart
index 46b7ca2..8fa76fd 100644
--- a/test/directory_watcher/mac_os_test.dart
+++ b/test/directory_watcher/mac_os_test.dart
@@ -4,7 +4,7 @@
@TestOn('mac-os')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/mac_os.dart';
import 'package:watcher/watcher.dart';
@@ -14,8 +14,6 @@
void main() {
watcherFactory = (dir) => new MacOSDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () {
@@ -25,28 +23,28 @@
test(
'does not notify about the watched directory being deleted and '
- 'recreated immediately before watching', () {
+ 'recreated immediately before watching', () async {
createDir("dir");
writeFile("dir/old.txt");
deleteDir("dir");
createDir("dir");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
writeFile("dir/newer.txt");
- expectAddEvent("dir/newer.txt");
+ await expectAddEvent("dir/newer.txt");
});
test('emits events for many nested files moved out then immediately back in',
- () {
+ () async {
withPermutations(
(i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt"));
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameDir("dir/sub", "sub");
renameDir("sub", "dir/sub");
- allowEither(() {
+ await allowEither(() {
inAnyOrder(withPermutations(
(i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")));
diff --git a/test/directory_watcher/polling_test.dart b/test/directory_watcher/polling_test.dart
index 0192b25..39bbbef 100644
--- a/test/directory_watcher/polling_test.dart
+++ b/test/directory_watcher/polling_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
import 'shared.dart';
@@ -13,16 +13,14 @@
watcherFactory = (dir) => new PollingDirectoryWatcher(dir,
pollingDelay: new Duration(milliseconds: 100));
- setUp(createSandbox);
-
sharedTests();
- test('does not notify if the modification time did not change', () {
+ test('does not notify if the modification time did not change', () async {
writeFile("a.txt", contents: "before");
writeFile("b.txt", contents: "before");
- startWatcher();
+ await startWatcher();
writeFile("a.txt", contents: "after", updateModified: false);
writeFile("b.txt", contents: "after");
- expectModifyEvent("b.txt");
+ await expectModifyEvent("b.txt");
});
}
diff --git a/test/directory_watcher/shared.dart b/test/directory_watcher/shared.dart
index 2bdc077..2c0f441 100644
--- a/test/directory_watcher/shared.dart
+++ b/test/directory_watcher/shared.dart
@@ -2,136 +2,138 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/utils.dart';
import '../utils.dart';
void sharedTests() {
- test('does not notify for files that already exist when started', () {
+ test('does not notify for files that already exist when started', () async {
// Make some pre-existing files.
writeFile("a.txt");
writeFile("b.txt");
- startWatcher();
+ await startWatcher();
// Change one after the watcher is running.
writeFile("b.txt", contents: "modified");
// We should get a modify event for the changed file, but no add events
// for them before this.
- expectModifyEvent("b.txt");
+ await expectModifyEvent("b.txt");
});
- test('notifies when a file is added', () {
- startWatcher();
+ test('notifies when a file is added', () async {
+ await startWatcher();
writeFile("file.txt");
- expectAddEvent("file.txt");
+ await expectAddEvent("file.txt");
});
- test('notifies when a file is modified', () {
+ test('notifies when a file is modified', () async {
writeFile("file.txt");
- startWatcher();
+ await startWatcher();
writeFile("file.txt", contents: "modified");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
- test('notifies when a file is removed', () {
+ test('notifies when a file is removed', () async {
writeFile("file.txt");
- startWatcher();
+ await startWatcher();
deleteFile("file.txt");
- expectRemoveEvent("file.txt");
+ await expectRemoveEvent("file.txt");
});
- test('notifies when a file is modified multiple times', () {
+ test('notifies when a file is modified multiple times', () async {
writeFile("file.txt");
- startWatcher();
+ await startWatcher();
writeFile("file.txt", contents: "modified");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
writeFile("file.txt", contents: "modified again");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
- test('notifies even if the file contents are unchanged', () {
+ test('notifies even if the file contents are unchanged', () async {
writeFile("a.txt", contents: "same");
writeFile("b.txt", contents: "before");
- startWatcher();
+ await startWatcher();
writeFile("a.txt", contents: "same");
writeFile("b.txt", contents: "after");
- inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]);
+ await inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]);
});
- test('when the watched directory is deleted, removes all files', () {
+ test('when the watched directory is deleted, removes all files', () async {
writeFile("dir/a.txt");
writeFile("dir/b.txt");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
deleteDir("dir");
- inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
+ await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
});
- test('when the watched directory is moved, removes all files', () {
+ test('when the watched directory is moved, removes all files', () async {
writeFile("dir/a.txt");
writeFile("dir/b.txt");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameDir("dir", "moved_dir");
createDir("dir");
- inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
+ await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
});
// Regression test for b/30768513.
test(
"doesn't crash when the directory is moved immediately after a subdir "
- "is added", () {
+ "is added", () async {
writeFile("dir/a.txt");
writeFile("dir/b.txt");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
createDir("dir/subdir");
renameDir("dir", "moved_dir");
createDir("dir");
- inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
+ await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]);
});
group("moves", () {
- test('notifies when a file is moved within the watched directory', () {
+ test('notifies when a file is moved within the watched directory',
+ () async {
writeFile("old.txt");
- startWatcher();
+ await startWatcher();
renameFile("old.txt", "new.txt");
- inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]);
+ await inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]);
});
test('notifies when a file is moved from outside the watched directory',
- () {
+ () async {
writeFile("old.txt");
createDir("dir");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameFile("old.txt", "dir/new.txt");
expectAddEvent("dir/new.txt");
});
- test('notifies when a file is moved outside the watched directory', () {
+ test('notifies when a file is moved outside the watched directory',
+ () async {
writeFile("dir/old.txt");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameFile("dir/old.txt", "new.txt");
expectRemoveEvent("dir/old.txt");
});
- test('notifies when a file is moved onto an existing one', () {
+ test('notifies when a file is moved onto an existing one', () async {
writeFile("from.txt");
writeFile("to.txt");
- startWatcher();
+ await startWatcher();
renameFile("from.txt", "to.txt");
- inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]);
+ await inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]);
});
});
@@ -144,14 +146,15 @@
// that as well.
group("clustered changes", () {
test("doesn't notify when a file is created and then immediately removed",
- () {
- startWatcher();
+ () async {
+ writeFile("test.txt");
+ await startWatcher();
writeFile("file.txt");
deleteFile("file.txt");
// Backup case.
startClosingEventStream();
- allowEvents(() {
+ await allowEvents(() {
expectAddEvent("file.txt");
expectRemoveEvent("file.txt");
});
@@ -159,14 +162,14 @@
test(
"reports a modification when a file is deleted and then immediately "
- "recreated", () {
+ "recreated", () async {
writeFile("file.txt");
- startWatcher();
+ await startWatcher();
deleteFile("file.txt");
writeFile("file.txt", contents: "re-created");
- allowEither(() {
+ await allowEither(() {
expectModifyEvent("file.txt");
}, () {
// Backup case.
@@ -177,14 +180,14 @@
test(
"reports a modification when a file is moved and then immediately "
- "recreated", () {
+ "recreated", () async {
writeFile("old.txt");
- startWatcher();
+ await startWatcher();
renameFile("old.txt", "new.txt");
writeFile("old.txt", contents: "re-created");
- allowEither(() {
+ await allowEither(() {
inAnyOrder([isModifyEvent("old.txt"), isAddEvent("new.txt")]);
}, () {
// Backup case.
@@ -196,76 +199,77 @@
test(
"reports a removal when a file is modified and then immediately "
- "removed", () {
+ "removed", () async {
writeFile("file.txt");
- startWatcher();
+ await startWatcher();
writeFile("file.txt", contents: "modified");
deleteFile("file.txt");
// Backup case.
- allowModifyEvent("file.txt");
+ await allowModifyEvent("file.txt");
- expectRemoveEvent("file.txt");
+ await expectRemoveEvent("file.txt");
});
test("reports an add when a file is added and then immediately modified",
- () {
- startWatcher();
+ () async {
+ await startWatcher();
writeFile("file.txt");
writeFile("file.txt", contents: "modified");
- expectAddEvent("file.txt");
+ await expectAddEvent("file.txt");
// Backup case.
startClosingEventStream();
- allowModifyEvent("file.txt");
+ await allowModifyEvent("file.txt");
});
});
group("subdirectories", () {
- test('watches files in subdirectories', () {
- startWatcher();
+ test('watches files in subdirectories', () async {
+ await startWatcher();
writeFile("a/b/c/d/file.txt");
expectAddEvent("a/b/c/d/file.txt");
});
test(
'notifies when a subdirectory is moved within the watched directory '
- 'and then its contents are modified', () {
+ 'and then its contents are modified', () async {
writeFile("old/file.txt");
- startWatcher();
+ await startWatcher();
renameDir("old", "new");
- inAnyOrder([isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]);
+ await inAnyOrder(
+ [isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]);
writeFile("new/file.txt", contents: "modified");
- expectModifyEvent("new/file.txt");
+ await expectModifyEvent("new/file.txt");
});
- test('notifies when a file is replaced by a subdirectory', () {
+ test('notifies when a file is replaced by a subdirectory', () async {
writeFile("new");
writeFile("old/file.txt");
- startWatcher();
+ await startWatcher();
deleteFile("new");
renameDir("old", "new");
- inAnyOrder([
+ await inAnyOrder([
isRemoveEvent("new"),
isRemoveEvent("old/file.txt"),
isAddEvent("new/file.txt")
]);
});
- test('notifies when a subdirectory is replaced by a file', () {
+ test('notifies when a subdirectory is replaced by a file', () async {
writeFile("old");
writeFile("new/file.txt");
- startWatcher();
+ await startWatcher();
renameDir("new", "newer");
renameFile("old", "new");
- inAnyOrder([
+ await inAnyOrder([
isRemoveEvent("new/file.txt"),
isAddEvent("newer/file.txt"),
isRemoveEvent("old"),
@@ -275,23 +279,23 @@
"mac-os": new Skip("https://github.com/dart-lang/watcher/issues/21")
});
- test('emits events for many nested files added at once', () {
+ test('emits events for many nested files added at once', () async {
withPermutations((i, j, k) => writeFile("sub/sub-$i/sub-$j/file-$k.txt"));
createDir("dir");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameDir("sub", "dir/sub");
- inAnyOrder(withPermutations(
+ await inAnyOrder(withPermutations(
(i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")));
});
- test('emits events for many nested files removed at once', () {
+ test('emits events for many nested files removed at once', () async {
withPermutations(
(i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt"));
createDir("dir");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
// Rename the directory rather than deleting it because native watchers
// report a rename as a single DELETE event for the directory, whereas
@@ -299,19 +303,19 @@
// directory.
renameDir("dir/sub", "sub");
- inAnyOrder(withPermutations(
+ await inAnyOrder(withPermutations(
(i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")));
});
- test('emits events for many nested files moved at once', () {
+ test('emits events for many nested files moved at once', () async {
withPermutations(
(i, j, k) => writeFile("dir/old/sub-$i/sub-$j/file-$k.txt"));
createDir("dir");
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
renameDir("dir/old", "dir/new");
- inAnyOrder(unionAll(withPermutations((i, j, k) {
+ await inAnyOrder(unionAll(withPermutations((i, j, k) {
return new Set.from([
isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"),
isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt")
@@ -321,10 +325,10 @@
test(
"emits events for many files added at once in a subdirectory with the "
- "same name as a removed file", () {
+ "same name as a removed file", () async {
writeFile("dir/sub");
withPermutations((i, j, k) => writeFile("old/sub-$i/sub-$j/file-$k.txt"));
- startWatcher(path: "dir");
+ await startWatcher(path: "dir");
deleteFile("dir/sub");
renameDir("old", "dir/sub");
@@ -332,7 +336,7 @@
var events = withPermutations(
(i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"));
events.add(isRemoveEvent("dir/sub"));
- inAnyOrder(events);
+ await inAnyOrder(events);
});
});
}
diff --git a/test/directory_watcher/windows_test.dart b/test/directory_watcher/windows_test.dart
index 176fe2d..3696f9c 100644
--- a/test/directory_watcher/windows_test.dart
+++ b/test/directory_watcher/windows_test.dart
@@ -4,7 +4,7 @@
@TestOn('windows')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/windows.dart';
import 'package:watcher/watcher.dart';
@@ -14,9 +14,11 @@
void main() {
watcherFactory = (dir) => new WindowsDirectoryWatcher(dir);
- setUp(createSandbox);
-
- sharedTests();
+ // TODO(grouma) - renable when https://github.com/dart-lang/sdk/issues/31760
+ // is resolved.
+ group("Shared Tests:", () {
+ sharedTests();
+ }, skip: "SDK issue see - https://github.com/dart-lang/sdk/issues/31760");
test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () {
expect(
diff --git a/test/file_watcher/native_test.dart b/test/file_watcher/native_test.dart
index cbf11b6..b6ed901 100644
--- a/test/file_watcher/native_test.dart
+++ b/test/file_watcher/native_test.dart
@@ -4,7 +4,7 @@
@TestOn('linux || mac-os')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/file_watcher/native.dart';
import 'shared.dart';
@@ -14,7 +14,6 @@
watcherFactory = (file) => new NativeFileWatcher(file);
setUp(() {
- createSandbox();
writeFile("file.txt");
});
diff --git a/test/file_watcher/polling_test.dart b/test/file_watcher/polling_test.dart
index e502544..01d579a 100644
--- a/test/file_watcher/polling_test.dart
+++ b/test/file_watcher/polling_test.dart
@@ -4,7 +4,7 @@
@TestOn('linux || mac-os')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
import 'shared.dart';
@@ -15,7 +15,6 @@
pollingDelay: new Duration(milliseconds: 100));
setUp(() {
- createSandbox();
writeFile("file.txt");
});
diff --git a/test/file_watcher/shared.dart b/test/file_watcher/shared.dart
index 50f7aeb..286a042 100644
--- a/test/file_watcher/shared.dart
+++ b/test/file_watcher/shared.dart
@@ -4,73 +4,67 @@
import 'dart:async';
-import 'package:scheduled_test/scheduled_test.dart';
-import 'package:watcher/src/utils.dart';
+import 'package:test/test.dart';
import '../utils.dart';
void sharedTests() {
- test("doesn't notify if the file isn't modified", () {
- startWatcher(path: "file.txt");
- // Give the watcher time to fire events if it's going to.
- schedule(() => pumpEventQueue());
+ test("doesn't notify if the file isn't modified", () async {
+ await startWatcher(path: "file.txt");
+ await pumpEventQueue();
deleteFile("file.txt");
- expectRemoveEvent("file.txt");
+ await expectRemoveEvent("file.txt");
});
- test("notifies when a file is modified", () {
- startWatcher(path: "file.txt");
+ test("notifies when a file is modified", () async {
+ await startWatcher(path: "file.txt");
writeFile("file.txt", contents: "modified");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
- test("notifies when a file is removed", () {
- startWatcher(path: "file.txt");
+ test("notifies when a file is removed", () async {
+ await startWatcher(path: "file.txt");
deleteFile("file.txt");
- expectRemoveEvent("file.txt");
+ await expectRemoveEvent("file.txt");
});
- test("notifies when a file is modified multiple times", () {
- startWatcher(path: "file.txt");
+ test("notifies when a file is modified multiple times", () async {
+ await startWatcher(path: "file.txt");
writeFile("file.txt", contents: "modified");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
writeFile("file.txt", contents: "modified again");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
- test("notifies even if the file contents are unchanged", () {
- startWatcher(path: "file.txt");
+ test("notifies even if the file contents are unchanged", () async {
+ await startWatcher(path: "file.txt");
writeFile("file.txt");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
- test("emits a remove event when the watched file is moved away", () {
- startWatcher(path: "file.txt");
+ test("emits a remove event when the watched file is moved away", () async {
+ await startWatcher(path: "file.txt");
renameFile("file.txt", "new.txt");
- expectRemoveEvent("file.txt");
+ await expectRemoveEvent("file.txt");
});
test(
"emits a modify event when another file is moved on top of the watched "
- "file", () {
+ "file", () async {
writeFile("old.txt");
- startWatcher(path: "file.txt");
+ await startWatcher(path: "file.txt");
renameFile("old.txt", "file.txt");
- expectModifyEvent("file.txt");
+ await expectModifyEvent("file.txt");
});
// Regression test for a race condition.
- test("closes the watcher immediately after deleting the file", () {
+ test("closes the watcher immediately after deleting the file", () async {
writeFile("old.txt");
- var watcher = createWatcher(path: "file.txt", waitForReady: false);
- var sub = schedule(() => watcher.events.listen(null));
+ var watcher = createWatcher(path: "file.txt");
+ var sub = watcher.events.listen(null);
deleteFile("file.txt");
- schedule(() async {
- // Reproducing the race condition will always be flaky, but this sleep
- // helped it reproduce more consistently on my machine.
- await new Future.delayed(new Duration(milliseconds: 10));
- (await sub).cancel();
- });
+ await new Future.delayed(new Duration(milliseconds: 10));
+ await sub.cancel();
});
}
diff --git a/test/no_subscription/linux_test.dart b/test/no_subscription/linux_test.dart
index c8e8ae9..e9bfd69 100644
--- a/test/no_subscription/linux_test.dart
+++ b/test/no_subscription/linux_test.dart
@@ -4,7 +4,7 @@
@TestOn('linux')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/linux.dart';
import 'shared.dart';
@@ -13,7 +13,5 @@
void main() {
watcherFactory = (dir) => new LinuxDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/no_subscription/mac_os_test.dart b/test/no_subscription/mac_os_test.dart
index 499aff3..fc14ebf 100644
--- a/test/no_subscription/mac_os_test.dart
+++ b/test/no_subscription/mac_os_test.dart
@@ -5,7 +5,7 @@
@TestOn('mac-os')
@Skip("Flaky due to sdk#23877")
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/mac_os.dart';
import 'shared.dart';
@@ -14,7 +14,5 @@
void main() {
watcherFactory = (dir) => new MacOSDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/no_subscription/polling_test.dart b/test/no_subscription/polling_test.dart
index 5c99bc0..75fa3a7 100644
--- a/test/no_subscription/polling_test.dart
+++ b/test/no_subscription/polling_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:scheduled_test/scheduled_test.dart';
import 'package:watcher/watcher.dart';
import 'shared.dart';
@@ -11,7 +10,5 @@
void main() {
watcherFactory = (dir) => new PollingDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/no_subscription/shared.dart b/test/no_subscription/shared.dart
index 5858656..c7e0501 100644
--- a/test/no_subscription/shared.dart
+++ b/test/no_subscription/shared.dart
@@ -4,60 +4,51 @@
import 'dart:async';
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:async/async.dart';
+import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
import '../utils.dart';
void sharedTests() {
- test('does not notify for changes when there are no subscribers', () {
+ test('does not notify for changes when there are no subscribers', () async {
// Note that this test doesn't rely as heavily on the test functions in
// utils.dart because it needs to be very explicit about when the event
// stream is and is not subscribed.
var watcher = createWatcher();
+ var queue = new StreamQueue(watcher.events);
+ queue.hasNext;
- // Subscribe to the events.
- var completer = new Completer();
- var subscription = watcher.events.listen(expectAsync1((event) {
- expect(event, isWatchEvent(ChangeType.ADD, "file.txt"));
- completer.complete();
- }));
+ var future =
+ expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "file.txt")));
+ expect(queue, neverEmits(anything));
- writeFile("file.txt");
+ await watcher.ready;
- // Then wait until we get an event for it.
- schedule(() => completer.future);
+ writeFile('file.txt');
+
+ await future;
// Unsubscribe.
- schedule(() {
- subscription.cancel();
- });
+ await queue.cancel(immediate: true);
// Now write a file while we aren't listening.
writeFile("unwatched.txt");
- // Then start listening again.
- schedule(() {
- completer = new Completer();
- subscription = watcher.events.listen(expectAsync1((event) {
- // We should get an event for the third file, not the one added while
- // we weren't subscribed.
- expect(event, isWatchEvent(ChangeType.ADD, "added.txt"));
- completer.complete();
- }));
+ queue = new StreamQueue(watcher.events);
+ future =
+ expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "added.txt")));
+ expect(queue, neverEmits(isWatchEvent(ChangeType.ADD, "unwatched.txt")));
- // Wait until the watcher is ready to dispatch events again.
- return watcher.ready;
- });
+ // Wait until the watcher is ready to dispatch events again.
+ await watcher.ready;
// And add a third file.
writeFile("added.txt");
// Wait until we get an event for the third file.
- schedule(() => completer.future);
+ await future;
- schedule(() {
- subscription.cancel();
- });
+ await queue.cancel(immediate: true);
});
}
diff --git a/test/ready/linux_test.dart b/test/ready/linux_test.dart
index c8e8ae9..e9bfd69 100644
--- a/test/ready/linux_test.dart
+++ b/test/ready/linux_test.dart
@@ -4,7 +4,7 @@
@TestOn('linux')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/linux.dart';
import 'shared.dart';
@@ -13,7 +13,5 @@
void main() {
watcherFactory = (dir) => new LinuxDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/ready/mac_os_test.dart b/test/ready/mac_os_test.dart
index d5b1c8e..9533cc8 100644
--- a/test/ready/mac_os_test.dart
+++ b/test/ready/mac_os_test.dart
@@ -4,7 +4,7 @@
@TestOn('mac-os')
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/mac_os.dart';
import 'shared.dart';
@@ -13,7 +13,5 @@
void main() {
watcherFactory = (dir) => new MacOSDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/ready/polling_test.dart b/test/ready/polling_test.dart
index 5c99bc0..75fa3a7 100644
--- a/test/ready/polling_test.dart
+++ b/test/ready/polling_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:scheduled_test/scheduled_test.dart';
import 'package:watcher/watcher.dart';
import 'shared.dart';
@@ -11,7 +10,5 @@
void main() {
watcherFactory = (dir) => new PollingDirectoryWatcher(dir);
- setUp(createSandbox);
-
sharedTests();
}
diff --git a/test/ready/shared.dart b/test/ready/shared.dart
index 7be4833..730d579 100644
--- a/test/ready/shared.dart
+++ b/test/ready/shared.dart
@@ -2,97 +2,61 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:scheduled_test/scheduled_test.dart';
+import 'package:test/test.dart';
import '../utils.dart';
void sharedTests() {
- test('ready does not complete until after subscription', () {
- var watcher = createWatcher(waitForReady: false);
+ test('ready does not complete until after subscription', () async {
+ var watcher = createWatcher();
var ready = false;
watcher.ready.then((_) {
ready = true;
});
+ await pumpEventQueue();
- // Should not be ready yet.
- schedule(() {
- expect(ready, isFalse);
- });
+ expect(ready, isFalse);
// Subscribe to the events.
- schedule(() {
- var subscription = watcher.events.listen((event) {});
+ watcher.events.listen((event) {});
- currentSchedule.onComplete.schedule(() {
- subscription.cancel();
- });
- });
+ await watcher.ready;
// Should eventually be ready.
- schedule(() => watcher.ready);
-
- schedule(() {
- expect(ready, isTrue);
- });
+ expect(watcher.isReady, isTrue);
});
- test('ready completes immediately when already ready', () {
- var watcher = createWatcher(waitForReady: false);
+ test('ready completes immediately when already ready', () async {
+ var watcher = createWatcher();
// Subscribe to the events.
- schedule(() {
- var subscription = watcher.events.listen((event) {});
+ watcher.events.listen((event) {});
- currentSchedule.onComplete.schedule(() {
- subscription.cancel();
- });
- });
+ // Allow watcher to become ready
+ await watcher.ready;
- // Should eventually be ready.
- schedule(() => watcher.ready);
-
- // Now ready should be a future that immediately completes.
- var ready = false;
- schedule(() {
- watcher.ready.then((_) {
- ready = true;
- });
- });
-
- schedule(() {
- expect(ready, isTrue);
- });
+ // Ensure ready completes immediately
+ expect(
+ watcher.ready.timeout(new Duration(milliseconds: 0),
+ onTimeout: () => throw 'Does not complete immedately'),
+ completes);
});
- test('ready returns a future that does not complete after unsubscribing', () {
- var watcher = createWatcher(waitForReady: false);
+ test('ready returns a future that does not complete after unsubscribing',
+ () async {
+ var watcher = createWatcher();
// Subscribe to the events.
- var subscription;
- schedule(() {
- subscription = watcher.events.listen((event) {});
- });
-
- var ready = false;
+ var subscription = watcher.events.listen((event) {});
// Wait until ready.
- schedule(() => watcher.ready);
+ await watcher.ready;
// Now unsubscribe.
- schedule(() {
- subscription.cancel();
-
- // Track when it's ready again.
- ready = false;
- watcher.ready.then((_) {
- ready = true;
- });
- });
+ await subscription.cancel();
// Should be back to not ready.
- schedule(() {
- expect(ready, isFalse);
- });
+ expect(watcher.ready, doesNotComplete);
});
}
diff --git a/test/utils.dart b/test/utils.dart
index 6700500..637eacf 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -2,21 +2,23 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:async';
import 'dart:io';
+import 'package:async/async.dart';
import 'package:path/path.dart' as p;
-import 'package:scheduled_test/scheduled_stream.dart';
-import 'package:scheduled_test/scheduled_test.dart';
-import 'package:watcher/watcher.dart';
+import 'package:test/test.dart';
+import 'package:test_descriptor/test_descriptor.dart' as d;
+
import 'package:watcher/src/stat.dart';
-import 'package:watcher/src/utils.dart';
+import 'package:watcher/watcher.dart';
-/// The path to the temporary sandbox created for each test. All file
-/// operations are implicitly relative to this directory.
-String _sandboxDir;
+typedef Watcher WatcherFactory(String directory);
-/// The [Watcher] being used for the current scheduled test.
-Watcher _watcher;
+/// Sets the function used to create the watcher.
+set watcherFactory(WatcherFactory factory) {
+ _watcherFactory = factory;
+}
/// The mock modification times (in milliseconds since epoch) for each file.
///
@@ -27,53 +29,10 @@
///
/// Instead, we'll just mock that out. Each time a file is written, we manually
/// increment the mod time for that file instantly.
-Map<String, int> _mockFileModificationTimes;
-
-typedef Watcher WatcherFactory(String directory);
-
-/// Sets the function used to create the watcher.
-set watcherFactory(WatcherFactory factory) {
- _watcherFactory = factory;
-}
+final _mockFileModificationTimes = <String, int>{};
WatcherFactory _watcherFactory;
-/// Creates the sandbox directory the other functions in this library use and
-/// ensures it's deleted when the test ends.
-///
-/// This should usually be called by [setUp].
-void createSandbox() {
- var dir = Directory.systemTemp.createTempSync('watcher_test_');
- _sandboxDir = dir.path;
-
- _mockFileModificationTimes = new Map<String, int>();
- mockGetModificationTime((path) {
- path = p.normalize(p.relative(path, from: _sandboxDir));
-
- // Make sure we got a path in the sandbox.
- assert(p.isRelative(path) && !path.startsWith(".."));
-
- var mtime = _mockFileModificationTimes[path];
- return new DateTime.fromMillisecondsSinceEpoch(mtime == null ? 0 : mtime);
- });
-
- // Delete the sandbox when done.
- currentSchedule.onComplete.schedule(() {
- if (_sandboxDir != null) {
- // TODO(rnystrom): Issue 19155. The watcher should already be closed when
- // we clean up the sandbox.
- if (_watcherEvents != null) {
- _watcherEvents.close();
- }
- new Directory(_sandboxDir).deleteSync(recursive: true);
- _sandboxDir = null;
- }
-
- _mockFileModificationTimes = null;
- mockGetModificationTime(null);
- }, "delete sandbox");
-}
-
/// Creates a new [Watcher] that watches a temporary file or directory.
///
/// Normally, this will pause the schedule until the watcher is done scanning
@@ -81,62 +40,43 @@
/// not schedule this delay.
///
/// If [path] is provided, watches a subdirectory in the sandbox with that name.
-Watcher createWatcher({String path, bool waitForReady}) {
+Watcher createWatcher({String path}) {
if (path == null) {
- path = _sandboxDir;
+ path = d.sandbox;
} else {
- path = p.join(_sandboxDir, path);
+ path = p.join(d.sandbox, path);
}
- var watcher = _watcherFactory(path);
-
- // Wait until the scan is finished so that we don't miss changes to files
- // that could occur before the scan completes.
- if (waitForReady != false) {
- schedule(() => watcher.ready, "wait for watcher to be ready");
- }
-
- return watcher;
+ return _watcherFactory(path);
}
/// The stream of events from the watcher started with [startWatcher].
-ScheduledStream<WatchEvent> _watcherEvents;
+StreamQueue<WatchEvent> _watcherEvents;
/// Creates a new [Watcher] that watches a temporary file or directory and
/// starts monitoring it for events.
///
/// If [path] is provided, watches a path in the sandbox with that name.
-void startWatcher({String path}) {
+Future<Null> startWatcher({String path}) async {
+ mockGetModificationTime((path) {
+ path = p.normalize(p.relative(path, from: d.sandbox));
+
+ // Make sure we got a path in the sandbox.
+ assert(p.isRelative(path) && !path.startsWith(".."));
+
+ var mtime = _mockFileModificationTimes[path];
+ return new DateTime.fromMillisecondsSinceEpoch(mtime ?? 0);
+ });
+
// We want to wait until we're ready *after* we subscribe to the watcher's
// events.
- _watcher = createWatcher(path: path, waitForReady: false);
-
- // Schedule [_watcher.events.listen] so that the watcher doesn't start
- // watching [path] before it exists. Expose [_watcherEvents] immediately so
- // that it can be accessed synchronously after this.
- _watcherEvents = new ScheduledStream(futureStream(
- schedule(() {
- currentSchedule.onComplete.schedule(() {
- _watcher = null;
- if (!_closePending) _watcherEvents.close();
-
- // If there are already errors, don't add this to the output and make
- // people think it might be the root cause.
- if (currentSchedule.errors.isEmpty) {
- _watcherEvents.expect(isDone);
- }
- }, "reset watcher");
-
- return _watcher.events;
- }, "create watcher"),
- broadcast: true));
-
- schedule(() => _watcher.ready, "wait for watcher to be ready");
+ var watcher = createWatcher(path: path);
+ _watcherEvents = new StreamQueue(watcher.events);
+ // Forces a subscription to the underlying stream.
+ _watcherEvents.hasNext;
+ await watcher.ready;
}
-/// Whether an event to close [_watcherEvents] has been scheduled.
-bool _closePending = false;
-
/// Schedule closing the watcher stream after the event queue has been pumped.
///
/// This is necessary when events are allowed to occur, but don't have to occur,
@@ -144,12 +84,7 @@
/// indefinitely because they might in the future and because the watcher is
/// normally only closed after the test completes.
void startClosingEventStream() {
- schedule(() {
- _closePending = true;
- pumpEventQueue().then((_) => _watcherEvents.close()).whenComplete(() {
- _closePending = false;
- });
- }, 'start closing event stream');
+ pumpEventQueue().then((_) => _watcherEvents.cancel(immediate: true));
}
/// A list of [StreamMatcher]s that have been collected using
@@ -165,7 +100,7 @@
_collectedStreamMatchers = new List<StreamMatcher>();
try {
block();
- return inOrder(_collectedStreamMatchers);
+ return emitsInOrder(_collectedStreamMatchers);
} finally {
_collectedStreamMatchers = oldStreamMatchers;
}
@@ -175,47 +110,45 @@
/// it with [_collectStreamMatcher].
///
/// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value.
-void _expectOrCollect(streamMatcher) {
+Future _expectOrCollect(streamMatcher) {
if (_collectedStreamMatchers != null) {
- _collectedStreamMatchers.add(new StreamMatcher.wrap(streamMatcher));
+ _collectedStreamMatchers.add(emits(streamMatcher));
+ return null;
} else {
- _watcherEvents.expect(streamMatcher);
+ return expectLater(_watcherEvents, emits(streamMatcher));
}
}
/// Expects that [matchers] will match emitted events in any order.
///
/// [matchers] may be [Matcher]s or values, but not [StreamMatcher]s.
-void inAnyOrder(Iterable matchers) {
+Future inAnyOrder(Iterable matchers) {
matchers = matchers.toSet();
- _expectOrCollect(nextValues(matchers.length, unorderedMatches(matchers)));
+ return _expectOrCollect(emitsInAnyOrder(matchers));
}
/// Expects that the expectations established in either [block1] or [block2]
/// will match the emitted events.
///
/// If both blocks match, the one that consumed more events will be used.
-void allowEither(block1(), block2()) {
- _expectOrCollect(
- either(_collectStreamMatcher(block1), _collectStreamMatcher(block2)));
-}
+Future allowEither(block1(), block2()) => _expectOrCollect(
+ emitsAnyOf([_collectStreamMatcher(block1), _collectStreamMatcher(block2)]));
/// Allows the expectations established in [block] to match the emitted events.
///
/// If the expectations in [block] don't match, no error will be raised and no
/// events will be consumed. If this is used at the end of a test,
/// [startClosingEventStream] should be called before it.
-void allowEvents(block()) {
- _expectOrCollect(allow(_collectStreamMatcher(block)));
-}
+Future allowEvents(block()) =>
+ _expectOrCollect(mayEmit(_collectStreamMatcher(block)));
-/// Returns a matcher that matches a [WatchEvent] with the given [type] and
-/// [path].
+/// Returns a StreamMatcher that matches a [WatchEvent] with the given [type]
+/// and [path].
Matcher isWatchEvent(ChangeType type, String path) {
return predicate((e) {
return e is WatchEvent &&
e.type == type &&
- e.path == p.join(_sandboxDir, p.normalize(path));
+ e.path == p.join(d.sandbox, p.normalize(path));
}, "is $type $path");
}
@@ -231,16 +164,16 @@
Matcher isRemoveEvent(String path) => isWatchEvent(ChangeType.REMOVE, path);
/// Expects that the next event emitted will be for an add event for [path].
-void expectAddEvent(String path) =>
+Future expectAddEvent(String path) =>
_expectOrCollect(isWatchEvent(ChangeType.ADD, path));
/// Expects that the next event emitted will be for a modification event for
/// [path].
-void expectModifyEvent(String path) =>
+Future expectModifyEvent(String path) =>
_expectOrCollect(isWatchEvent(ChangeType.MODIFY, path));
/// Expects that the next event emitted will be for a removal event for [path].
-void expectRemoveEvent(String path) =>
+Future expectRemoveEvent(String path) =>
_expectOrCollect(isWatchEvent(ChangeType.REMOVE, path));
/// Consumes an add event for [path] if one is emitted at this point in the
@@ -248,24 +181,24 @@
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
-void allowAddEvent(String path) =>
- _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path)));
+Future allowAddEvent(String path) =>
+ _expectOrCollect(mayEmit(isWatchEvent(ChangeType.ADD, path)));
/// Consumes a modification event for [path] if one is emitted at this point in
/// the schedule, but doesn't throw an error if it isn't.
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
-void allowModifyEvent(String path) =>
- _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path)));
+Future allowModifyEvent(String path) =>
+ _expectOrCollect(mayEmit(isWatchEvent(ChangeType.MODIFY, path)));
/// Consumes a removal event for [path] if one is emitted at this point in the
/// schedule, but doesn't throw an error if it isn't.
///
/// If this is used at the end of a test, [startClosingEventStream] should be
/// called before it.
-void allowRemoveEvent(String path) =>
- _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path)));
+Future allowRemoveEvent(String path) =>
+ _expectOrCollect(mayEmit(isWatchEvent(ChangeType.REMOVE, path)));
/// Schedules writing a file in the sandbox at [path] with [contents].
///
@@ -275,71 +208,55 @@
if (contents == null) contents = "";
if (updateModified == null) updateModified = true;
- schedule(() {
- var fullPath = p.join(_sandboxDir, path);
+ var fullPath = p.join(d.sandbox, path);
- // Create any needed subdirectories.
- var dir = new Directory(p.dirname(fullPath));
- if (!dir.existsSync()) {
- dir.createSync(recursive: true);
- }
+ // Create any needed subdirectories.
+ var dir = new Directory(p.dirname(fullPath));
+ if (!dir.existsSync()) {
+ dir.createSync(recursive: true);
+ }
- new File(fullPath).writeAsStringSync(contents);
+ new File(fullPath).writeAsStringSync(contents);
- // Manually update the mock modification time for the file.
- if (updateModified) {
- // Make sure we always use the same separator on Windows.
- path = p.normalize(path);
+ if (updateModified) {
+ path = p.normalize(path);
- _mockFileModificationTimes.putIfAbsent(path, () => 0);
- _mockFileModificationTimes[path]++;
- }
- }, "write file $path");
+ _mockFileModificationTimes.putIfAbsent(path, () => 0);
+ _mockFileModificationTimes[path]++;
+ }
}
/// Schedules deleting a file in the sandbox at [path].
void deleteFile(String path) {
- schedule(() {
- new File(p.join(_sandboxDir, path)).deleteSync();
- }, "delete file $path");
+ new File(p.join(d.sandbox, path)).deleteSync();
}
/// Schedules renaming a file in the sandbox from [from] to [to].
///
/// If [contents] is omitted, creates an empty file.
void renameFile(String from, String to) {
- schedule(() {
- new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to));
+ new File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to));
- // Make sure we always use the same separator on Windows.
- to = p.normalize(to);
+ // Make sure we always use the same separator on Windows.
+ to = p.normalize(to);
- // Manually update the mock modification time for the file.
- _mockFileModificationTimes.putIfAbsent(to, () => 0);
- _mockFileModificationTimes[to]++;
- }, "rename file $from to $to");
+ _mockFileModificationTimes.putIfAbsent(to, () => 0);
+ _mockFileModificationTimes[to]++;
}
/// Schedules creating a directory in the sandbox at [path].
void createDir(String path) {
- schedule(() {
- new Directory(p.join(_sandboxDir, path)).createSync();
- }, "create directory $path");
+ new Directory(p.join(d.sandbox, path)).createSync();
}
/// Schedules renaming a directory in the sandbox from [from] to [to].
void renameDir(String from, String to) {
- schedule(() {
- new Directory(p.join(_sandboxDir, from))
- .renameSync(p.join(_sandboxDir, to));
- }, "rename directory $from to $to");
+ new Directory(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to));
}
/// Schedules deleting a directory in the sandbox at [path].
void deleteDir(String path) {
- schedule(() {
- new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true);
- }, "delete directory $path");
+ new Directory(p.join(d.sandbox, path)).deleteSync(recursive: true);
}
/// Runs [callback] with every permutation of non-negative [i], [j], and [k]