Bug 842818 - Run WebCrypto tests in Workers r=mt,rbarnes
authorTim Taubert <ttaubert@mozilla.com>
Mon, 21 Sep 2015 19:53:01 +0200
changeset 292424 ffcb400c1a48223f5ed74bd4f89b5fbe9602f70e
parent 292423 a98b4fa6de54138696403c6c98c7ea5ba61035bf
child 292425 f83f79281511d9ea9d8c5bde4ad0c1ef15d27a89
push id30160
push userryanvm@gmail.com
push dateSun, 10 Apr 2016 20:21:04 +0000
treeherdermozilla-central@29d5a4175c8b [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" };