Bug 927560 - Shutdown osfile_async_worker.js, companion tests. r=froydnj, a=koi+
☠☠ backed out by 549aa6d4fabc ☠ ☠
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Fri, 13 Dec 2013 09:38:49 -0500
changeset 156870 66fd5784afd9b1b803d8a9d6d31b0ef5cd9cff6d
parent 156869 4f8e819f864498a85fea5c06f434f4132d1e692f
child 156871 d6f81ce77e7e7d1114603eeac43cc3fd1dd47881
push id366
push userryanvm@gmail.com
push dateFri, 13 Dec 2013 14:41:01 +0000
reviewersfroydnj, koi
bugs927560
milestone26.0
Bug 927560 - Shutdown osfile_async_worker.js, companion tests. r=froydnj, a=koi+
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
toolkit/components/osfile/tests/xpcshell/test_reset.js
toolkit/components/osfile/tests/xpcshell/test_shutdown.js
toolkit/components/osfile/tests/xpcshell/xpcshell.ini
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -155,17 +155,16 @@ let test = maketest("Main", function mai
     yield test_read_write();
     yield test_read_write_all();
     yield test_position();
     yield test_copy();
     yield test_mkdir();
     yield test_iter();
     yield test_exists();
     yield test_debug_test();
-    yield test_system_shutdown();
     yield test_duration();
     info("Test is over");
     SimpleTest.finish();
   });
 });
 
 /**
  * A file that we know exists and that can be used for reading.
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/tests/xpcshell/test_reset.js
@@ -0,0 +1,86 @@
+Components.utils.import("resource://gre/modules/Services.jsm", this);
+Components.utils.import("resource://gre/modules/Promise.jsm", this);
+Components.utils.import("resource://gre/modules/Task.jsm", this);
+Components.utils.import("resource://gre/modules/osfile.jsm", this);
+
+let Scope = {};
+Components.utils.import("resource://gre/modules/Services.jsm", Scope);
+
+Scope.Services.prefs.setBoolPref("toolkit.osfile.log", true);
+
+let Path = OS.Constants.Path;
+
+add_task(function init() {
+  do_get_profile();
+});
+
+add_task(function reset_before_launching() {
+  do_print("Reset without launching OS.File, it shouldn't break");
+  yield OS.File.resetWorker();
+});
+
+add_task(function transparent_reset() {
+  for (let i = 1; i < 3; ++i) {
+    do_print("Do stome stuff before and after " + i + " reset(s), " +
+             "it shouldn't break");
+    let CONTENT = "some content " + i;
+    let path = OS.Path.join(Path.profileDir, "tmp");
+    yield OS.File.writeAtomic(path, CONTENT);
+    for (let j = 0; j < i; ++j) {
+      yield OS.File.resetWorker();
+    }
+    let data = yield OS.File.read(path);
+    let string = (new TextDecoder()).decode(data);
+    do_check_eq(string, CONTENT);
+  }
+});
+
+add_task(function file_open_cannot_reset() {
+  let TEST_FILE = OS.Path.join(Path.profileDir, "tmp-" + Math.random());
+  do_print("Leaking file descriptor " + TEST_FILE + ", we shouldn't be able to reset");
+  let openedFile = yield OS.File.open(TEST_FILE, { create: true} );
+  let thrown = false;
+  try {
+    yield OS.File.resetWorker();
+  } catch (ex if ex.message.indexOf(TEST_FILE) != -1 ) {
+    thrown = true;
+  }
+  do_check_true(thrown);
+
+  do_print("Closing the file, we should now be able to reset");
+  yield openedFile.close();
+  yield OS.File.resetWorker();
+});
+
+add_task(function file_open_cannot_reset() {
+  let TEST_DIR = yield OS.File.getCurrentDirectory();
+  do_print("Leaking directory " + TEST_DIR + ", we shouldn't be able to reset");
+  let iterator = new OS.File.DirectoryIterator(TEST_DIR);
+  let thrown = false;
+  try {
+    yield OS.File.resetWorker();
+  } catch (ex if ex.message.indexOf(TEST_DIR) != -1 ) {
+    thrown = true;
+  }
+  do_check_true(thrown);
+
+  do_print("Closing the directory, we should now be able to reset");
+  yield iterator.close();
+  do_print("Directory is closed");
+  yield OS.File.resetWorker();
+});
+
+add_task(function finish_with_a_reset() {
+  do_print("Reset without waiting for the result");
+  // Arbitrary operation, just to wake up the worker
+  try {
+    yield OS.File.read("/foo");
+  } catch (ex) {
+  }
+  // Now reset
+  /*don't yield*/ OS.File.resetWorker();
+});
+
+function run_test() {
+  run_next_test();
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/tests/xpcshell/test_shutdown.js
@@ -0,0 +1,98 @@
+Components.utils.import("resource://gre/modules/Services.jsm", this);
+Components.utils.import("resource://gre/modules/Promise.jsm", this);
+Components.utils.import("resource://gre/modules/Task.jsm", this);
+Components.utils.import("resource://gre/modules/osfile.jsm", this);
+
+add_task(function init() {
+  do_get_profile();
+});
+
+/**
+ * Test logging of file descriptors leaks.
+ */
+add_task(function system_shutdown() {
+
+  // Test that unclosed files cause warnings
+  // Test that unclosed directories cause warnings
+  // Test that closed files do not cause warnings
+  // Test that closed directories do not cause warnings
+  function testLeaksOf(resource, topic) {
+    return Task.spawn(function() {
+      let deferred = Promise.defer();
+
+      // Register observer
+      Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
+      Services.prefs.setBoolPref("toolkit.osfile.log", true);
+      Services.prefs.setBoolPref("toolkit.osfile.log.redirect", true);
+      Services.prefs.setCharPref("toolkit.osfile.test.shutdown.observer", topic);
+
+      let observer = function(aMessage) {
+        try {
+          do_print("Got message: " + aMessage);
+          if (!(aMessage instanceof Components.interfaces.nsIConsoleMessage)) {
+            return;
+          }
+          let message = aMessage.message;
+          do_print("Got message: " + message);
+          if (message.indexOf("TEST OS Controller WARNING") < 0) {
+            return;
+          }
+          do_print("Got message: " + message + ", looking for resource " + resource);
+          if (message.indexOf(resource) < 0) {
+            return;
+          }
+          do_print("Resource: " + resource + " found");
+          do_execute_soon(deferred.resolve);
+        } catch (ex) {
+          do_execute_soon(function() {
+            deferred.reject(ex);
+          });
+        }
+      };
+      Services.console.registerListener(observer);
+      Services.obs.notifyObservers(null, topic, null);
+      do_timeout(2000, function() {
+        do_print("Timeout while waiting for resource: " + resource);
+        deferred.reject("timeout");
+      });
+
+      let resolved = false;
+      try {
+        yield deferred.promise;
+        resolved = true;
+      } catch (ex if ex == "timeout") {
+        resolved = false;
+      }
+      Services.console.unregisterListener(observer);
+      Services.prefs.clearUserPref("toolkit.osfile.log");
+      Services.prefs.clearUserPref("toolkit.osfile.log.redirect");
+      Services.prefs.clearUserPref("toolkit.osfile.test.shutdown.observer");
+      Services.prefs.clearUserPref("toolkit.async_shutdown.testing", true);
+
+      throw new Task.Result(resolved);
+    });
+  }
+
+  let TEST_DIR = OS.Path.join((yield OS.File.getCurrentDirectory()), "..");
+  do_print("Testing for leaks of directory iterator " + TEST_DIR);
+  let iterator = new OS.File.DirectoryIterator(TEST_DIR);
+  do_print("At this stage, we leak the directory");
+  do_check_true((yield testLeaksOf(TEST_DIR, "test.shutdown.dir.leak")));
+  yield iterator.close();
+  do_print("At this stage, we don't leak the directory anymore");
+  do_check_false((yield testLeaksOf(TEST_DIR, "test.shutdown.dir.noleak")));
+
+  let TEST_FILE = OS.Path.join(OS.Constants.Path.profileDir, "test");
+  do_print("Testing for leaks of file descriptor: " + TEST_FILE);
+  let openedFile = yield OS.File.open(TEST_FILE, { create: true} );
+  do_print("At this stage, we leak the file");
+  do_check_true((yield testLeaksOf(TEST_FILE, "test.shutdown.file.leak")));
+  yield openedFile.close();
+  do_print("At this stage, we don't leak the file anymore");
+  do_check_false((yield testLeaksOf(TEST_FILE, "test.shutdown.file.leak")));
+});
+
+
+function run_test() {
+  run_next_test();
+}
--- a/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
@@ -4,9 +4,11 @@ tail =
 
 [test_osfile_closed.js]
 [test_path.js]
 [test_osfile_async.js]
 [test_profiledir.js]
 [test_logging.js]
 # bug 845190 - thread pool wasn't shutdown assertions
 skip-if = (os == "win" || "linux") && debug
+[test_reset.js]
+[test_shutdown.js]
 [test_creationDate.js]