Bug 1084233 - Part 3: Add marionette test for unlocking pin. r=hsinyi
authorEdgar Chen <echen@mozilla.com>
Mon, 27 Oct 2014 11:10:35 +0800
changeset 242023 d638e47fe6380956933fc2340fb29d13a592729a
parent 242022 3392f55163d325c30380f92c827d4af46312d6dd
child 242024 1ce89b6f89893700dc0f15ab7c91fd5a9877ad19
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [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 3: Add marionette test for unlocking pin. r=hsinyi
dom/icc/tests/marionette/head.js
dom/icc/tests/marionette/manifest.ini
dom/icc/tests/marionette/test_icc_card_lock_unlock_pin.js
--- a/dom/icc/tests/marionette/head.js
+++ b/dom/icc/tests/marionette/head.js
@@ -133,16 +133,168 @@ function getMozIcc(aIccId) {
     ok(true, "iccManager.iccIds[0] is undefined");
     return null;
   }
 
   return iccManager.getIccById(aIccId);
 }
 
 /**
+ * Get MozMobileConnection by ServiceId
+ *
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: 0 if not indicated.
+ *
+ * @return A MozMobileConnection.
+ */
+function getMozMobileConnectionByServiceId(aServiceId) {
+  aServiceId = aServiceId || 0;
+  return workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
+}
+
+/**
+ * Set radio enabling state.
+ *
+ * Resolve no matter the request succeeds or fails. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabled(aEnabled, aServiceId) {
+  return getMozMobileConnectionByServiceId(aServiceId).setRadioEnabled(aEnabled)
+    .then(() => {
+      ok(true, "setRadioEnabled " + aEnabled + " on " + aServiceId + " success.");
+    }, (aError) => {
+      ok(false, "setRadioEnabled " + aEnabled + " on " + aServiceId + " " +
+         aError.name);
+    });
+}
+
+/**
+ * Wait for one named event.
+ *
+ * Resolve if that named event occurs.  Never reject.
+ *
+ * Fulfill params: the DOMEvent passed.
+ *
+ * @param aEventTarget
+ *        An EventTarget object.
+ * @param aEventName
+ *        A string event name.
+ * @param aMatchFun [optional]
+ *        A matching function returns true or false to filter the event.
+ *
+ * @return A deferred promise.
+ */
+function waitForTargetEvent(aEventTarget, aEventName, aMatchFun) {
+  let deferred = Promise.defer();
+
+  aEventTarget.addEventListener(aEventName, function onevent(aEvent) {
+    if (!aMatchFun || aMatchFun(aEvent)) {
+      aEventTarget.removeEventListener(aEventName, onevent);
+      ok(true, "Event '" + aEventName + "' got.");
+      deferred.resolve(aEvent);
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Set radio enabling state and wait for "radiostatechange" event.
+ *
+ * Resolve if radio state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aEnabled
+ *        A boolean state.
+ * @param aServiceId [optional]
+ *        A numeric DSDS service id. Default: the one indicated in
+ *        start*TestCommon() or 0 if not indicated.
+ *
+ * @return A deferred promise.
+ */
+function setRadioEnabledAndWait(aEnabled, aServiceId) {
+  let mobileConn = getMozMobileConnectionByServiceId(aServiceId);
+  let promises = [];
+
+  promises.push(waitForTargetEvent(mobileConn, "radiostatechange", function() {
+    // To ignore some transient states, we only resolve that deferred promise
+    // when |radioState| equals to the expected one.
+    return mobileConn.radioState === (aEnabled ? "enabled" : "disabled");
+  }));
+  promises.push(setRadioEnabled(aEnabled, aServiceId));
+
+  return Promise.all(promises);
+}
+
+/**
+ * Restart radio and wait card state changes to expected one.
+ *
+ * Resolve if card state changed to the expected one. Never reject.
+ *
+ * Fulfill params: (none)
+ *
+ * @param aCardState
+ *        Expected card state.
+ *
+ * @return A deferred promise.
+ */
+function restartRadioAndWait(aCardState) {
+  return setRadioEnabledAndWait(false).then(() => {
+    let promises = [];
+
+    promises.push(waitForTargetEvent(iccManager, "iccdetected")
+      .then((aEvent) => {
+        let icc = getMozIcc(aEvent.iccId);
+        if (icc.cardState !== aCardState) {
+          return waitForTargetEvent(icc, "cardstatechange", function() {
+            return icc.cardState === aCardState;
+          });
+        }
+      }));
+    promises.push(setRadioEnabledAndWait(true));
+
+    return Promise.all(promises);
+  });
+}
+
+/**
+ * Enable/Disable PIN-lock.
+ *
+ * Fulfill params: (none)
+ * Reject params:
+ *   An object contains error name and remaining retry count.
+ *   @see IccCardLockError
+ *
+ * @param aIcc
+ *        A MozIcc object.
+ * @param aEnabled
+ *        A boolean state.
+ *
+ * @return A deferred promise.
+ */
+function setPinLockEnabled(aIcc, aEnabled) {
+  let options = {
+    lockType: "pin",
+    enabled: aEnabled,
+    pin: DEFAULT_PIN
+  };
+
+  return aIcc.setCardLock(options);
+}
+
+/**
  * 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;
--- a/dom/icc/tests/marionette/manifest.ini
+++ b/dom/icc/tests/marionette/manifest.ini
@@ -3,16 +3,17 @@ b2g = true
 browser = false
 qemu = true
 
 [test_stk_proactive_command.js]
 [test_icc_contact.js]
 [test_icc_card_lock_get_retry_count.js]
 [test_icc_card_lock_change_pin.js]
 [test_icc_card_lock_enable_pin.js]
+[test_icc_card_lock_unlock_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]
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_icc_card_lock_unlock_pin.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testUnlockPin(aIcc, aPin, aErrorName, aRetryCount) {
+  log("testUnlockPin with pin=" + aPin);
+
+  return aIcc.unlockCardLock({ lockType: "pin", pin: aPin })
+    .then((aResult) => {
+      if (aErrorName) {
+        ok(false, "unlocking pin should not success");
+      }
+    }, (aError) => {
+      if (!aErrorName) {
+        ok(false, "unlocking pin should not fail");
+        return;
+      }
+
+      // Check the request error.
+      is(aError.name, aErrorName, "error.name");
+      is(aError.retryCount, aRetryCount, "error.retryCount");
+    });
+}
+
+function testUnlockPinAndWait(aIcc, aPin, aCardState) {
+  log("testUnlockPin with pin=" + aPin + ", and wait cardState changes to '" +
+      aCardState + "'");
+
+  let promises = [];
+
+  promises.push(waitForTargetEvent(aIcc, "cardstatechange", function() {
+    return aIcc.cardState === aCardState;
+  }));
+  promises.push(testUnlockPin(aIcc, aPin));
+
+  return Promise.all(promises);
+}
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+  let retryCount;
+
+  // Enable PIN-lock.
+  return setPinLockEnabled(icc, true)
+    // Reset card state to "pinRequired" by restarting radio
+    .then(() => restartRadioAndWait("pinRequired"))
+    .then(() => { icc = getMozIcc(); })
+
+    // Get current PIN-lock retry count.
+    .then(() => icc.getCardLockRetryCount("pin"))
+    .then((aResult) => {
+      retryCount = aResult.retryCount;
+      ok(true, "pin retryCount is " + retryCount);
+    })
+
+    // Test fail to unlock PIN-lock.
+    // The retry count should be decreased by 1.
+    .then(() => testUnlockPin(icc, "1111", "IncorrectPassword", retryCount - 1))
+
+    // Test success to unlock PIN-lock.
+    .then(() => testUnlockPinAndWait(icc, DEFAULT_PIN, "ready"))
+
+    // Restore pin state.
+    .then(() => setPinLockEnabled(icc, false));
+});