Bug 842818 - Run WebCrypto tests in Workers r=mt,rbarnes
authorTim Taubert <ttaubert@mozilla.com>
Mon, 21 Sep 2015 19:53:01 +0200
changeset 330295 ffcb400c1a48
parent 330294 a98b4fa6de54
child 330296 f83f79281511
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmt, rbarnes
bugs842818
milestone48.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 842818 - Run WebCrypto tests in Workers r=mt,rbarnes
dom/crypto/test/mochitest.ini
dom/crypto/test/test-array.js
dom/crypto/test/test-worker.js
dom/crypto/test/test_WebCrypto.html
dom/crypto/test/test_WebCrypto_JWK.html
--- a/dom/crypto/test/mochitest.ini
+++ b/dom/crypto/test/mochitest.ini
@@ -1,15 +1,16 @@
 [DEFAULT]
 # Bug 1010743 - Re-enable WebCrypto tests on b2g
 skip-if = (buildapp == 'b2g')
 support-files =
   file_indexedDB.html
   test-array.js
   test-vectors.js
+  test-worker.js
   test_WebCrypto.css
   util.js
 
 [test_indexedDB.html]
 skip-if = toolkit == 'android' # bug 1200570
 [test_WebCrypto.html]
 [test_WebCrypto_DH.html]
 [test_WebCrypto_ECDH.html]
--- a/dom/crypto/test/test-array.js
+++ b/dom/crypto/test/test-array.js
@@ -83,33 +83,66 @@ function Test(name, test) {
     if (this.startTime &&  this.endTime) {
       this.row[2].innerHTML = (this.endTime - this.startTime) + " ms";
     } else {
       this.row[2].innerHTML = "";
     }
   };
 }
 
+function WorkerTest(worker, name, test) {
+  this.name = `${name} (Worker)`;
+  this.startTime = null;
+  this.endTime = null;
+  this.result = null;
+  this.row = null;
+
+  this.run = function() {
+    // Note the start time
+    this.startTime = new Date();
+
+    // Send the test code to the worker.
+    worker.postMessage(test.toSource());
+
+    // We expect only boolean responses from the worker script.
+    worker.onmessage = e => this.complete(e.data);
+    worker.onerror = e => this.complete(false);
+  };
+
+  var base = new Test(name, test);
+
+  // Inherit what we need from the |Test| class. We can't simply use its
+  // prototype as Test is just a function that can be used like a constructor.
+  for (var method of ["draw", "setRow", "next", "complete"]) {
+    this[method] = base[method].bind(this);
+  }
+}
+
 var TestArray = {
   tests: [],
   table: null,
   passSpan: null,
   failSpan: null,
   pendingSpan: null,
   pass: 0,
   fail: 0,
   pending: 0,
   currTest: 0,
+  worker: new Worker("test-worker.js"),
 
   addTest: function(name, testFn) {
     // Give it a reference to the array
     var test = new Test(name, testFn);
     test.ta = this;
+
     // Add test to tests
     this.tests.push(test);
+
+    // Run the test in a worker too.
+    this.tests.push(new WorkerTest(this.worker, name, testFn));
   },
 
   updateSummary: function() {
     this.pass = this.fail = this.pending = 0;
     for (var i=0; i<this.tests.length; ++i) {
       if (this.tests[i].result == true)  this.pass++;
       if (this.tests[i].result == false) this.fail++;
       if (this.tests[i].result == null)  this.pending++;
@@ -169,16 +202,17 @@ if (window.addEventListener) {
 
 function start() {
   TestArray.run();
 }
 
 MOCHITEST = ("SimpleTest" in window);
 if (MOCHITEST) {
   SimpleTest.waitForExplicitFinish();
+  SimpleTest.requestLongerTimeout(2);
   window.addEventListener("load", function() {
     SimpleTest.waitForFocus(start);
   });
 }
 
 function error(test) {
   return function(x) {
     console.log("ERROR :: " + x);
new file mode 100644
--- /dev/null
+++ b/dom/crypto/test/test-worker.js
@@ -0,0 +1,44 @@
+/* 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/. */
+
+importScripts("util.js");
+importScripts("test-vectors.js");
+
+var window = this;
+
+function finish(result) {
+  postMessage(result);
+}
+
+function complete(test, valid) {
+  return function(x) {
+    if (valid) {
+      finish(valid(x));
+    } else {
+      finish(true);
+    }
+  };
+}
+
+function memcmp_complete(test, value) {
+  return function (x) {
+    finish(util.memcmp(x, value));
+  };
+}
+
+function error(test) {
+  return function (x) {
+    throw x;
+  };
+}
+
+onmessage = function (msg) {
+  var test = eval("(" + msg.data + ")");
+
+  try {
+    test.call({complete: finish});
+  } catch (err) {
+    error(`Failed to run worker test: ${err}\n`);
+  }
+};
--- a/dom/crypto/test/test_WebCrypto.html
+++ b/dom/crypto/test/test_WebCrypto.html
@@ -987,16 +987,21 @@ TestArray.addTest(
     doCheckRSASSA().then(error(that), complete(that));
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
   "Test that we're using the right globals when creating objects",
   function() {
+    // This test isn't supported in workers.
+    if (window.importScripts) {
+      return this.complete(true);
+    }
+
     var that = this;
     var data = crypto.getRandomValues(new Uint8Array(10));
     var hmacAlg = {name: "HMAC", length: 256, hash: "SHA-1"};
 
     var rsaAlg = {
       name: "RSA-PSS",
       hash: "SHA-1",
       modulusLength: 1024,
--- a/dom/crypto/test/test_WebCrypto_JWK.html
+++ b/dom/crypto/test/test_WebCrypto_JWK.html
@@ -172,18 +172,21 @@ TestArray.addTest(
                  x.k == jwk.k
         }),
         error(that)
       );
   }
 );
 
 // -----------------------------------------------------------------------------
-function importExportRSAPrivateKey(jwk) {
-  return function () {
+TestArray.addTest(
+  "JWK import/export of an RSA private key",
+  function () {
+    var jwk = tv.rsassa.jwk_priv;
+
     var that = this;
     var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
 
     function doExport(k) {
       return crypto.subtle.exportKey("jwk", k);
     }
 
     crypto.subtle.importKey("jwk", jwk, alg, true, ['sign'])
@@ -203,26 +206,53 @@ function importExportRSAPrivateKey(jwk) 
                  x.q  == jwk.q  &&
                  x.dp == jwk.dp &&
                  x.dq == jwk.dq &&
                  x.qi == jwk.qi;
           }),
         error(that)
       );
   }
-}
-
-TestArray.addTest(
-  "JWK import/export of an RSA private key",
-  importExportRSAPrivateKey(tv.rsassa.jwk_priv)
 );
 
+// -----------------------------------------------------------------------------
 TestArray.addTest(
   "JWK import/export of an RSA private key where p < q",
-  importExportRSAPrivateKey(tv.rsassa.jwk_priv_pLTq)
+  function () {
+    var jwk = tv.rsassa.jwk_priv_pLTq;
+
+    var that = this;
+    var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
+
+    function doExport(k) {
+      return crypto.subtle.exportKey("jwk", k);
+    }
+
+    crypto.subtle.importKey("jwk", jwk, alg, true, ['sign'])
+      .then(doExport)
+      .then(
+        complete(that, function(x) {
+          return hasBaseJwkFields(x) &&
+                 hasFields(x, ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi']) &&
+                 x.kty == 'RSA' &&
+                 x.alg == 'RS256' &&
+                 x.ext &&
+                 shallowArrayEquals(x.key_ops, ['sign']) &&
+                 x.n  == jwk.n  &&
+                 x.e  == jwk.e  &&
+                 x.d  == jwk.d  &&
+                 x.p  == jwk.p  &&
+                 x.q  == jwk.q  &&
+                 x.dp == jwk.dp &&
+                 x.dq == jwk.dq &&
+                 x.qi == jwk.qi;
+          }),
+        error(that)
+      );
+  }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
   "JWK export of an RSA public key",
   function () {
     var that = this;
     var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };