Bug 926332 - Expose getTestFile to mochitest chrome/browser that returns nsIFile instance for test data files. r=jmaher
☠☠ backed out by 7cb193c966bf ☠ ☠
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 17 Oct 2013 14:27:23 -0400
changeset 151124 62732da6ae3d5addd4e4522610d042cf1d8804f6
parent 151123 7063d9f5c1fdd312bdc8403fc6cd34e30d76a782
child 151125 dc42a14663fe4a54852f59772af67962c906b527
push id3096
push userryanvm@gmail.com
push dateThu, 17 Oct 2013 18:27:38 +0000
treeherderfx-team@62732da6ae3d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs926332
milestone27.0a1
Bug 926332 - Expose getTestFile to mochitest chrome/browser that returns nsIFile instance for test data files. r=jmaher
testing/mochitest/chrome-harness.js
testing/mochitest/chrome/Makefile.in
testing/mochitest/chrome/test-dir/test-file
testing/mochitest/chrome/test_chromeGetTestFile.xul
testing/mochitest/tests/browser/browser.ini
testing/mochitest/tests/browser/browser_getTestFile.js
testing/mochitest/tests/browser/test-dir/test-file
--- a/testing/mochitest/chrome-harness.js
+++ b/testing/mochitest/chrome-harness.js
@@ -282,32 +282,69 @@ function extractJarToTmp(jar) {
   /* Create dir structure first, no guarantee about ordering of directories and
    * files returned from findEntries.
    */
   var dirs = zReader.findEntries(filepath + '*/');
   while (dirs.hasMore()) {
     var targetDir = buildRelativePath(dirs.getNext(), tmpdir, filepath);
     // parseInt is used because octal escape sequences cause deprecation warnings
     // in strict mode (which is turned on in debug builds)
-    targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
+    if (!targetDir.exists()) {
+      targetDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8));
+    }
   }
 
   //now do the files
   var files = zReader.findEntries(filepath + "*");
   while (files.hasMore()) {
     var fname = files.getNext();
     if (fname.substr(-1) != '/') {
       var targetFile = buildRelativePath(fname, tmpdir, filepath);
       zReader.extract(fname, targetFile);
     }
   }
   return tmpdir;
 }
 
 /*
+ * Take a relative path from the current mochitest file
+ * and returns the absolute path for the given test data file.
+ */
+function getTestFilePath(path) {
+  if (path[0] == "/") {
+    throw new Error("getTestFilePath only accepts relative path");
+  }
+  // Get the chrome/jar uri for the current mochitest file
+  // gTestPath being defined by the test harness in browser-chrome tests
+  // or window is being used for mochitest-browser
+  var baseURI = typeof(gTestPath) == "string" ? gTestPath : window.location.href;
+  var parentURI = getResolvedURI(getRootDirectory(baseURI));
+  var file;
+  if (parentURI.JARFile) {
+    // If it's a jar/zip, we have to extract it first
+    file = extractJarToTmp(parentURI);
+  } else {
+    // Otherwise, we can directly cast it to a file URI
+    var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"].
+                      getService(Components.interfaces.nsIFileProtocolHandler);
+    file = fileHandler.getFileFromURLSpec(parentURI.spec);
+  }
+  // Then walk by the given relative path
+  path.split("/")
+      .forEach(function (p) {
+        if (p == "..") {
+          file = file.parent;
+        } else if (p != ".") {
+          file.append(p);
+        }
+      });
+  return file.path;
+}
+
+/*
  * Simple utility function to take the directory structure in jarentryname and 
  * translate that to a path of a nsILocalFile.
  */
 function buildRelativePath(jarentryname, destdir, basepath)
 {
   var baseParts = basepath.split('/');
   if (baseParts[baseParts.length-1] == '') {
     baseParts.pop();
--- a/testing/mochitest/chrome/Makefile.in
+++ b/testing/mochitest/chrome/Makefile.in
@@ -5,12 +5,14 @@
 
 include $(topsrcdir)/config/rules.mk
 
 _STATIC_FILES = test_sample.xul \
 		test_sanityChromeUtils.xul \
 		test_sanityPluginUtils.html \
 		test_sanityException.xul \
 		test_sanityException2.xul \
+		test_chromeGetTestFile.xul \
+		test-dir/ \
 		$(NULL)
 
 libs:: $(_STATIC_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/chrome/test-dir/test-file
@@ -0,0 +1,1 @@
+foo
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/chrome/test_chromeGetTestFile.xul
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<window title="Test chrome harness functions"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+  <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+  <script type="application/javascript">
+  <![CDATA[
+    let {Promise} = Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js");
+    Components.utils.import("resource://gre/modules/osfile.jsm");
+    let decoder = new TextDecoder();
+
+    SimpleTest.waitForExplicitFinish();
+
+    SimpleTest.doesThrow(function () {
+      getTestFilePath("/test_chromeGetTestFile.xul")
+    }, "getTestFilePath rejects absolute paths");
+
+    Promise.all([
+      OS.File.exists(getTestFilePath("test_chromeGetTestFile.xul"))
+        .then(function (exists) {
+          ok(exists, "getTestFilePath consider the path as being relative");
+        }),
+
+      OS.File.exists(getTestFilePath("./test_chromeGetTestFile.xul"))
+        .then(function (exists) {
+          ok(exists, "getTestFilePath also accepts explicit relative path");
+        }),
+
+      OS.File.exists(getTestFilePath("./test_chromeGetTestFileTypo.xul"))
+        .then(function (exists) {
+          ok(!exists, "getTestFilePath do not throw if the file doesn't exists");
+        }),
+
+      OS.File.read(getTestFilePath("test-dir/test-file"))
+        .then(function (array) {
+          is(decoder.decode(array), "foo\n", "getTestFilePath can reach sub-folder files 1/2");
+        }),
+
+      OS.File.read(getTestFilePath("./test-dir/test-file"))
+        .then(function (array) {
+          is(decoder.decode(array), "foo\n", "getTestFilePath can reach sub-folder files 2/2");
+        })
+
+    ]).then(function () {
+      SimpleTest.finish();
+    }, console.error);
+  ]]>
+  </script>
+</window>
--- a/testing/mochitest/tests/browser/browser.ini
+++ b/testing/mochitest/tests/browser/browser.ini
@@ -1,20 +1,25 @@
 [DEFAULT]
-support-files = head.js
+support-files =
+  head.js
 
 [browser_add_task.js]
 [browser_async.js]
 [browser_head.js]
 [browser_pass.js]
 [browser_popupNode.js]
 [browser_popupNode_check.js]
 [browser_privileges.js]
 [browser_sanityException.js]
 [browser_sanityException2.js]
+[browser_getTestFile.js]
+support-files =
+  test-dir/*
+
 # Disabled, these are only good for testing the harness' failure reporting
 #  browser_zz_fail_openwindow.js
 #  browser_fail.js
 #  browser_fail_add_task.js
 #  browser_fail_async_throw.js
 #  browser_fail_fp.js
 #  browser_fail_pf.js
 #  browser_fail_throw.js
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/tests/browser/browser_getTestFile.js
@@ -0,0 +1,44 @@
+function test() {
+  let {Promise} = Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js");
+  Components.utils.import("resource://gre/modules/osfile.jsm");
+  let decoder = new TextDecoder();
+
+  waitForExplicitFinish();
+
+  SimpleTest.doesThrow(function () {
+    getTestFilePath("/browser_getTestFile.js")
+  }, "getTestFilePath rejects absolute paths");
+
+  Promise.all([
+    OS.File.exists(getTestFilePath("browser_getTestFile.js"))
+      .then(function (exists) {
+        ok(exists, "getTestFilePath consider the path as being relative");
+      }),
+
+    OS.File.exists(getTestFilePath("./browser_getTestFile.js"))
+      .then(function (exists) {
+        ok(exists, "getTestFilePath also accepts explicit relative path");
+      }),
+
+    OS.File.exists(getTestFilePath("./browser_getTestFileTypo.xul"))
+      .then(function (exists) {
+        ok(!exists, "getTestFilePath do not throw if the file doesn't exists");
+      }),
+
+    OS.File.read(getTestFilePath("test-dir/test-file"))
+      .then(function (array) {
+        is(decoder.decode(array), "foo\n", "getTestFilePath can reach sub-folder files 1/2");
+      }),
+
+    OS.File.read(getTestFilePath("./test-dir/test-file"))
+      .then(function (array) {
+        is(decoder.decode(array), "foo\n", "getTestFilePath can reach sub-folder files 2/2");
+      })
+
+  ]).then(function () {
+    finish();
+  }, function (error) {
+    ok(false, error);
+    finish();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/tests/browser/test-dir/test-file
@@ -0,0 +1,1 @@
+foo