Split up tests and add some heartbeats to try to make them not timeout.
BUG=
R=nweiz@google.com
Review URL: https://codereview.chromium.org//18877005
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24978 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart
index 0f297ba..61bf6c5 100644
--- a/pkgs/watcher/lib/src/directory_watcher.dart
+++ b/pkgs/watcher/lib/src/directory_watcher.dart
@@ -42,13 +42,24 @@
Future get ready => _ready.future;
Completer _ready = new Completer();
+ /// The amount of time the watcher pauses between successive polls of the
+ /// directory contents.
+ final Duration pollingDelay;
+
/// The previous status of the files in the directory.
///
/// Used to tell which files have been modified.
final _statuses = new Map<String, _FileStatus>();
/// Creates a new [DirectoryWatcher] monitoring [directory].
- DirectoryWatcher(this.directory) {
+ ///
+ /// If [pollingDelay] is passed, it specifies the amount of time the watcher
+ /// will pause between successive polls of the directory contents. Making
+ /// this shorter will give more immediate feedback at the expense of doing
+ /// more IO and higher CPU usage. Defaults to one second.
+ DirectoryWatcher(this.directory, {Duration pollingDelay})
+ : pollingDelay = pollingDelay != null ? pollingDelay :
+ new Duration(seconds: 1) {
_events = new StreamController<WatchEvent>.broadcast(onListen: () {
_state = _state.listen(this);
}, onCancel: () {
@@ -93,7 +104,7 @@
// restarting just so that we don't whale on the file system.
// TODO(rnystrom): Tune this and/or make it tunable?
if (_state.shouldNotify) {
- return new Future.delayed(new Duration(seconds: 1));
+ return new Future.delayed(pollingDelay);
}
}).then((_) {
// Make sure we haven't transitioned to a non-watching state during the
diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart
index 635f7ee..800d54d 100644
--- a/pkgs/watcher/test/directory_watcher_test.dart
+++ b/pkgs/watcher/test/directory_watcher_test.dart
@@ -90,150 +90,4 @@
writeFile("a/b/c/d/file.txt");
expectAddEvent("a/b/c/d/file.txt");
});
-
- test('does not notify for changes when there were no subscribers', () {
- // 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();
-
- // Subscribe to the events.
- var completer = new Completer();
- var subscription = watcher.events.listen((event) {
- expect(event.type, equals(ChangeType.ADD));
- expect(event.path, endsWith("file.txt"));
- completer.complete();
- });
-
- writeFile("file.txt");
-
- // Then wait until we get an event for it.
- schedule(() => completer.future);
-
- // Unsubscribe.
- schedule(() {
- subscription.cancel();
- });
-
- // Now write a file while we aren't listening.
- writeFile("unwatched.txt");
-
- // Then start listening again.
- schedule(() {
- completer = new Completer();
- subscription = watcher.events.listen((event) {
- // We should get an event for the third file, not the one added while
- // we weren't subscribed.
- expect(event.type, equals(ChangeType.ADD));
- expect(event.path, endsWith("added.txt"));
- completer.complete();
- });
- });
-
- // The watcher will have been cancelled and then resumed in the middle of
- // its pause between polling loops. That means the second scan to skip
- // what changed while we were unsubscribed won't happen until after that
- // delay is done. Wait long enough for that to happen.
- schedule(() => new Future.delayed(new Duration(seconds: 1)));
-
- // And add a third file.
- writeFile("added.txt");
-
- // Wait until we get an event for the third file.
- schedule(() => completer.future);
-
- schedule(() {
- subscription.cancel();
- });
- });
-
-
- test('ready does not complete until after subscription', () {
- var watcher = createWatcher(waitForReady: false);
-
- var ready = false;
- watcher.ready.then((_) {
- ready = true;
- });
-
- // Should not be ready yet.
- schedule(() {
- expect(ready, isFalse);
- });
-
- // Subscribe to the events.
- schedule(() {
- var subscription = watcher.events.listen((event) {});
-
- currentSchedule.onComplete.schedule(() {
- subscription.cancel();
- });
- });
-
- // Should eventually be ready.
- schedule(() => watcher.ready);
-
- schedule(() {
- expect(ready, isTrue);
- });
- });
-
- test('ready completes immediately when already ready', () {
- var watcher = createWatcher(waitForReady: false);
-
- // Subscribe to the events.
- schedule(() {
- var subscription = watcher.events.listen((event) {});
-
- currentSchedule.onComplete.schedule(() {
- subscription.cancel();
- });
- });
-
- // 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);
- });
- });
-
- test('ready returns a future that does not complete after unsubscribing', () {
- var watcher = createWatcher(waitForReady: false);
-
- // Subscribe to the events.
- var subscription;
- schedule(() {
- subscription = watcher.events.listen((event) {});
- });
-
- var ready = false;
-
- // Wait until ready.
- schedule(() => watcher.ready);
-
- // Now unsubscribe.
- schedule(() {
- subscription.cancel();
-
- // Track when it's ready again.
- ready = false;
- watcher.ready.then((_) {
- ready = true;
- });
- });
-
- // Should be back to not ready.
- schedule(() {
- expect(ready, isFalse);
- });
- });
}
diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription_test.dart
new file mode 100644
index 0000000..e9cb4e3
--- /dev/null
+++ b/pkgs/watcher/test/no_subscription_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// 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:scheduled_test/scheduled_test.dart';
+import 'package:watcher/watcher.dart';
+
+import 'utils.dart';
+
+main() {
+ initConfig();
+
+ setUp(createSandbox);
+
+ test('does not notify for changes when there were no subscribers', () {
+ // 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();
+
+ // Subscribe to the events.
+ var completer = new Completer();
+ var subscription = watcher.events.listen((event) {
+ expect(event.type, equals(ChangeType.ADD));
+ expect(event.path, endsWith("file.txt"));
+ completer.complete();
+ });
+
+ writeFile("file.txt");
+
+ // Then wait until we get an event for it.
+ schedule(() => completer.future);
+
+ // Unsubscribe.
+ schedule(() {
+ subscription.cancel();
+ });
+
+ // Now write a file while we aren't listening.
+ writeFile("unwatched.txt");
+
+ // Then start listening again.
+ schedule(() {
+ completer = new Completer();
+ subscription = watcher.events.listen((event) {
+ // We should get an event for the third file, not the one added while
+ // we weren't subscribed.
+ expect(event.type, equals(ChangeType.ADD));
+ expect(event.path, endsWith("added.txt"));
+ completer.complete();
+ });
+ });
+
+ // The watcher will have been cancelled and then resumed in the middle of
+ // its pause between polling loops. That means the second scan to skip
+ // what changed while we were unsubscribed won't happen until after that
+ // delay is done. Wait long enough for that to happen.
+ schedule(() => new Future.delayed(new Duration(seconds: 1)));
+
+ // And add a third file.
+ writeFile("added.txt");
+
+ // Wait until we get an event for the third file.
+ schedule(() => completer.future);
+
+ schedule(() {
+ subscription.cancel();
+ });
+ });
+}
diff --git a/pkgs/watcher/test/ready_test.dart b/pkgs/watcher/test/ready_test.dart
new file mode 100644
index 0000000..dd799ce
--- /dev/null
+++ b/pkgs/watcher/test/ready_test.dart
@@ -0,0 +1,106 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// 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:scheduled_test/scheduled_test.dart';
+import 'package:watcher/watcher.dart';
+
+import 'utils.dart';
+
+main() {
+ initConfig();
+
+ setUp(createSandbox);
+
+ test('ready does not complete until after subscription', () {
+ var watcher = createWatcher(waitForReady: false);
+
+ var ready = false;
+ watcher.ready.then((_) {
+ ready = true;
+ });
+
+ // Should not be ready yet.
+ schedule(() {
+ expect(ready, isFalse);
+ });
+
+ // Subscribe to the events.
+ schedule(() {
+ var subscription = watcher.events.listen((event) {});
+
+ currentSchedule.onComplete.schedule(() {
+ subscription.cancel();
+ });
+ });
+
+ // Should eventually be ready.
+ schedule(() => watcher.ready);
+
+ schedule(() {
+ expect(ready, isTrue);
+ });
+ });
+
+ test('ready completes immediately when already ready', () {
+ var watcher = createWatcher(waitForReady: false);
+
+ // Subscribe to the events.
+ schedule(() {
+ var subscription = watcher.events.listen((event) {});
+
+ currentSchedule.onComplete.schedule(() {
+ subscription.cancel();
+ });
+ });
+
+ // 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);
+ });
+ });
+
+ test('ready returns a future that does not complete after unsubscribing', () {
+ var watcher = createWatcher(waitForReady: false);
+
+ // Subscribe to the events.
+ var subscription;
+ schedule(() {
+ subscription = watcher.events.listen((event) {});
+ });
+
+ var ready = false;
+
+ // Wait until ready.
+ schedule(() => watcher.ready);
+
+ // Now unsubscribe.
+ schedule(() {
+ subscription.cancel();
+
+ // Track when it's ready again.
+ ready = false;
+ watcher.ready.then((_) {
+ ready = true;
+ });
+ });
+
+ // Should be back to not ready.
+ schedule(() {
+ expect(ready, isFalse);
+ });
+ });
+}
diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart
index 7b3da02..5a22e60 100644
--- a/pkgs/watcher/test/utils.dart
+++ b/pkgs/watcher/test/utils.dart
@@ -77,7 +77,9 @@
/// and is polling for changes. If you pass `false` for [waitForReady], it will
/// not schedule this delay.
DirectoryWatcher createWatcher({bool waitForReady}) {
- _watcher = new DirectoryWatcher(_sandboxDir);
+ // Use a short delay to make the tests run quickly.
+ _watcher = new DirectoryWatcher(_sandboxDir,
+ pollingDelay: new Duration(milliseconds: 100));
// Wait until the scan is finished so that we don't miss changes to files
// that could occur before the scan completes.