summaryrefslogtreecommitdiffstats
path: root/toolkit/components/filewatcher/tests
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/filewatcher/tests')
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js7
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/head.js29
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_arguments.js79
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js69
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js39
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js62
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js49
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js46
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js51
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js54
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js54
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js73
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js114
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.js55
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js32
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini18
16 files changed, 831 insertions, 0 deletions
diff --git a/toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js b/toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js
new file mode 100644
index 000000000..d35787cd2
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "../../../../../testing/xpcshell/xpcshell.eslintrc.js"
+ ]
+};
diff --git a/toolkit/components/filewatcher/tests/xpcshell/head.js b/toolkit/components/filewatcher/tests/xpcshell/head.js
new file mode 100644
index 000000000..73f8ac4f5
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/head.js
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/osfile.jsm", this);
+Cu.import("resource://gre/modules/Promise.jsm", this);
+
+function makeWatcher() {
+ let watcher =
+ Cc['@mozilla.org/toolkit/filewatcher/native-file-watcher;1']
+ .getService(Ci.nsINativeFileWatcherService);
+ return watcher;
+}
+
+function promiseAddPath(watcher, resource, onChange=null, onError=null) {
+ return new Promise(resolve =>
+ watcher.addPath(resource, onChange, onError, resolve)
+ );
+}
+
+function promiseRemovePath(watcher, resource, onChange=null, onError=null) {
+ return new Promise(resolve =>
+ watcher.removePath(resource, onChange, onError, resolve)
+ );
+}
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_arguments.js b/toolkit/components/filewatcher/tests/xpcshell/test_arguments.js
new file mode 100644
index 000000000..7e62b1cb6
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_arguments.js
@@ -0,0 +1,79 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test for addPath usage with null arguments.
+ */
+add_task(function* test_null_args_addPath() {
+
+ let watcher = makeWatcher();
+ let testPath = 'someInvalidPath';
+
+ // Define a dummy callback function. In this test no callback is
+ // expected to be called.
+ let dummyFunc = function(changed) {
+ do_throw("Not expected in this test.");
+ };
+
+ // Check for error when passing a null first argument
+ try {
+ watcher.addPath(testPath, null, dummyFunc);
+ } catch (ex) {
+ if (ex.result != Cr.NS_ERROR_NULL_POINTER)
+ throw ex;
+ do_print("Initialisation thrown NS_ERROR_NULL_POINTER as expected.");
+ }
+
+ // Check for error when passing both null arguments
+ try {
+ watcher.addPath(testPath, null, null);
+ } catch (ex) {
+ if (ex.result != Cr.NS_ERROR_NULL_POINTER)
+ throw ex;
+ do_print("Initialisation thrown NS_ERROR_NULL_POINTER as expected.");
+ }
+});
+
+/**
+ * Test for removePath usage with null arguments.
+ */
+add_task(function* test_null_args_removePath() {
+
+ let watcher = makeWatcher();
+ let testPath = 'someInvalidPath';
+
+ // Define a dummy callback function. In this test no callback is
+ // expected to be called.
+ let dummyFunc = function(changed) {
+ do_throw("Not expected in this test.");
+ };
+
+ // Check for error when passing a null first argument
+ try {
+ watcher.removePath(testPath, null, dummyFunc);
+ } catch (ex) {
+ if (ex.result != Cr.NS_ERROR_NULL_POINTER)
+ throw ex;
+ do_print("Initialisation thrown NS_ERROR_NULL_POINTER as expected.");
+ }
+
+ // Check for error when passing both null arguments
+ try {
+ watcher.removePath(testPath, null, null);
+ } catch (ex) {
+ if (ex.result != Cr.NS_ERROR_NULL_POINTER)
+ throw ex;
+ do_print("Initialisation thrown NS_ERROR_NULL_POINTER as expected.");
+ }
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js b/toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js
new file mode 100644
index 000000000..e5ceb33e5
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test the component behaves correctly when no error callback is
+ * provided and an error occurs.
+ */
+add_task(function* test_error_with_no_error_callback() {
+
+ let watcher = makeWatcher();
+ let testPath = 'someInvalidPath';
+
+ // Define a dummy callback function. In this test no callback is
+ // expected to be called.
+ let dummyFunc = function(changed) {
+ do_throw("Not expected in this test.");
+ };
+
+ // We don't pass an error callback and try to watch an invalid
+ // path.
+ watcher.addPath(testPath, dummyFunc);
+});
+
+/**
+ * Test the component behaves correctly when no error callback is
+ * provided (no error should occur).
+ */
+add_task(function* test_watch_single_path_file_creation_no_error_cb() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ let tempFileName = "test_filecreation.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Watch the profile directory but do not pass an error callback.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve);
+
+ // Create a file within the watched directory.
+ let tmpFilePath = OS.Path.join(watchedDir, tempFileName);
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' to unregister).
+ watcher.removePath(watchedDir, deferred.resolve);
+
+ // Remove the test directory and all of its content.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js b/toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js
new file mode 100644
index 000000000..1375584a3
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test removing non watched path
+ */
+add_task(function* test_remove_not_watched() {
+ let nonExistingDir =
+ OS.Path.join(OS.Constants.Path.profileDir, "absolutelyNotExisting");
+
+ // Instantiate the native watcher.
+ let watcher = makeWatcher();
+
+ // Try to un-watch a path which wasn't being watched.
+ watcher.removePath(
+ nonExistingDir,
+ function(changed) {
+ do_throw("No change is expected in this test.");
+ },
+ function(xpcomError, osError) {
+ // When removing a resource which wasn't being watched, it should silently
+ // ignore the request.
+ do_throw("Unexpected exception: "
+ + xpcomError + " (XPCOM) "
+ + osError + " (OS Error)");
+ }
+ );
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js b/toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js
new file mode 100644
index 000000000..482ba6b8b
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test the watcher correctly handles two watches sharing the same
+ * change callback.
+ */
+add_task(function* test_watch_with_shared_callback() {
+
+ // Create and watch two sub-directories of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDirs =
+ [
+ OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground"),
+ OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground2")
+ ];
+
+ yield OS.File.makeDir(watchedDirs[0]);
+ yield OS.File.makeDir(watchedDirs[1]);
+
+ let tempFileName = "test_filecreation.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Watch both directories using the same callbacks.
+ yield promiseAddPath(watcher, watchedDirs[0], deferred.resolve, deferred.reject);
+ yield promiseAddPath(watcher, watchedDirs[1], deferred.resolve, deferred.reject);
+
+ // Remove the watch for the first directory, but keep watching
+ // for changes in the second: we need to make sure the callback
+ // survives the removal of the first watch.
+ watcher.removePath(watchedDirs[0], deferred.resolve, deferred.reject);
+
+ // Create a file within the watched directory.
+ let tmpFilePath = OS.Path.join(watchedDirs[1], tempFileName);
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ watcher.removePath(watchedDirs[1], deferred.resolve, deferred.reject);
+
+ // Remove the test directories and all of their content.
+ yield OS.File.removeDir(watchedDirs[0]);
+ yield OS.File.removeDir(watchedDirs[1]);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js
new file mode 100644
index 000000000..a434ec751
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files
+ do_get_profile();
+
+ // Start executing the tests
+ run_next_test();
+}
+
+/**
+ * Tests that the watcher correctly notifies of a directory creation when watching
+ * a single path.
+ */
+add_task(function* test_watch_single_path_directory_creation() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ let tmpDirPath = OS.Path.join(watchedDir, "testdir");
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Once ready, create a directory within the watched directory.
+ yield OS.File.makeDir(tmpDirPath);
+
+ // Wait until the watcher informs us that the file has changed.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpDirPath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Clean up the test directory.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js
new file mode 100644
index 000000000..2c74a9361
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Tests that the watcher correctly notifies of a directory deletion when watching
+ * a single path.
+ */
+add_task(function* test_watch_single_path_directory_deletion() {
+
+ let watchedDir = OS.Constants.Path.profileDir;
+ let tempDirName = "test";
+ let tmpDirPath = OS.Path.join(watchedDir, tempDirName);
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Create a directory within the watched directory.
+ yield OS.File.makeDir(tmpDirPath);
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the directory.
+ OS.File.removeDir(tmpDirPath);
+
+ // Wait until the watcher informs us that the file has changed.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpDirPath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js
new file mode 100644
index 000000000..9f87793f4
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js
@@ -0,0 +1,51 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test the watcher correctly notifies of a file creation when watching
+ * a single path.
+ */
+add_task(function* test_watch_single_path_file_creation() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ let tempFileName = "test_filecreation.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ let tmpFilePath = OS.Path.join(watchedDir, tempFileName);
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // create the file within the watched directory.
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the test directory and all of its content.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js
new file mode 100644
index 000000000..97d2d61bc
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+/**
+ * Test the watcher correctly notifies of a file deletion when watching
+ * a single path.
+ */
+add_task(function* test_watch_single_path_file_deletion() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ let tempFileName = "test_filedeletion.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Create a file within the directory to be watched. We do this
+ // before watching the directory so we do not get the creation notification.
+ let tmpFilePath = OS.Path.join(watchedDir, tempFileName);
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the file we created (should trigger a notification).
+ do_print('Removing ' + tmpFilePath);
+ yield OS.File.remove(tmpFilePath);
+
+ // Wait until the watcher informs us that the file was deleted.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the test directory and all of its content.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js
new file mode 100644
index 000000000..ba25fdff6
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files
+ do_get_profile();
+
+ // Start executing the tests
+ run_next_test();
+}
+
+/**
+ * Tests that the watcher correctly notifies of a file modification when watching
+ * a single path.
+ */
+add_task(function* test_watch_single_path_file_modification() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ let tempFileName = "test_filemodification.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Create a file within the directory to be watched. We do this
+ // before watching the directory so we do not get the creation notification.
+ let tmpFilePath = OS.Path.join(watchedDir, tempFileName);
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Once ready, modify the file to trigger the notification.
+ yield OS.File.writeAtomic(tmpFilePath, "some new data");
+
+ // Wait until the watcher informs us that the file has changed.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the test directory and all of its content.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js
new file mode 100644
index 000000000..c236c6e1d
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files
+ do_get_profile();
+
+ // Start executing the tests
+ run_next_test();
+}
+
+/**
+ * Test that we correctly handle watching directories when hundreds of files
+ * change simultaneously.
+ */
+add_task(function* test_fill_notification_buffer() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ // The number of files to create.
+ let numberOfFiles = 100;
+ let fileNameBase = "testFile";
+
+ // This will be used to keep track of the number of changes within the watched
+ // directory.
+ let detectedChanges = 0;
+
+ // We expect at least the following notifications for each file:
+ // - File creation
+ // - File deletion
+ let expectedChanges = numberOfFiles * 2;
+
+ // Instantiate the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Initialise the change callback.
+ let changeCallback = function(changed) {
+ do_print(changed + " has changed.");
+
+ detectedChanges += 1;
+
+ // Resolve the promise if we get all the expected changes.
+ if (detectedChanges >= expectedChanges) {
+ deferred.resolve();
+ }
+ };
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ yield promiseAddPath(watcher, watchedDir, changeCallback, deferred.reject);
+
+ // Create and then remove the files within the watched directory.
+ for (let i = 0; i < numberOfFiles; i++) {
+ let tmpFilePath = OS.Path.join(watchedDir, fileNameBase + i);
+ yield OS.File.writeAtomic(tmpFilePath, "test content");
+ yield OS.File.remove(tmpFilePath);
+ }
+
+ // Wait until the watcher informs us that all the files were
+ // created, modified and removed.
+ yield deferred.promise;
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'changeCallback' and 'errorCallback' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, changeCallback, deferred.reject);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js
new file mode 100644
index 000000000..c55b262f1
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js
@@ -0,0 +1,114 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files
+ do_get_profile();
+
+ // Start executing the tests
+ run_next_test();
+}
+
+/**
+ * Tests the watcher by watching several resources.
+ * This test creates the specified number of directory inside the profile
+ * directory, adds each one of them to the watched list the creates
+ * a file in them in order to trigger the notification.
+ * The test keeps track of the number of times the changes callback is
+ * called in order to verify the success of the test.
+ */
+add_task(function* test_watch_multi_paths() {
+
+ // The number of resources to watch. We expect changes for
+ // creating a file within each directory.
+ let resourcesToWatch = 5;
+ let watchedDir = OS.Constants.Path.profileDir;
+
+ // The directories to be watched will be created with.
+ let tempDirNameBase = "FileWatcher_Test_";
+ let tempFileName = "test.tmp";
+
+ // Instantiate the native watcher.
+ let watcher = makeWatcher();
+
+ // This will be used to keep track of the number of changes within the watched
+ // resources.
+ let detectedChanges = 0;
+ let watchedResources = 0;
+ let unwatchedResources = 0;
+
+ let deferredChanges = Promise.defer();
+ let deferredSuccesses = Promise.defer();
+ let deferredShutdown = Promise.defer();
+
+ // Define the change callback function.
+ let changeCallback = function(changed) {
+ do_print(changed + " has changed.");
+
+ detectedChanges += 1;
+
+ // Resolve the promise if we get all the expected changes.
+ if (detectedChanges === resourcesToWatch) {
+ deferredChanges.resolve();
+ }
+ };
+
+ // Define the watch success callback function.
+ let watchSuccessCallback = function(resourcePath) {
+ do_print(resourcePath + " is being watched.");
+
+ watchedResources += 1;
+
+ // Resolve the promise when all the resources are being
+ // watched.
+ if (watchedResources === resourcesToWatch) {
+ deferredSuccesses.resolve();
+ }
+ };
+
+ // Define the watch success callback function.
+ let unwatchSuccessCallback = function(resourcePath) {
+ do_print(resourcePath + " is being un-watched.");
+
+ unwatchedResources += 1;
+
+ // Resolve the promise when all the resources are being
+ // watched.
+ if (unwatchedResources === resourcesToWatch) {
+ deferredShutdown.resolve();
+ }
+ };
+
+ // Create the directories and add them to the watched resources list.
+ for (let i = 0; i < resourcesToWatch; i++) {
+ let tmpSubDirPath = OS.Path.join(watchedDir, tempDirNameBase + i);
+ do_print("Creating the " + tmpSubDirPath + " directory.");
+ yield OS.File.makeDir(tmpSubDirPath);
+ watcher.addPath(tmpSubDirPath, changeCallback, deferredChanges.reject, watchSuccessCallback);
+ }
+
+ // Wait until the watcher informs us that all the desired resources
+ // are being watched.
+ yield deferredSuccesses.promise;
+
+ // Create a file within each watched directory.
+ for (let i = 0; i < resourcesToWatch; i++) {
+ let tmpFilePath = OS.Path.join(watchedDir, tempDirNameBase + i, tempFileName);
+ yield OS.File.writeAtomic(tmpFilePath, "test content");
+ }
+
+ // Wait until the watcher informs us that all the files were created.
+ yield deferredChanges.promise;
+
+ // Remove the directories we have created.
+ for (let i = 0; i < resourcesToWatch; i++) {
+ let tmpSubDirPath = OS.Path.join(watchedDir, tempDirNameBase + i);
+ watcher.removePath(tmpSubDirPath, changeCallback, deferredChanges.reject, unwatchSuccessCallback);
+ }
+
+ // Wait until the watcher un-watches the resources.
+ yield deferredShutdown.promise;
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.js
new file mode 100644
index 000000000..13a3de8d3
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.js
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files.
+ do_get_profile();
+
+ // Start executing the tests.
+ run_next_test();
+}
+
+/**
+ * Test the watcher correctly notifies of a file creation in a subdirectory
+ * of the watched sub-directory (recursion).
+ */
+add_task(function* test_watch_recursively() {
+
+ // Create and watch a sub-directory of the profile directory so we don't
+ // catch notifications we're not interested in (i.e. "startupCache").
+ let watchedDir = OS.Path.join(OS.Constants.Path.profileDir, "filewatcher_playground");
+ yield OS.File.makeDir(watchedDir);
+
+ // We need at least 2 levels of directories to test recursion.
+ let subdirectory = OS.Path.join(watchedDir, "level1");
+ yield OS.File.makeDir(subdirectory);
+
+ let tempFileName = "test_filecreation.tmp";
+
+ // Instantiate and initialize the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ let tmpFilePath = OS.Path.join(subdirectory, tempFileName);
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ yield promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Create a file within the subdirectory of the watched directory.
+ yield OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = yield deferred.promise;
+ do_check_eq(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ yield promiseRemovePath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the test directory and all of its content.
+ yield OS.File.removeDir(watchedDir);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js b/toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js
new file mode 100644
index 000000000..fffdff24b
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function run_test() {
+ // Set up profile. We will use profile path create some test files
+ do_get_profile();
+
+ // Start executing the tests
+ run_next_test();
+}
+
+/**
+ * Test watching non-existing path
+ */
+add_task(function* test_watching_non_existing() {
+ let notExistingDir =
+ OS.Path.join(OS.Constants.Path.profileDir, "absolutelyNotExisting");
+
+ // Instantiate the native watcher.
+ let watcher = makeWatcher();
+ let deferred = Promise.defer();
+
+ // Try watch a path which doesn't exist.
+ watcher.addPath(notExistingDir, deferred.reject, deferred.resolve);
+
+ // Wait until the watcher informs us that there was an error.
+ let error = yield deferred.promise;
+ do_check_eq(error, Components.results.NS_ERROR_FILE_NOT_FOUND);
+});
diff --git a/toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini b/toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini
new file mode 100644
index 000000000..d6cc968eb
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini
@@ -0,0 +1,18 @@
+[DEFAULT]
+head = head.js
+tail =
+skip-if = os != "win"
+
+[test_arguments.js]
+[test_no_error_callback.js]
+[test_remove_non_watched.js]
+[test_shared_callback.js]
+[test_watch_file_creation_single.js]
+[test_watch_file_deletion_single.js]
+[test_watch_file_modification_single.js]
+[test_watch_directory_creation_single.js]
+[test_watch_directory_deletion_single.js]
+[test_watch_many_changes.js]
+[test_watch_multi_paths.js]
+[test_watch_recursively.js]
+[test_watch_resource.js]