Bug 1084233 - Part 1: Introduce head.js and rewrite test_icc_card_lock.js with Promise. r=hsinyi
authorEdgar Chen <echen@mozilla.com>
Tue, 28 Oct 2014 15:23:44 +0800
changeset 217707 3d6c6dd443aebb6076044a12d0c2be15f38f38fa
parent 217706 c1bd2baefceb0acce3e0854256b36cc26de9175f
child 217708 3392f55163d325c30380f92c827d4af46312d6dd
push id27888
push userryanvm@gmail.com
push dateThu, 27 Nov 2014 02:38:47 +0000
treeherdermozilla-central@cef590a6f946 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs1084233
milestone36.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 1084233 - Part 1: Introduce head.js and rewrite test_icc_card_lock.js with Promise. r=hsinyi
dom/icc/tests/marionette/head.js
dom/icc/tests/marionette/manifest.ini
dom/icc/tests/marionette/test_icc_card_lock.js
dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
dom/icc/tests/marionette/test_icc_card_lock_get_retry_count.js
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/head.js
@@ -0,0 +1,194 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
+
+const PREF_KEY_RIL_DEBUGGING_ENABLED = "ril.debugging.enabled";
+
+// The pin code hard coded in emulator is "0000".
+const DEFAULT_PIN = "0000";
+
+// Emulate Promise.jsm semantics.
+Promise.defer = function() { return new Deferred(); }
+function Deferred() {
+  this.promise = new Promise(function(resolve, reject) {
+    this.resolve = resolve;
+    this.reject = reject;
+  }.bind(this));
+  Object.freeze(this);
+}
+
+let _pendingEmulatorCmdCount = 0;
+
+/**
+ * Send emulator command with safe guard.
+ *
+ * We should only call |finish()| after all emulator command transactions
+ * end, so here comes with the pending counter.  Resolve when the emulator
+ * gives positive response, and reject otherwise.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @param aCommand
+ *        A string command to be passed to emulator through its telnet console.
+ *
+ * @return A deferred promise.
+ */
+function runEmulatorCmdSafe(aCommand) {
+  let deferred = Promise.defer();
+
+  ++_pendingEmulatorCmdCount;
+  runEmulatorCmd(aCommand, function(aResult) {
+    --_pendingEmulatorCmdCount;
+
+    ok(true, "Emulator response: " + JSON.stringify(aResult));
+    if (Array.isArray(aResult) &&
+        aResult[aResult.length - 1] === "OK") {
+      deferred.resolve(aResult);
+    } else {
+      deferred.reject(aResult);
+    }
+  });
+
+  return deferred.promise;
+}
+
+let workingFrame;
+let iccManager;
+
+/**
+ * Push required permissions and test if
+ * |navigator.mozIccManager| exists. Resolve if it does,
+ * reject otherwise.
+ *
+ * Fulfill params:
+ *   iccManager -- an reference to navigator.mozIccManager.
+ *
+ * Reject params: (none)
+ *
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string.
+ *
+ * @return A deferred promise.
+ */
+function ensureIccManager(aAdditionalPermissions) {
+  let deferred = Promise.defer();
+
+  aAdditionalPermissions = aAdditionalPermissions || [];
+
+  if (aAdditionalPermissions.indexOf("mobileconnection") < 0) {
+    aAdditionalPermissions.push("mobileconnection");
+  }
+  let permissions = [];
+  for (let perm of aAdditionalPermissions) {
+    permissions.push({ "type": perm, "allow": 1, "context": document });
+  }
+
+  SpecialPowers.pushPermissions(permissions, function() {
+    ok(true, "permissions pushed: " + JSON.stringify(permissions));
+
+    // Permission changes can't change existing Navigator.prototype
+    // objects, so grab our objects from a new Navigator.
+    workingFrame = document.createElement("iframe");
+    workingFrame.addEventListener("load", function load() {
+      workingFrame.removeEventListener("load", load);
+
+      iccManager = workingFrame.contentWindow.navigator.mozIccManager;
+
+      if (iccManager) {
+        ok(true, "navigator.mozIccManager is instance of " + iccManager.constructor);
+      } else {
+        ok(true, "navigator.mozIccManager is undefined");
+      }
+
+      if (iccManager instanceof MozIccManager) {
+        deferred.resolve(iccManager);
+      } else {
+        deferred.reject();
+      }
+    });
+
+    document.body.appendChild(workingFrame);
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Get MozIcc by IccId
+ *
+ * @param aIccId [optional]
+ *        Default: The first item of |aIccManager.iccIds|.
+ *
+ * @return A MozIcc.
+ */
+function getMozIcc(aIccId) {
+  aIccId = aIccId || iccManager.iccIds[0];
+
+  if (!aIccId) {
+    ok(true, "iccManager.iccIds[0] is undefined");
+    return null;
+  }
+
+  return iccManager.getIccById(aIccId);
+}
+
+/**
+ * Wait for pending emulator transactions and call |finish()|.
+ */
+function cleanUp() {
+  // Use ok here so that we have at least one test run.
+  ok(true, ":: CLEANING UP ::");
+
+  waitFor(finish, function() {
+    return _pendingEmulatorCmdCount === 0;
+  });
+}
+
+/**
+ * Basic test routine helper for icc tests.
+ *
+ * This helper does nothing but clean-ups.
+ *
+ * @param aTestCaseMain
+ *        A function that takes no parameter.
+ */
+function startTestBase(aTestCaseMain) {
+  // Turn on debugging pref.
+  let debugPref = SpecialPowers.getBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED);
+  SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, true);
+
+  Promise.resolve()
+    .then(aTestCaseMain)
+    .catch((aError) => {
+      ok(false, "promise rejects during test: " + aError);
+    })
+    .then(() => {
+      // Restore debugging pref.
+      SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, debugPref);
+      cleanUp();
+    });
+}
+
+/**
+ * Common test routine helper for icc tests.
+ *
+ * This function ensures global variable |iccManager| and |icc| is available
+ * during the process and performs clean-ups as well.
+ *
+ * @param aTestCaseMain
+ *        A function that takes one parameter -- icc.
+ * @param aAdditonalPermissions [optional]
+ *        An array of permission strings other than "mobileconnection" to be
+ *        pushed. Default: empty string..
+ */
+function startTestCommon(aTestCaseMain, aAdditionalPermissions) {
+  startTestBase(function() {
+    return ensureIccManager(aAdditionalPermissions)
+      .then(aTestCaseMain);
+  });
+}
--- a/dom/icc/tests/marionette/manifest.ini
+++ b/dom/icc/tests/marionette/manifest.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_stk_proactive_command.js]
 [test_icc_contact.js]
-[test_icc_card_lock.js]
+[test_icc_card_lock_get_retry_count.js]
+[test_icc_card_lock_change_pin.js]
 [test_icc_card_state.js]
 [test_icc_info.js]
 [test_stk_refresh.js]
 [test_stk_poll_off.js]
 [test_stk_setup_event_list.js]
 [test_stk_setup_call.js]
 [test_stk_send_ss.js]
 [test_stk_send_ussd.js]
rename from dom/icc/tests/marionette/test_icc_card_lock.js
rename to dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
--- a/dom/icc/tests/marionette/test_icc_card_lock.js
+++ b/dom/icc/tests/marionette/test_icc_card_lock_change_pin.js
@@ -1,126 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 30000;
-MARIONETTE_HEAD_JS = "icc_header.js";
-
-/* Test PIN code changes fail */
-taskHelper.push(function testPinChangeFailed() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "1111",
-     newPin: "0000"});
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
 
-  request.onerror = function onerror() {
-    is(request.error.name, "IncorrectPassword");
-    // The default pin retries is 3, failed once becomes to 2
-    is(request.error.retryCount, 2);
-
-    // Reset pin retries by passing correct pin code.
-    let resetRequest = icc.setCardLock(
-      {lockType: "pin",
-       pin: "0000",
-       newPin: "0000"});
+const LOCK_TYPE = "pin";
 
-    resetRequest.onsuccess = function onsuccess() {
-      taskHelper.runNext();
-    };
-
-    resetRequest.onerror = function onerror() {
-      ok(false, "Reset pin retries got error: " + request.error.name);
-      taskHelper.runNext();
-    };
-  };
-});
-
-/* Test PIN code changes success */
-taskHelper.push(function testPinChangeSuccess() {
-  // The default pin is '0000' in emulator
-  let request = icc.setCardLock(
-    {lockType: "pin",
-     pin: "0000",
-     newPin: "0000"});
-
-  ok(request instanceof DOMRequest,
-     "request instanceof " + request.constructor);
-
-  request.onerror = function onerror() {
-    ok(false, "Should not fail, got error: " + request.error.name);
-
-    taskHelper.runNext();
-  };
-
-  request.onsuccess = function onsuccess() {
-    taskHelper.runNext();
-  };
-});
+function testChangePin(aIcc, aPin, aNewPin, aErrorName, aRetryCount) {
+  log("testChangePin for pin=" + aPin + " and newPin=" + aNewPin);
+  return aIcc.setCardLock({ lockType: LOCK_TYPE, pin: aPin, newPin: aNewPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "changing pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "changing pin should not fail");
+        return;
+      }
 
-/* Read PIN-lock retry count */
-taskHelper.push(function testPinCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('pin');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+      // check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-/* Read PUK-lock retry count */
-taskHelper.push(function testPukCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('puk');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
 
-  request.onsuccess = function onsuccess() {
-    ok(request.result.retryCount >= 0,
-        'retryCount is ' + request.result.retryCount);
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    // The operation is optional any might not be supported for all
-    // all locks. In this case, we generate 'NotSupportedError' for
-    // the valid lock types.
-    is(request.error.name, 'RequestNotSupported',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
+  return icc.getCardLockRetryCount(LOCK_TYPE)
+    // Get current PIN-lock retry count.
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, LOCK_TYPE + " retryCount is " + retryCount);
+    })
+    // Test PIN code changes fail.
+    // The retry count should be decreased by 1.
+    .then(() => testChangePin(icc, "1111", DEFAULT_PIN, "IncorrectPassword",
+                              retryCount - 1))
+    // Test PIN code changes success. This will reset the retry count.
+    .then(() => testChangePin(icc, DEFAULT_PIN, DEFAULT_PIN));
 });
-
-/* Read lock retry count for an invalid entries  */
-taskHelper.push(function testInvalidCardLockRetryCount() {
-  let request = icc.getCardLockRetryCount('invalid-lock-type');
-
-  ok(request instanceof DOMRequest,
-     'request instanceof ' + request.constructor);
-
-  request.onsuccess = function onsuccess() {
-    ok(false,
-        'request should never return success for an invalid lock type');
-    taskHelper.runNext();
-  };
-  request.onerror = function onerror() {
-    is(request.error.name, 'GenericFailure',
-        'error name is ' + request.error.name);
-    taskHelper.runNext();
-  };
-});
-
-// Start test
-taskHelper.runNext();
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_get_retry_count.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testGetCardLockRetryCount(aIcc, aLockType, aRetryCount) {
+  log("testGetCardLockRetryCount for " + aLockType);
+  return aIcc.getCardLockRetryCount(aLockType)
+    .then((aResult) => {
+      if (!aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not success");
+        return;
+      }
+
+      // Check the request result.
+      is(aResult.retryCount, aRetryCount, "result.retryCount");
+    }, (aError) => {
+      if (aRetryCount) {
+        ok(false, "getCardLockRetryCount(" + aLockType + ") should not fail");
+        return;
+      }
+
+      // Check the error.
+      is(aError.name, "GenericFailure", "error.name");
+    });
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // Read PIN-lock retry count.
+  // The default PIN-lock retry count hard coded in emulator is 3.
+  return testGetCardLockRetryCount(icc, "pin", 3)
+    // Read PUK-lock retry count.
+    // The default PUK-lock retry count hard coded in emulator is 6.
+    .then(() => testGetCardLockRetryCount(icc, "puk", 6))
+    // Read lock retry count for an invalid entries.
+    .then(() => testGetCardLockRetryCount(icc, "invalid-lock-type"));
+});