summaryrefslogtreecommitdiffstats
path: root/toolkit/components/filewatcher/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /toolkit/components/filewatcher/tests
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/filewatcher/tests')
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/head.js27
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_arguments.js81
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js70
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js45
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js70
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js56
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js50
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js58
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js61
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js61
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js75
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js127
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.js62
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js33
-rw-r--r--toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini17
15 files changed, 893 insertions, 0 deletions
diff --git a/toolkit/components/filewatcher/tests/xpcshell/head.js b/toolkit/components/filewatcher/tests/xpcshell/head.js
new file mode 100644
index 0000000000..57c777feb4
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/head.js
@@ -0,0 +1,27 @@
+/* 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";
+
+ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
+ChromeUtils.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 0000000000..bf713338ca
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_arguments.js
@@ -0,0 +1,81 @@
+/* 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(async 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;
+ }
+ info("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;
+ }
+ info("Initialisation thrown NS_ERROR_NULL_POINTER as expected.");
+ }
+});
+
+/**
+ * Test for removePath usage with null arguments.
+ */
+add_task(async 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;
+ }
+ info("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;
+ }
+ info("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 0000000000..c1404f3d63
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_no_error_callback.js
@@ -0,0 +1,70 @@
+/* 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(async 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(async 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"
+ );
+ await 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.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve);
+
+ // Create a file within the watched directory.
+ let tmpFilePath = OS.Path.join(watchedDir, tempFileName);
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = await deferred.promise;
+ Assert.equal(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.
+ await 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 0000000000..dc0d25efc9
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_remove_non_watched.js
@@ -0,0 +1,45 @@
+/* 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(async 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 0000000000..ac886c6bc3
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_shared_callback.js
@@ -0,0 +1,70 @@
+/* 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(async 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"),
+ ];
+
+ await OS.File.makeDir(watchedDirs[0]);
+ await 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.
+ await promiseAddPath(
+ watcher,
+ watchedDirs[0],
+ deferred.resolve,
+ deferred.reject
+ );
+ await 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);
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = await deferred.promise;
+ Assert.equal(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.
+ await OS.File.removeDir(watchedDirs[0]);
+ await 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 0000000000..d3ab9739df
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_creation_single.js
@@ -0,0 +1,56 @@
+/* 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(async 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"
+ );
+ await 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.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Once ready, create a directory within the watched directory.
+ await OS.File.makeDir(tmpDirPath);
+
+ // Wait until the watcher informs us that the file has changed.
+ let changed = await deferred.promise;
+ Assert.equal(changed, tmpDirPath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await promiseRemovePath(
+ watcher,
+ watchedDir,
+ deferred.resolve,
+ deferred.reject
+ );
+
+ // Clean up the test directory.
+ await 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 0000000000..697470b31b
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_directory_deletion_single.js
@@ -0,0 +1,50 @@
+/* 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(async 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.
+ await OS.File.makeDir(tmpDirPath);
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ await 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 = await deferred.promise;
+ Assert.equal(changed, tmpDirPath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await 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 0000000000..a77d08309d
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_creation_single.js
@@ -0,0 +1,58 @@
+/* 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(async 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"
+ );
+ await 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.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // create the file within the watched directory.
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = await deferred.promise;
+ Assert.equal(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await promiseRemovePath(
+ watcher,
+ watchedDir,
+ deferred.resolve,
+ deferred.reject
+ );
+
+ // Remove the test directory and all of its content.
+ await 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 0000000000..6dbc118b14
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_deletion_single.js
@@ -0,0 +1,61 @@
+/* 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(async 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"
+ );
+ await 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);
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Remove the file we created (should trigger a notification).
+ info("Removing " + tmpFilePath);
+ await OS.File.remove(tmpFilePath);
+
+ // Wait until the watcher informs us that the file was deleted.
+ let changed = await deferred.promise;
+ Assert.equal(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await promiseRemovePath(
+ watcher,
+ watchedDir,
+ deferred.resolve,
+ deferred.reject
+ );
+
+ // Remove the test directory and all of its content.
+ await 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 0000000000..ec66366deb
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_file_modification_single.js
@@ -0,0 +1,61 @@
+/* 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(async 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"
+ );
+ await 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);
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Add the profile directory to the watch list and wait for the file watcher
+ // to start watching it.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Once ready, modify the file to trigger the notification.
+ await OS.File.writeAtomic(tmpFilePath, "some new data");
+
+ // Wait until the watcher informs us that the file has changed.
+ let changed = await deferred.promise;
+ Assert.equal(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await promiseRemovePath(
+ watcher,
+ watchedDir,
+ deferred.resolve,
+ deferred.reject
+ );
+
+ // Remove the test directory and all of its content.
+ await 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 0000000000..14f425c65f
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_many_changes.js
@@ -0,0 +1,75 @@
+/* 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(async 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"
+ );
+ await 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) {
+ info(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.
+ await 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);
+ await OS.File.writeAtomic(tmpFilePath, "test content");
+ await OS.File.remove(tmpFilePath);
+ }
+
+ // Wait until the watcher informs us that all the files were
+ // created, modified and removed.
+ await deferred.promise;
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'changeCallback' and 'errorCallback' to unregister).
+ await 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 0000000000..f32afaa71e
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_multi_paths.js
@@ -0,0 +1,127 @@
+/* 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(async 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) {
+ info(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) {
+ info(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) {
+ info(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);
+ info("Creating the " + tmpSubDirPath + " directory.");
+ await 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.
+ await 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
+ );
+ await OS.File.writeAtomic(tmpFilePath, "test content");
+ }
+
+ // Wait until the watcher informs us that all the files were created.
+ await 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.
+ await 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 0000000000..830bddfd67
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_recursively.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 notifies of a file creation in a subdirectory
+ * of the watched sub-directory (recursion).
+ */
+add_task(async 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"
+ );
+ await OS.File.makeDir(watchedDir);
+
+ // We need at least 2 levels of directories to test recursion.
+ let subdirectory = OS.Path.join(watchedDir, "level1");
+ await 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.
+ await promiseAddPath(watcher, watchedDir, deferred.resolve, deferred.reject);
+
+ // Create a file within the subdirectory of the watched directory.
+ await OS.File.writeAtomic(tmpFilePath, "some data");
+
+ // Wait until the watcher informs us that the file was created.
+ let changed = await deferred.promise;
+ Assert.equal(changed, tmpFilePath);
+
+ // Remove the watch and free the associated memory (we need to
+ // reuse 'deferred.resolve' and 'deferred.reject' to unregister).
+ await promiseRemovePath(
+ watcher,
+ watchedDir,
+ deferred.resolve,
+ deferred.reject
+ );
+
+ // Remove the test directory and all of its content.
+ await 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 0000000000..355624fff1
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/test_watch_resource.js
@@ -0,0 +1,33 @@
+/* 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(async function test_watching_non_existing() {
+ let notExistingDir = OS.Path.join(
+ OS.Constants.Path.profileDir,
+ "absolutelyNotExisting"
+ );
+
+ // Instantiate the native watcher.
+ let watcher = makeWatcher();
+ let error = await new Promise((resolve, reject) => {
+ // Try watch a path which doesn't exist.
+ watcher.addPath(notExistingDir, reject, resolve);
+
+ // Wait until the watcher informs us that there was an error.
+ });
+ Assert.equal(error, Cr.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 0000000000..51bb8e1188
--- /dev/null
+++ b/toolkit/components/filewatcher/tests/xpcshell/xpcshell.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+head = head.js
+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]