Bug 1159134 - Part 2: Add Test Cases for STK related Requests. r=echen
authorBevis Tseng <btseng@mozilla.com>
Tue, 05 May 2015 19:10:58 +0800
changeset 247120 abeb01323218b1815ba95f50fffb460dcf0a5647
parent 247119 ec84531589e4b6a2317a93cc92bfcb5b60eaa8da
child 247121 f21fac50a8cca34cf708d6acffca39e1d4d4e6d8
child 247221 97217ebc948633b5c537d2da10a470eb8b784183
push id60612
push userryanvm@gmail.com
push dateThu, 04 Jun 2015 13:28:04 +0000
treeherdermozilla-inbound@dbc89e025b5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1159134
milestone41.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 1159134 - Part 2: Add Test Cases for STK related Requests. r=echen
dom/icc/tests/marionette/head.js
dom/icc/tests/marionette/manifest.ini
dom/icc/tests/marionette/test_stk_event_download.js
dom/icc/tests/marionette/test_stk_menu_selection.js
dom/icc/tests/marionette/test_stk_response.js
dom/icc/tests/marionette/test_stk_timer_expiration.js
--- a/dom/icc/tests/marionette/head.js
+++ b/dom/icc/tests/marionette/head.js
@@ -126,28 +126,108 @@ function runEmulatorCmdSafe(aCommand) {
       }
     });
   });
 }
 
 /**
  * Send stk proactive pdu.
  *
- * Fulfill params: (none)
- * Reject params: (none)
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ * Reject params:
+ *   result -- an array of emulator response lines.
  *
  * @param aPdu
  *
  * @return A deferred promise.
  */
 function sendEmulatorStkPdu(aPdu) {
   let cmd = "stk pdu " + aPdu;
   return runEmulatorCmdSafe(cmd);
 }
 
+/**
+ * Peek the last STK terminal response sent to modem.
+ *
+ * Fulfill params:
+ *   result -- last terminal response in HEX String.
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+function peekLastStkResponse() {
+  return runEmulatorCmdSafe("stk lastresponse")
+    .then(aResult => aResult[0]);
+}
+
+/**
+ * Peek the last STK envelope sent to modem.
+ *
+ * Fulfill params:
+ *   result -- last envelope in HEX String.
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+function peekLastStkEnvelope() {
+  return runEmulatorCmdSafe("stk lastenvelope")
+    .then(aResult => aResult[0]);
+}
+
+/**
+ * Verify with the peeked STK response.
+ *
+ * Fulfill params:
+ *   result -- (none)
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @param aExpectResponse
+ *        The expected Response PDU in HEX String.
+ *
+ * @return A deferred promise.
+ */
+function verifyWithPeekedStkResponse(aExpectResponse) {
+  return new Promise(function(aResolve, aReject) {
+    window.setTimeout(function() {
+      peekLastStkResponse().then(aResult => {
+        is(aResult, aExpectResponse, "Verify sent APDU");
+        aResolve();
+      });
+    }, 3000);
+  });
+}
+
+/**
+ * Verify with the peeked STK response.
+ *
+ * Fulfill params:
+ *   result -- (none)
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @param aExpectEnvelope
+ *        The expected Envelope PDU in HEX String.
+ *
+ * @return A deferred promise.
+ */
+function verifyWithPeekedStkEnvelope(aExpectEnvelope) {
+  return new Promise(function(aResolve, aReject) {
+    window.setTimeout(function() {
+      peekLastStkEnvelope().then(aResult => {
+        is(aResult, aExpectEnvelope, "Verify sent APDU");
+        aResolve();
+      });
+    }, 3000);
+  });
+}
+
 let workingFrame;
 let iccManager;
 
 /**
  * Push required permissions and test if
  * |navigator.mozIccManager| exists. Resolve if it does,
  * reject otherwise.
  *
--- a/dom/icc/tests/marionette/manifest.ini
+++ b/dom/icc/tests/marionette/manifest.ini
@@ -31,8 +31,12 @@ qemu = true
 [test_stk_setup_idle_mode_text.js]
 [test_stk_bip_command.js]
 [test_stk_local_info.js]
 [test_stk_timer_management.js]
 [test_icc_access_invalid_object.js]
 [test_icc_detected_undetected_event.js]
 [test_icc_match_mvno.js]
 [test_icc_service_state.js]
+[test_stk_menu_selection.js]
+[test_stk_timer_expiration.js]
+[test_stk_event_download.js]
+[test_stk_response.js]
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_stk_event_download.js
@@ -0,0 +1,204 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 90000;
+MARIONETTE_HEAD_JS = "head.js";
+
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // APDU format of ENVELOPE:
+  // Class = 'A0', INS = 'C2', P1 = '00', P2 = '00', XXXX, (No Le)
+
+  // Since |sendStkEventDownload| is an API without call back to identify the
+  // result, the tests of |sendStkMenuSelection| must be executed one by one with
+  // |verifyWithPeekedStkEnvelope| introduced here.
+  return Promise.resolve()
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_USER_ACTIVITY
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "07" + // Length
+      "990104" + // TAG_EVENT_LIST (STK_EVENT_TYPE_USER_ACTIVITY)
+      "82028281" // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "07" + // Length
+      "990105" + // TAG_EVENT_LIST (STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE)
+      "82020281" // TAG_DEVICE_ID (STK_DEVICE_ID_DISPLAY, STK_DEVICE_ID_SIM)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_LOCATION_STATUS,
+      locationStatus: MozIccManager.STK_SERVICE_STATE_NORMAL,
+      locationInfo: {
+        mcc: "466",
+        mnc: "92",
+        gsmLocationAreaCode: 10291,
+        gsmCellId: 19072823
+      }
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "15" + // Length
+      "990103" + // TAG_EVENT_LIST (STK_EVENT_TYPE_LOCATION_STATUS)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "9B0100" + // TAG_LOCATION_STATUS (STK_SERVICE_STATE_NORMAL)
+      "930964F629283301230737" // TAG_LOCATION_INFO (mccmnc = 46692, lac = 10291, cellId = 19072823)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_LOCATION_STATUS,
+      locationStatus: MozIccManager.STK_SERVICE_STATE_LIMITED,
+      // locationInfo shall be ignored if locationStatus != STK_SERVICE_STATE_NORMAL
+      locationInfo: {
+        mcc: "466",
+        mnc: "92",
+        gsmLocationAreaCode: 10291,
+        gsmCellId: 19072823
+      }
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990103" + // TAG_EVENT_LIST (STK_EVENT_TYPE_LOCATION_STATUS)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "9B0101" // TAG_LOCATION_STATUS (STK_SERVICE_STATE_LIMITED)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_LOCATION_STATUS,
+      locationStatus: MozIccManager.STK_SERVICE_STATE_UNAVAILABLE,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990103" + // TAG_EVENT_LIST (STK_EVENT_TYPE_LOCATION_STATUS)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "9B0102" // TAG_LOCATION_STATUS (STK_SERVICE_STATE_UNAVAILABLE)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_MT_CALL,
+      number: "+9876543210", // International number
+      isIssuedByRemote: true,
+      error: null
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "12" + // Length
+      "990100" + // TAG_EVENT_LIST (STK_EVENT_TYPE_MT_CALL)
+      "82028381" + // TAG_DEVICE_ID (STK_DEVICE_ID_NETWORK, STK_DEVICE_ID_SIM)
+      "9C0100" + // TAG_TRANSACTION_ID (transactionId always set to 0)
+      "8606918967452301" // TAG_ADDRESS (+9876543210)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_MT_CALL,
+      number: "987654321", // National number
+      isIssuedByRemote: true,
+      error: null
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "12" + // Length
+      "990100" + // TAG_EVENT_LIST (STK_EVENT_TYPE_MT_CALL)
+      "82028381" + // TAG_DEVICE_ID (STK_DEVICE_ID_NETWORK, STK_DEVICE_ID_SIM)
+      "9C0100" + // TAG_TRANSACTION_ID (transactionId always set to 0)
+      "86068189674523F1" // TAG_ADDRESS (987654321)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_CALL_CONNECTED,
+      isIssuedByRemote: true,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990101" + // TAG_EVENT_LIST (STK_EVENT_TYPE_CALL_CONNECTED)
+      "82028381" + // TAG_DEVICE_ID (STK_DEVICE_ID_NETWORK, STK_DEVICE_ID_SIM)
+      "9C0100" // TAG_TRANSACTION_ID (transactionId always set to 0)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_CALL_CONNECTED,
+      isIssuedByRemote: false,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990101" + // TAG_EVENT_LIST (STK_EVENT_TYPE_CALL_CONNECTED)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "9C0100" // TAG_TRANSACTION_ID (transactionId always set to 0)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED,
+      isIssuedByRemote: false,
+      error: "BusyError"
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0E" + // Length
+      "990102" + // TAG_EVENT_LIST (STK_EVENT_TYPE_CALL_DISCONNECTED)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "9C0100" + // TAG_TRANSACTION_ID (transactionId always set to 0)
+      "9A026091" // TAG_CAUSE (Busy)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_CALL_DISCONNECTED,
+      isIssuedByRemote: true,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990102" + // TAG_EVENT_LIST (STK_EVENT_TYPE_CALL_DISCONNECTED)
+      "82028381" + // TAG_DEVICE_ID (STK_DEVICE_ID_NETWORK, STK_DEVICE_ID_SIM)
+      "9C0100" // TAG_TRANSACTION_ID (transactionId always set to 0)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_LANGUAGE_SELECTION,
+      language: "zh",
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0B" + // Length
+      "990107" + // TAG_EVENT_LIST (STK_EVENT_TYPE_LANGUAGE_SELECTION)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "2D027A68" // TAG_LANGUAGE ("zh")
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_BROWSER_TERMINATION,
+      terminationCause: MozIccManager.STK_BROWSER_TERMINATION_CAUSE_USER,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990108" + // TAG_EVENT_LIST (STK_EVENT_TYPE_BROWSER_TERMINATION)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "B40100" // TAG_BROWSER_TERMINATION_CAUSE (USER)
+    ))
+
+    .then(() => icc.sendStkEventDownload({
+      eventType: MozIccManager.STK_EVENT_TYPE_BROWSER_TERMINATION,
+      terminationCause: MozIccManager.STK_BROWSER_TERMINATION_CAUSE_ERROR,
+    }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D6" + // BER_EVENT_DOWNLOAD_TAG
+      "0A" + // Length
+      "990108" + // TAG_EVENT_LIST (STK_EVENT_TYPE_BROWSER_TERMINATION)
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "B40101" // TAG_BROWSER_TERMINATION_CAUSE (ERROR)
+    ));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_stk_menu_selection.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+MARIONETTE_HEAD_JS = "head.js";
+
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // APDU format of ENVELOPE:
+  // Class = 'A0', INS = 'C2', P1 = '00', P2 = '00', XXXX, (No Le)
+
+  // Since |sendStkMenuSelection| is an API without call back to identify the
+  // result, the tests of |sendStkMenuSelection| must be executed one by one with
+  // |verifyWithPeekedStkEnvelope| introduced here.
+  return Promise.resolve()
+    .then(() => icc.sendStkMenuSelection(1, true))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D3" + // BER_MENU_SELECTION_TAG
+      "09" + // Length
+      "82020181" + // TAG_DEVICE_ID (STK_DEVICE_ID_KEYPAD, STK_DEVICE_ID_SIM)
+      "900101" + // TAG_ITEM_ID (Item (1))
+      "9500" // TAG_HELP_REQUEST
+    ))
+
+    .then(() => icc.sendStkMenuSelection(0, false))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D3" + // BER_MENU_SELECTION_TAG
+      "07" + // Length
+      "82020181" + // TAG_DEVICE_ID (STK_DEVICE_ID_KEYPAD, STK_DEVICE_ID_SIM)
+      "900100" // TAG_ITEM_ID (Item (0))
+    ));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_stk_response.js
@@ -0,0 +1,288 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 120000;
+MARIONETTE_HEAD_JS = "head.js";
+
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // APDU format of TERMINAL RESPONSE:
+  // Class = 'A0', INS = '14', P1 = '00', P2 = '00', XXXX, (No Le)
+
+  // Since |sendStkResponse| is an API without call back to identify the
+  // result, the tests of |sendStkResponse| must be executed one by one with
+  // |verifyWithPeekedStkResponse| introduced here.
+  return Promise.resolve()
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x01,
+      typeOfCommand: MozIccManager.STK_CMD_LAUNCH_BROWSER,
+      commandQualifier: 0x00,
+      options: {
+        url: "",
+        mode: MozIccManager.STK_BROWSER_MODE_LAUNCH_IF_NOT_ALREADY_LAUNCHED
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103011500" + // TAG_COMMAND_DETAILS (STK_CMD_LAUNCH_BROWSER)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100"  // TAG_RESULT (STK_RESULT_OK)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x02,
+      typeOfCommand: MozIccManager.STK_CMD_DISPLAY_TEXT,
+      commandQualifier: 0x01,
+      options: {
+        text: "Toolkit Test 1",
+        responseNeeded: false
+      }
+    }, {
+      resultCode:
+        MozIccManager.STK_RESULT_TERMINAL_CRNTLY_UNABLE_TO_PROCESS,
+      additionalInformation:
+        MozIccManager.STK_ADDITIONAL_INFO_ME_PROBLEM_SCREEN_IS_BUSY
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103022101" + // TAG_COMMAND_DETAILS (STK_CMD_DISPLAY_TEXT)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "83022001"  // TAG_RESULT (STK_ADDITIONAL_INFO_ME_PROBLEM_SCREEN_IS_BUSY)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x03,
+      typeOfCommand: MozIccManager.STK_CMD_SELECT_ITEM,
+      commandQualifier: 0x00,
+      options: {
+        title: "Toolkit Select",
+        items: [{identifier: 1, text: "Item 1"},
+                {identifier: 2, text: "Item 2"},
+                {identifier: 3, text: "Item 3"},
+                {identifier: 4, text: "Item 4"}]
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_HELP_INFO_REQUIRED,
+      itemIdentifier: 5
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103032400" + // TAG_COMMAND_DETAILS (STK_CMD_SELECT_ITEM)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830113" + // TAG_RESULT (STK_RESULT_HELP_INFO_REQUIRED)
+      "900105" // TAG_ITEM_ID (5)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x04,
+      typeOfCommand: MozIccManager.STK_CMD_GET_INKEY,
+      commandQualifier: 0x04,
+      options: {
+        text: "Enter Y/N"
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      isYesNo: true
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103042204" + // TAG_COMMAND_DETAILS (STK_CMD_GET_INKEY)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "8D020401" // TAG_TEXT_STRING (STK_TEXT_CODING_GSM_8BIT, YES)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x05,
+      typeOfCommand: MozIccManager.STK_CMD_GET_INKEY,
+      commandQualifier: 0x04,
+      options: {
+        text: "Enter Y/N",
+        duration: {
+          timeUnit: MozIccManager.STK_TIME_UNIT_SECOND,
+          timeInterval: 10
+        }
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_NO_RESPONSE_FROM_USER,
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103052204" + // TAG_COMMAND_DETAILS (STK_CMD_GET_INKEY)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830112" + // TAG_RESULT (STK_RESULT_NO_RESPONSE_FROM_USER)
+      "0402010A" // TAG_DURATION (10 seconds)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x06,
+      typeOfCommand: MozIccManager.STK_CMD_GET_INPUT,
+      commandQualifier: 0x01,
+      options: {
+        text: "Enter Yes"
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      input: "Yes"
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103062301" + // TAG_COMMAND_DETAILS (STK_CMD_GET_INPUT)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "8D0404596573" // TAG_TEXT_STRING (STK_TEXT_CODING_GSM_8BIT, "Yes")
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x07,
+      typeOfCommand: MozIccManager.STK_CMD_TIMER_MANAGEMENT,
+      commandQualifier: MozIccManager.STK_TIMER_START,
+      options: {
+        timerAction: MozIccManager.STK_TIMER_START,
+        timerId: 0x01,
+        timerValue: (0x01 * 60 * 60) + (0x02 * 60) + 0x03 // 01:02:03
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      timer: {
+        timerAction: MozIccManager.STK_TIMER_START,
+        timerId: 0x01,
+        timerValue: (0x01 * 60 * 60) + (0x02 * 60) + 0x03 // 01:02:03
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103072700" + // TAG_COMMAND_DETAILS (STK_CMD_TIMER_MANAGEMENT)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "240101" + // TIMER_IDENTIFIER (TIMER ID = 1)
+      "2503102030" // TAG_TIMER_VALUE
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x08,
+      typeOfCommand: MozIccManager.STK_CMD_TIMER_MANAGEMENT,
+      commandQualifier: MozIccManager.STK_TIMER_DEACTIVATE,
+      options: {
+        timerAction: MozIccManager.STK_TIMER_DEACTIVATE,
+        timerId: 0x02,
+        timerValue: (0x01 * 60 * 60) + (0x02 * 60) + 0x03 // 01:02:03
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      timer: {
+        timerId: 0x02
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103082701" + // TAG_COMMAND_DETAILS (STK_CMD_TIMER_MANAGEMENT)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "240102" // TIMER_IDENTIFIER (TIMER ID = 2)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x09,
+      typeOfCommand: MozIccManager.STK_CMD_TIMER_MANAGEMENT,
+      commandQualifier: MozIccManager.STK_TIMER_GET_CURRENT_VALUE,
+      options: {
+        timerAction: MozIccManager.STK_TIMER_GET_CURRENT_VALUE,
+        timerId: 0x03,
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_ACTION_CONTRADICTION_TIMER_STATE,
+      timer: {
+        timerId: 0x03
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "8103092702" + // TAG_COMMAND_DETAILS (STK_CMD_TIMER_MANAGEMENT)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830124" + // TAG_RESULT (STK_RESULT_ACTION_CONTRADICTION_TIMER_STATE)
+      "240103" // TIMER_IDENTIFIER (TIMER ID = 3)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x0A,
+      typeOfCommand: MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO,
+      commandQualifier: MozIccManager.STK_LOCAL_INFO_LOCATION_INFO,
+      options: {
+        localInfoType: MozIccManager.STK_LOCAL_INFO_LOCATION_INFO
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      localInfo: {
+        locationInfo: {
+          mcc: "466",
+          mnc: "92",
+          gsmLocationAreaCode: 10291,
+          gsmCellId: 19072823
+        }
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "81030A2600" + // TAG_COMMAND_DETAILS (STK_CMD_PROVIDE_LOCAL_INFO)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "930964F629283301230737" // TAG_LOCATION_INFO (mccmnc = 46692, lac = 10291, cellId = 19072823)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x0B,
+      typeOfCommand: MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO,
+      commandQualifier: MozIccManager.STK_LOCAL_INFO_IMEI,
+      options: {
+        localInfoType: MozIccManager.STK_LOCAL_INFO_IMEI
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      localInfo: {
+        imei: "123456789012345"
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "81030B2601" + // TAG_COMMAND_DETAILS (STK_CMD_PROVIDE_LOCAL_INFO)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "14081234567890123450" // TAG_IMEI ("123456789012345")
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x0C,
+      typeOfCommand: MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO,
+      commandQualifier: MozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE,
+      options: {
+        localInfoType: MozIccManager.STK_LOCAL_INFO_DATE_TIME_ZONE
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      localInfo: {
+        // 2012, 3/4, 5:06:07 (Month is zero-based)
+        date: new Date(Date.UTC(2012, 2, 4, 5, 6, 7))
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "81030C2603" + // TAG_COMMAND_DETAILS (STK_CMD_PROVIDE_LOCAL_INFO)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "260721304050607000" // TAG_DATE_TIME_ZONE ("2012, 3/4, 5:06:07" in UTC)
+    ))
+
+    .then(() => icc.sendStkResponse({
+      commandNumber: 0x0D,
+      typeOfCommand: MozIccManager.STK_CMD_PROVIDE_LOCAL_INFO,
+      commandQualifier: MozIccManager.STK_LOCAL_INFO_LANGUAGE,
+      options: {
+        localInfoType: MozIccManager.STK_LOCAL_INFO_LANGUAGE
+      }
+    }, {
+      resultCode: MozIccManager.STK_RESULT_OK,
+      localInfo: {
+        language: "zh"
+      },
+    }))
+    .then(() => verifyWithPeekedStkResponse(
+      "81030D2604" + // TAG_COMMAND_DETAILS (STK_CMD_PROVIDE_LOCAL_INFO)
+      "02028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "830100" + // TAG_RESULT (STK_RESULT_OK)
+      "2D027A68" // TAG_LANGUAGE ("zh")
+    ));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/tests/marionette/test_stk_timer_expiration.js
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+MARIONETTE_HEAD_JS = "head.js";
+
+
+// Start tests
+startTestCommon(function() {
+  let icc = getMozIcc();
+
+  // APDU format of ENVELOPE:
+  // Class = 'A0', INS = 'C2', P1 = '00', P2 = '00', XXXX, (No Le)
+
+  // Since |sendStkTimerExpiration| is an API without call back to identify the
+  // result, the tests of |sendStkMenuSelection| must be executed one by one with
+  // |verifyWithPeekedStkEnvelope| introduced here.
+  return Promise.resolve()
+    .then(() => icc.sendStkTimerExpiration({ timerId: 5, timerValue: 1234567 / 1000 }))
+    .then(() => verifyWithPeekedStkEnvelope(
+      "D7" + // BER_TIMER_EXPIRATION_TAG
+      "0C" + // Length
+      "82028281" + // TAG_DEVICE_ID (STK_DEVICE_ID_ME, STK_DEVICE_ID_SIM)
+      "A40105" + // TAG_TIMER_IDENTIFIER (5)
+      "A503000243" // TIMER_VALUE (00:20:34) = 1234 seconds
+    ));
+});
\ No newline at end of file