Bug 926332 - Expose getTestFile to mochitest chrome/browser that returns nsIFile instance for test data files. r=jmaher
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 17 Oct 2013 14:27:23 -0400
changeset 165211 5a315b0b917dc9412fb8754752793c0b62f71b17
parent 165210 e0c1a2edfbd87280e8f4476de548ccf74aa64a4a
child 165212 894025edbb7ba4e478e0386612d639102e619837
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs926332
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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