dom/system/gonk/tests/test_ril_worker_icc.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/system/gonk/tests/test_ril_worker_icc.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3187 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 +   http://creativecommons.org/publicdomain/zero/1.0/ */
     1.6 +
     1.7 +subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
     1.8 +
     1.9 +function run_test() {
    1.10 +  run_next_test();
    1.11 +}
    1.12 +
    1.13 +/**
    1.14 + * Helper function.
    1.15 + */
    1.16 +function newUint8Worker() {
    1.17 +  let worker = newWorker();
    1.18 +  let index = 0; // index for read
    1.19 +  let buf = [];
    1.20 +
    1.21 +  let context = worker.ContextPool._contexts[0];
    1.22 +  context.Buf.writeUint8 = function(value) {
    1.23 +    buf.push(value);
    1.24 +  };
    1.25 +
    1.26 +  context.Buf.readUint8 = function() {
    1.27 +    return buf[index++];
    1.28 +  };
    1.29 +
    1.30 +  context.Buf.seekIncoming = function(offset) {
    1.31 +    index += offset;
    1.32 +  };
    1.33 +
    1.34 +  context.Buf.getReadAvailable = function() {
    1.35 +    return buf.length - index;
    1.36 +  };
    1.37 +
    1.38 +  worker.debug = do_print;
    1.39 +
    1.40 +  return worker;
    1.41 +}
    1.42 +
    1.43 +/**
    1.44 + * Verify ICCPDUHelper#readICCUCS2String()
    1.45 + */
    1.46 +add_test(function test_read_icc_ucs2_string() {
    1.47 +  let worker = newUint8Worker();
    1.48 +  let context = worker.ContextPool._contexts[0];
    1.49 +  let helper = context.GsmPDUHelper;
    1.50 +  let iccHelper = context.ICCPDUHelper;
    1.51 +
    1.52 +  // 0x80
    1.53 +  let text = "TEST";
    1.54 +  helper.writeUCS2String(text);
    1.55 +  // Also write two unused octets.
    1.56 +  let ffLen = 2;
    1.57 +  for (let i = 0; i < ffLen; i++) {
    1.58 +    helper.writeHexOctet(0xff);
    1.59 +  }
    1.60 +  do_check_eq(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
    1.61 +
    1.62 +  // 0x81
    1.63 +  let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
    1.64 +               0xff, 0xff];
    1.65 +  let len = array.length;
    1.66 +  for (let i = 0; i < len; i++) {
    1.67 +    helper.writeHexOctet(array[i]);
    1.68 +  }
    1.69 +  do_check_eq(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
    1.70 +
    1.71 +  // 0x82
    1.72 +  let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
    1.73 +                0xca, 0xff, 0xff];
    1.74 +  let len2 = array2.length;
    1.75 +  for (let i = 0; i < len2; i++) {
    1.76 +    helper.writeHexOctet(array2[i]);
    1.77 +  }
    1.78 +  do_check_eq(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
    1.79 +
    1.80 +  run_next_test();
    1.81 +});
    1.82 +
    1.83 +/**
    1.84 + * Verify ICCPDUHelper#readDiallingNumber
    1.85 + */
    1.86 +add_test(function test_read_dialling_number() {
    1.87 +  let worker = newUint8Worker();
    1.88 +  let context = worker.ContextPool._contexts[0];
    1.89 +  let helper = context.GsmPDUHelper;
    1.90 +  let iccHelper = context.ICCPDUHelper;
    1.91 +  let str = "123456789";
    1.92 +
    1.93 +  helper.readHexOctet = function() {
    1.94 +    return 0x81;
    1.95 +  };
    1.96 +
    1.97 +  helper.readSwappedNibbleBcdString = function(len) {
    1.98 +    return str.substring(0, len);
    1.99 +  };
   1.100 +
   1.101 +  for (let i = 0; i < str.length; i++) {
   1.102 +    do_check_eq(str.substring(0, i - 1), // -1 for the TON
   1.103 +                iccHelper.readDiallingNumber(i));
   1.104 +  }
   1.105 +
   1.106 +  run_next_test();
   1.107 +});
   1.108 +
   1.109 +/**
   1.110 + * Verify ICCPDUHelper#read8BitUnpackedToString
   1.111 + */
   1.112 +add_test(function test_read_8bit_unpacked_to_string() {
   1.113 +  let worker = newUint8Worker();
   1.114 +  let context = worker.ContextPool._contexts[0];
   1.115 +  let helper = context.GsmPDUHelper;
   1.116 +  let iccHelper = context.ICCPDUHelper;
   1.117 +  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.118 +  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.119 +
   1.120 +  // Test 1: Read GSM alphabets.
   1.121 +  // Write alphabets before ESCAPE.
   1.122 +  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
   1.123 +    helper.writeHexOctet(i);
   1.124 +  }
   1.125 +
   1.126 +  // Write two ESCAPEs to make it become ' '.
   1.127 +  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
   1.128 +  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
   1.129 +
   1.130 +  for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
   1.131 +    helper.writeHexOctet(i);
   1.132 +  }
   1.133 +
   1.134 +  // Also write two unused fields.
   1.135 +  let ffLen = 2;
   1.136 +  for (let i = 0; i < ffLen; i++) {
   1.137 +    helper.writeHexOctet(0xff);
   1.138 +  }
   1.139 +
   1.140 +  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
   1.141 +              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
   1.142 +  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
   1.143 +  do_check_eq(iccHelper.read8BitUnpackedToString(langTable.length -
   1.144 +                                              PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
   1.145 +              langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
   1.146 +
   1.147 +  // Test 2: Read GSM extended alphabets.
   1.148 +  for (let i = 0; i < langShiftTable.length; i++) {
   1.149 +    helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
   1.150 +    helper.writeHexOctet(i);
   1.151 +  }
   1.152 +
   1.153 +  // Read string before RESERVED_CONTROL.
   1.154 +  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL  * 2),
   1.155 +              langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
   1.156 +  // ESCAPE + RESERVED_CONTROL will become ' '.
   1.157 +  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
   1.158 +  // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
   1.159 +  do_check_eq(iccHelper.read8BitUnpackedToString(
   1.160 +                (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1)  * 2),
   1.161 +              langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
   1.162 +                                       PDU_NL_EXTENDED_ESCAPE));
   1.163 +  // ESCAPE + ESCAPE will become ' '.
   1.164 +  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
   1.165 +  // Read remaining string.
   1.166 +  do_check_eq(iccHelper.read8BitUnpackedToString(
   1.167 +                (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1)  * 2),
   1.168 +              langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
   1.169 +
   1.170 +  run_next_test();
   1.171 +});
   1.172 +
   1.173 +/**
   1.174 + * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
   1.175 + *
   1.176 + * Test writing GSM 8 bit alphabets.
   1.177 + */
   1.178 +add_test(function test_write_string_to_8bit_unpacked() {
   1.179 +  let worker = newUint8Worker();
   1.180 +  let context = worker.ContextPool._contexts[0];
   1.181 +  let helper = context.GsmPDUHelper;
   1.182 +  let iccHelper = context.ICCPDUHelper;
   1.183 +  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.184 +  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.185 +  // Length of trailing 0xff.
   1.186 +  let ffLen = 2;
   1.187 +  let str;
   1.188 +
   1.189 +  // Test 1, write GSM alphabets.
   1.190 +  iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
   1.191 +
   1.192 +  for (let i = 0; i < langTable.length; i++) {
   1.193 +    do_check_eq(helper.readHexOctet(), i);
   1.194 +  }
   1.195 +
   1.196 +  for (let i = 0; i < ffLen; i++) {
   1.197 +    do_check_eq(helper.readHexOctet(), 0xff);
   1.198 +  }
   1.199 +
   1.200 +  // Test 2, write GSM extended alphabets.
   1.201 +  str = "\u000c\u20ac";
   1.202 +  iccHelper.writeStringTo8BitUnpacked(4, str);
   1.203 +
   1.204 +  do_check_eq(iccHelper.read8BitUnpackedToString(4), str);
   1.205 +
   1.206 +  // Test 3, write GSM and GSM extended alphabets.
   1.207 +  // \u000c, \u20ac are from gsm extended alphabets.
   1.208 +  // \u00a3 is from gsm alphabet.
   1.209 +  str = "\u000c\u20ac\u00a3";
   1.210 +
   1.211 +  // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
   1.212 +  // 1 octet for 1 gsm alphabet,
   1.213 +  // 2 octes for trailing 0xff.
   1.214 +  // "Totally 7 octets are to be written."
   1.215 +  iccHelper.writeStringTo8BitUnpacked(7, str);
   1.216 +
   1.217 +  do_check_eq(iccHelper.read8BitUnpackedToString(7), str);
   1.218 +
   1.219 +  run_next_test();
   1.220 +});
   1.221 +
   1.222 +/**
   1.223 + * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
   1.224 + */
   1.225 +add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
   1.226 +  let worker = newUint8Worker();
   1.227 +  let context = worker.ContextPool._contexts[0];
   1.228 +  let helper = context.GsmPDUHelper;
   1.229 +  let iccHelper = context.ICCPDUHelper;
   1.230 +  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.231 +  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.232 +
   1.233 +  // The maximum of the number of octets that can be written is 3.
   1.234 +  // Only 3 characters shall be written even the length of the string is 4.
   1.235 +  iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
   1.236 +  helper.writeHexOctet(0xff); // dummy octet.
   1.237 +  for (let i = 0; i < 3; i++) {
   1.238 +    do_check_eq(helper.readHexOctet(), i);
   1.239 +  }
   1.240 +  do_check_false(helper.readHexOctet() == 4);
   1.241 +
   1.242 +  // \u000c is GSM extended alphabet, 2 octets.
   1.243 +  // \u00a3 is GSM alphabet, 1 octet.
   1.244 +  let str = "\u000c\u00a3";
   1.245 +  iccHelper.writeStringTo8BitUnpacked(3, str);
   1.246 +  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
   1.247 +
   1.248 +  str = "\u00a3\u000c";
   1.249 +  iccHelper.writeStringTo8BitUnpacked(3, str);
   1.250 +  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
   1.251 +
   1.252 +  // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
   1.253 +  // alphabet can be written.
   1.254 +  str = "\u000c\u000c";
   1.255 +  iccHelper.writeStringTo8BitUnpacked(3, str);
   1.256 +  helper.writeHexOctet(0xff); // dummy octet.
   1.257 +  do_check_eq(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
   1.258 +
   1.259 +  run_next_test();
   1.260 +});
   1.261 +
   1.262 +/**
   1.263 + * Verify ICCPDUHelper.readAlphaIdentifier
   1.264 + */
   1.265 +add_test(function test_read_alpha_identifier() {
   1.266 +  let worker = newUint8Worker();
   1.267 +  let context = worker.ContextPool._contexts[0];
   1.268 +  let helper = context.GsmPDUHelper;
   1.269 +  let iccHelper = context.ICCPDUHelper;
   1.270 +
   1.271 +  // UCS2: 0x80
   1.272 +  let text = "TEST";
   1.273 +  helper.writeHexOctet(0x80);
   1.274 +  helper.writeUCS2String(text);
   1.275 +  // Also write two unused octets.
   1.276 +  let ffLen = 2;
   1.277 +  for (let i = 0; i < ffLen; i++) {
   1.278 +    helper.writeHexOctet(0xff);
   1.279 +  }
   1.280 +  do_check_eq(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
   1.281 +
   1.282 +  // UCS2: 0x81
   1.283 +  let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
   1.284 +  for (let i = 0; i < array.length; i++) {
   1.285 +    helper.writeHexOctet(array[i]);
   1.286 +  }
   1.287 +  do_check_eq(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
   1.288 +
   1.289 +  // UCS2: 0x82
   1.290 +  let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
   1.291 +  for (let i = 0; i < array2.length; i++) {
   1.292 +    helper.writeHexOctet(array2[i]);
   1.293 +  }
   1.294 +  do_check_eq(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
   1.295 +
   1.296 +  // GSM 8 Bit Unpacked
   1.297 +  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.298 +  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
   1.299 +    helper.writeHexOctet(i);
   1.300 +  }
   1.301 +  do_check_eq(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
   1.302 +              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
   1.303 +
   1.304 +  run_next_test();
   1.305 +});
   1.306 +
   1.307 +/**
   1.308 + * Verify ICCPDUHelper.writeAlphaIdentifier
   1.309 + */
   1.310 +add_test(function test_write_alpha_identifier() {
   1.311 +  let worker = newUint8Worker();
   1.312 +  let context = worker.ContextPool._contexts[0];
   1.313 +  let helper = context.GsmPDUHelper;
   1.314 +  let iccHelper = context.ICCPDUHelper;
   1.315 +  // Length of trailing 0xff.
   1.316 +  let ffLen = 2;
   1.317 +
   1.318 +  // Removal
   1.319 +  iccHelper.writeAlphaIdentifier(10, null);
   1.320 +  do_check_eq(iccHelper.readAlphaIdentifier(10), "");
   1.321 +
   1.322 +  // GSM 8 bit
   1.323 +  let str = "Mozilla";
   1.324 +  iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
   1.325 +  do_check_eq(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
   1.326 +
   1.327 +  // UCS2
   1.328 +  str = "Mozilla\u694a";
   1.329 +  iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
   1.330 +  // * 2 for each character will be encoded to UCS2 alphabets.
   1.331 +  do_check_eq(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
   1.332 +
   1.333 +  // Test with maximum octets written.
   1.334 +  // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
   1.335 +  str = "\u694a";
   1.336 +  iccHelper.writeAlphaIdentifier(3, str);
   1.337 +  do_check_eq(iccHelper.readAlphaIdentifier(3), str);
   1.338 +
   1.339 +  // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
   1.340 +  // numOctets is limited to 4, so only 1 UCS2 character can be written.
   1.341 +  str = "\u694a\u694a";
   1.342 +  iccHelper.writeAlphaIdentifier(4, str);
   1.343 +  helper.writeHexOctet(0xff); // dummy octet.
   1.344 +  do_check_eq(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
   1.345 +
   1.346 +  // Write 0 octet.
   1.347 +  iccHelper.writeAlphaIdentifier(0, "1");
   1.348 +  helper.writeHexOctet(0xff); // dummy octet.
   1.349 +  do_check_eq(iccHelper.readAlphaIdentifier(1), "");
   1.350 +
   1.351 +  run_next_test();
   1.352 +});
   1.353 +
   1.354 +/**
   1.355 + * Verify ICCPDUHelper.readAlphaIdDiallingNumber
   1.356 + */
   1.357 +add_test(function test_read_alpha_id_dialling_number() {
   1.358 +  let worker = newUint8Worker();
   1.359 +  let context = worker.ContextPool._contexts[0];
   1.360 +  let helper = context.GsmPDUHelper;
   1.361 +  let iccHelper = context.ICCPDUHelper;
   1.362 +  let buf = context.Buf;
   1.363 +  const recordSize = 32;
   1.364 +
   1.365 +  function testReadAlphaIdDiallingNumber(contact) {
   1.366 +    iccHelper.readAlphaIdentifier = function() {
   1.367 +      return contact.alphaId;
   1.368 +    };
   1.369 +
   1.370 +    iccHelper.readNumberWithLength = function() {
   1.371 +      return contact.number;
   1.372 +    };
   1.373 +
   1.374 +    let strLen = recordSize * 2;
   1.375 +    buf.writeInt32(strLen);     // fake length
   1.376 +    helper.writeHexOctet(0xff); // fake CCP
   1.377 +    helper.writeHexOctet(0xff); // fake EXT1
   1.378 +    buf.writeStringDelimiter(strLen);
   1.379 +
   1.380 +    let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
   1.381 +    if (contact.alphaId == "" && contact.number == "") {
   1.382 +      do_check_eq(contactR, null);
   1.383 +    } else {
   1.384 +      do_check_eq(contactR.alphaId, contact.alphaId);
   1.385 +      do_check_eq(contactR.number, contact.number);
   1.386 +    }
   1.387 +  }
   1.388 +
   1.389 +  testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
   1.390 +  testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
   1.391 +
   1.392 +  run_next_test();
   1.393 +});
   1.394 +
   1.395 +/**
   1.396 + * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
   1.397 + */
   1.398 +add_test(function test_write_alpha_id_dialling_number() {
   1.399 +  let worker = newUint8Worker();
   1.400 +  let context = worker.ContextPool._contexts[0];
   1.401 +  let helper = context.ICCPDUHelper;
   1.402 +  const recordSize = 32;
   1.403 +
   1.404 +  // Write a normal contact.
   1.405 +  let contactW = {
   1.406 +    alphaId: "Mozilla",
   1.407 +    number: "1234567890"
   1.408 +  };
   1.409 +  helper.writeAlphaIdDiallingNumber(recordSize, contactW.alphaId,
   1.410 +                                    contactW.number);
   1.411 +
   1.412 +  let contactR = helper.readAlphaIdDiallingNumber(recordSize);
   1.413 +  do_check_eq(contactW.alphaId, contactR.alphaId);
   1.414 +  do_check_eq(contactW.number, contactR.number);
   1.415 +
   1.416 +  // Write a contact with alphaId encoded in UCS2 and number has '+'.
   1.417 +  let contactUCS2 = {
   1.418 +    alphaId: "火狐",
   1.419 +    number: "+1234567890"
   1.420 +  };
   1.421 +  helper.writeAlphaIdDiallingNumber(recordSize, contactUCS2.alphaId,
   1.422 +                                    contactUCS2.number);
   1.423 +  contactR = helper.readAlphaIdDiallingNumber(recordSize);
   1.424 +  do_check_eq(contactUCS2.alphaId, contactR.alphaId);
   1.425 +  do_check_eq(contactUCS2.number, contactR.number);
   1.426 +
   1.427 +  // Write a null contact (Removal).
   1.428 +  helper.writeAlphaIdDiallingNumber(recordSize);
   1.429 +  contactR = helper.readAlphaIdDiallingNumber(recordSize);
   1.430 +  do_check_eq(contactR, null);
   1.431 +
   1.432 +  // Write a longer alphaId/dialling number
   1.433 +  // Dialling Number : Maximum 20 digits(10 octets).
   1.434 +  // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
   1.435 +  //                   octet for TON/NPI, 1 for number length octet, and 2 for
   1.436 +  //                   Ext) = Maximum 18 octets.
   1.437 +  let longContact = {
   1.438 +    alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
   1.439 +    number: "123456789012345678901234567890",
   1.440 +  };
   1.441 +  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
   1.442 +                                    longContact.number);
   1.443 +  contactR = helper.readAlphaIdDiallingNumber(recordSize);
   1.444 +  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
   1.445 +  do_check_eq(contactR.number, "12345678901234567890");
   1.446 +
   1.447 +  // Add '+' to number and test again.
   1.448 +  longContact.number = "+123456789012345678901234567890";
   1.449 +  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
   1.450 +                                    longContact.number);
   1.451 +  contactR = helper.readAlphaIdDiallingNumber(recordSize);
   1.452 +  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
   1.453 +  do_check_eq(contactR.number, "+12345678901234567890");
   1.454 +
   1.455 +  run_next_test();
   1.456 +});
   1.457 +
   1.458 +/**
   1.459 + * Verify ICCPDUHelper.writeDiallingNumber
   1.460 + */
   1.461 +add_test(function test_write_dialling_number() {
   1.462 +  let worker = newUint8Worker();
   1.463 +  let context = worker.ContextPool._contexts[0];
   1.464 +  let helper = context.ICCPDUHelper;
   1.465 +
   1.466 +  // with +
   1.467 +  let number = "+123456";
   1.468 +  let len = 4;
   1.469 +  helper.writeDiallingNumber(number);
   1.470 +  do_check_eq(helper.readDiallingNumber(len), number);
   1.471 +
   1.472 +  // without +
   1.473 +  number = "987654";
   1.474 +  len = 4;
   1.475 +  helper.writeDiallingNumber(number);
   1.476 +  do_check_eq(helper.readDiallingNumber(len), number);
   1.477 +
   1.478 +  number = "9876543";
   1.479 +  len = 5;
   1.480 +  helper.writeDiallingNumber(number);
   1.481 +  do_check_eq(helper.readDiallingNumber(len), number);
   1.482 +
   1.483 +  run_next_test();
   1.484 +});
   1.485 +
   1.486 +/**
   1.487 + * Verify ICCPDUHelper.readNumberWithLength
   1.488 + */
   1.489 +add_test(function test_read_number_with_length() {
   1.490 +  let worker = newUint8Worker();
   1.491 +  let context = worker.ContextPool._contexts[0];
   1.492 +  let helper = context.GsmPDUHelper;
   1.493 +  let iccHelper = context.ICCPDUHelper;
   1.494 +  let number = "123456789";
   1.495 +
   1.496 +  iccHelper.readDiallingNumber = function(numLen) {
   1.497 +    return number.substring(0, numLen);
   1.498 +  };
   1.499 +
   1.500 +  helper.writeHexOctet(number.length + 1);
   1.501 +  helper.writeHexOctet(PDU_TOA_ISDN);
   1.502 +  do_check_eq(iccHelper.readNumberWithLength(), number);
   1.503 +
   1.504 +  helper.writeHexOctet(0xff);
   1.505 +  do_check_eq(iccHelper.readNumberWithLength(), null);
   1.506 +
   1.507 +  run_next_test();
   1.508 +});
   1.509 +
   1.510 +/**
   1.511 + * Verify ICCPDUHelper.writeNumberWithLength
   1.512 + */
   1.513 +add_test(function test_write_number_with_length() {
   1.514 +  let worker = newUint8Worker();
   1.515 +  let context = worker.ContextPool._contexts[0];
   1.516 +  let helper = context.GsmPDUHelper;
   1.517 +  let iccHelper = context.ICCPDUHelper;
   1.518 +
   1.519 +  function test(number, expectedNumber) {
   1.520 +    expectedNumber = expectedNumber || number;
   1.521 +    iccHelper.writeNumberWithLength(number);
   1.522 +    let numLen = helper.readHexOctet();
   1.523 +    do_check_eq(expectedNumber, iccHelper.readDiallingNumber(numLen));
   1.524 +    for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
   1.525 +      do_check_eq(0xff, helper.readHexOctet());
   1.526 +    }
   1.527 +  }
   1.528 +
   1.529 +  // without +
   1.530 +  test("123456789");
   1.531 +
   1.532 +  // with +
   1.533 +  test("+987654321");
   1.534 +
   1.535 +  // extended BCD coding
   1.536 +  test("1*2#3,4*5#6,");
   1.537 +
   1.538 +  // with + and extended BCD coding
   1.539 +  test("+1*2#3,4*5#6,");
   1.540 +
   1.541 +  // non-supported characters should not be written.
   1.542 +  test("(1)23-456+789", "123456789");
   1.543 +
   1.544 +  test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
   1.545 +
   1.546 +  // null
   1.547 +  iccHelper.writeNumberWithLength(null);
   1.548 +  for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
   1.549 +    do_check_eq(0xff, helper.readHexOctet());
   1.550 +  }
   1.551 +
   1.552 +  run_next_test();
   1.553 +});
   1.554 +
   1.555 +/**
   1.556 + * Verify GsmPDUHelper.writeTimestamp
   1.557 + */
   1.558 +add_test(function test_write_timestamp() {
   1.559 +  let worker = newUint8Worker();
   1.560 +  let context = worker.ContextPool._contexts[0];
   1.561 +  let helper = context.GsmPDUHelper;
   1.562 +
   1.563 +  // current date
   1.564 +  let dateInput = new Date();
   1.565 +  let dateOutput = new Date();
   1.566 +  helper.writeTimestamp(dateInput);
   1.567 +  dateOutput.setTime(helper.readTimestamp());
   1.568 +
   1.569 +  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
   1.570 +  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
   1.571 +  do_check_eq(dateInput.getDate(), dateOutput.getDate());
   1.572 +  do_check_eq(dateInput.getHours(), dateOutput.getHours());
   1.573 +  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
   1.574 +  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
   1.575 +  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
   1.576 +
   1.577 +  // 2034-01-23 12:34:56 -0800 GMT
   1.578 +  let time = Date.UTC(2034, 1, 23, 12, 34, 56);
   1.579 +  time = time - (8 * 60 * 60 * 1000);
   1.580 +  dateInput.setTime(time);
   1.581 +  helper.writeTimestamp(dateInput);
   1.582 +  dateOutput.setTime(helper.readTimestamp());
   1.583 +
   1.584 +  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
   1.585 +  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
   1.586 +  do_check_eq(dateInput.getDate(), dateOutput.getDate());
   1.587 +  do_check_eq(dateInput.getHours(), dateOutput.getHours());
   1.588 +  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
   1.589 +  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
   1.590 +  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
   1.591 +
   1.592 +  run_next_test();
   1.593 +});
   1.594 +
   1.595 +/**
   1.596 + * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
   1.597 + */
   1.598 +add_test(function test_octect_BCD() {
   1.599 +  let worker = newUint8Worker();
   1.600 +  let context = worker.ContextPool._contexts[0];
   1.601 +  let helper = context.GsmPDUHelper;
   1.602 +
   1.603 +  // 23
   1.604 +  let number = 23;
   1.605 +  let octet = helper.BCDToOctet(number);
   1.606 +  do_check_eq(helper.octetToBCD(octet), number);
   1.607 +
   1.608 +  // 56
   1.609 +  number = 56;
   1.610 +  octet = helper.BCDToOctet(number);
   1.611 +  do_check_eq(helper.octetToBCD(octet), number);
   1.612 +
   1.613 +  // 0x23
   1.614 +  octet = 0x23;
   1.615 +  number = helper.octetToBCD(octet);
   1.616 +  do_check_eq(helper.BCDToOctet(number), octet);
   1.617 +
   1.618 +  // 0x56
   1.619 +  octet = 0x56;
   1.620 +  number = helper.octetToBCD(octet);
   1.621 +  do_check_eq(helper.BCDToOctet(number), octet);
   1.622 +
   1.623 +  run_next_test();
   1.624 +});
   1.625 +
   1.626 +/**
   1.627 + * Verify ICCUtilsHelper.isICCServiceAvailable.
   1.628 + */
   1.629 +add_test(function test_is_icc_service_available() {
   1.630 +  let worker = newUint8Worker();
   1.631 +  let context = worker.ContextPool._contexts[0];
   1.632 +  let ICCUtilsHelper = context.ICCUtilsHelper;
   1.633 +  let RIL = context.RIL;
   1.634 +
   1.635 +  function test_table(sst, geckoService, simEnabled, usimEnabled) {
   1.636 +    RIL.iccInfoPrivate.sst = sst;
   1.637 +    RIL.appType = CARD_APPTYPE_SIM;
   1.638 +    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
   1.639 +    RIL.appType = CARD_APPTYPE_USIM;
   1.640 +    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
   1.641 +  }
   1.642 +
   1.643 +  test_table([0x08], "ADN", true, false);
   1.644 +  test_table([0x08], "FDN", false, false);
   1.645 +  test_table([0x08], "SDN", false, true);
   1.646 +
   1.647 +  run_next_test();
   1.648 +});
   1.649 +
   1.650 +/**
   1.651 + * Verify ICCUtilsHelper.isGsm8BitAlphabet
   1.652 + */
   1.653 +add_test(function test_is_gsm_8bit_alphabet() {
   1.654 +  let worker = newUint8Worker();
   1.655 +  let context = worker.ContextPool._contexts[0];
   1.656 +  let ICCUtilsHelper = context.ICCUtilsHelper;
   1.657 +  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.658 +  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
   1.659 +
   1.660 +  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
   1.661 +  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
   1.662 +  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
   1.663 +
   1.664 +  run_next_test();
   1.665 +});
   1.666 +
   1.667 +/**
   1.668 + * Verify RIL.iccGetCardLockState("fdn")
   1.669 + */
   1.670 +add_test(function test_icc_get_card_lock_state_fdn() {
   1.671 +  let worker = newUint8Worker();
   1.672 +  let context = worker.ContextPool._contexts[0];
   1.673 +  let ril = context.RIL;
   1.674 +  let buf = context.Buf;
   1.675 +
   1.676 +  buf.sendParcel = function() {
   1.677 +    // Request Type.
   1.678 +    do_check_eq(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
   1.679 +
   1.680 +    // Token : we don't care.
   1.681 +    this.readInt32();
   1.682 +
   1.683 +    // String Array Length.
   1.684 +    do_check_eq(this.readInt32(), ril.v5Legacy ? 3 : 4);
   1.685 +
   1.686 +    // Facility.
   1.687 +    do_check_eq(this.readString(), ICC_CB_FACILITY_FDN);
   1.688 +
   1.689 +    // Password.
   1.690 +    do_check_eq(this.readString(), "");
   1.691 +
   1.692 +    // Service class.
   1.693 +    do_check_eq(this.readString(), (ICC_SERVICE_CLASS_VOICE |
   1.694 +                                    ICC_SERVICE_CLASS_DATA  |
   1.695 +                                    ICC_SERVICE_CLASS_FAX).toString());
   1.696 +
   1.697 +    if (!ril.v5Legacy) {
   1.698 +      // AID. Ignore because it's from modem.
   1.699 +      this.readInt32();
   1.700 +    }
   1.701 +
   1.702 +    run_next_test();
   1.703 +  };
   1.704 +
   1.705 +  ril.iccGetCardLockState({lockType: "fdn"});
   1.706 +});
   1.707 +
   1.708 +add_test(function test_get_network_name_from_icc() {
   1.709 +  let worker = newUint8Worker();
   1.710 +  let context = worker.ContextPool._contexts[0];
   1.711 +  let RIL = context.RIL;
   1.712 +  let ICCUtilsHelper = context.ICCUtilsHelper;
   1.713 +
   1.714 +  function testGetNetworkNameFromICC(operatorData, expectedResult) {
   1.715 +    let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
   1.716 +                                                      operatorData.mnc,
   1.717 +                                                      operatorData.lac);
   1.718 +
   1.719 +    if (expectedResult == null) {
   1.720 +      do_check_eq(result, expectedResult);
   1.721 +    } else {
   1.722 +      do_check_eq(result.fullName, expectedResult.longName);
   1.723 +      do_check_eq(result.shortName, expectedResult.shortName);
   1.724 +    }
   1.725 +  }
   1.726 +
   1.727 +  // Before EF_OPL and EF_PNN have been loaded.
   1.728 +  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, null);
   1.729 +  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x2000}, null);
   1.730 +
   1.731 +  // Set HPLMN
   1.732 +  RIL.iccInfo.mcc = 123;
   1.733 +  RIL.iccInfo.mnc = 456;
   1.734 +
   1.735 +  RIL.voiceRegistrationState = {
   1.736 +    cell: {
   1.737 +      gsmLocationAreaCode: 0x1000
   1.738 +    }
   1.739 +  };
   1.740 +  RIL.operator = {};
   1.741 +
   1.742 +  // Set EF_PNN
   1.743 +  RIL.iccInfoPrivate = {
   1.744 +    PNN: [
   1.745 +      {"fullName": "PNN1Long", "shortName": "PNN1Short"},
   1.746 +      {"fullName": "PNN2Long", "shortName": "PNN2Short"},
   1.747 +      {"fullName": "PNN3Long", "shortName": "PNN3Short"},
   1.748 +      {"fullName": "PNN4Long", "shortName": "PNN4Short"}
   1.749 +    ]
   1.750 +  };
   1.751 +
   1.752 +  // EF_OPL isn't available and current isn't in HPLMN,
   1.753 +  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, null);
   1.754 +
   1.755 +  // EF_OPL isn't available and current is in HPLMN,
   1.756 +  // the first record of PNN should be returned.
   1.757 +  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
   1.758 +                            {longName: "PNN1Long", shortName: "PNN1Short"});
   1.759 +
   1.760 +  // Set EF_OPL
   1.761 +  RIL.iccInfoPrivate.OPL = [
   1.762 +    {
   1.763 +      "mcc": 123,
   1.764 +      "mnc": 456,
   1.765 +      "lacTacStart": 0,
   1.766 +      "lacTacEnd": 0xFFFE,
   1.767 +      "pnnRecordId": 4
   1.768 +    },
   1.769 +    {
   1.770 +      "mcc": 321,
   1.771 +      "mnc": 654,
   1.772 +      "lacTacStart": 0,
   1.773 +      "lacTacEnd": 0x0010,
   1.774 +      "pnnRecordId": 3
   1.775 +    },
   1.776 +    {
   1.777 +      "mcc": 321,
   1.778 +      "mnc": 654,
   1.779 +      "lacTacStart": 0x0100,
   1.780 +      "lacTacEnd": 0x1010,
   1.781 +      "pnnRecordId": 2
   1.782 +    }
   1.783 +  ];
   1.784 +
   1.785 +  // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
   1.786 +  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
   1.787 +                            {longName: "PNN4Long", shortName: "PNN4Short"});
   1.788 +
   1.789 +  // Current PLMN is not HPLMN, and according to LAC, we should get
   1.790 +  // the second PNN record.
   1.791 +  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000},
   1.792 +                            {longName: "PNN2Long", shortName: "PNN2Short"});
   1.793 +
   1.794 +  // Current PLMN is not HPLMN, and according to LAC, we should get
   1.795 +  // the thrid PNN record.
   1.796 +  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x0001},
   1.797 +                            {longName: "PNN3Long", shortName: "PNN3Short"});
   1.798 +
   1.799 +  run_next_test();
   1.800 +});
   1.801 +
   1.802 +add_test(function test_path_id_for_spid_and_spn() {
   1.803 +  let worker = newWorker({
   1.804 +    postRILMessage: function(data) {
   1.805 +      // Do nothing
   1.806 +    },
   1.807 +    postMessage: function(message) {
   1.808 +      // Do nothing
   1.809 +    }});
   1.810 +  let context = worker.ContextPool._contexts[0];
   1.811 +  let RIL = context.RIL;
   1.812 +  let ICCFileHelper = context.ICCFileHelper;
   1.813 +
   1.814 +  // Test SIM
   1.815 +  RIL.appType = CARD_APPTYPE_SIM;
   1.816 +  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
   1.817 +              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
   1.818 +  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPN),
   1.819 +              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
   1.820 +
   1.821 +  // Test USIM
   1.822 +  RIL.appType = CARD_APPTYPE_USIM;
   1.823 +  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
   1.824 +              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
   1.825 +  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
   1.826 +              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
   1.827 +  run_next_test();
   1.828 +});
   1.829 +
   1.830 +/**
   1.831 + * Verify ICCUtilsHelper.parsePbrTlvs
   1.832 + */
   1.833 +add_test(function test_parse_pbr_tlvs() {
   1.834 +  let worker = newUint8Worker();
   1.835 +  let context = worker.ContextPool._contexts[0];
   1.836 +  let buf = context.Buf;
   1.837 +
   1.838 +  let pbrTlvs = [
   1.839 +    {tag: ICC_USIM_TYPE1_TAG,
   1.840 +     length: 0x0F,
   1.841 +     value: [{tag: ICC_USIM_EFADN_TAG,
   1.842 +              length: 0x03,
   1.843 +              value: [0x4F, 0x3A, 0x02]},
   1.844 +             {tag: ICC_USIM_EFIAP_TAG,
   1.845 +              length: 0x03,
   1.846 +              value: [0x4F, 0x25, 0x01]},
   1.847 +             {tag: ICC_USIM_EFPBC_TAG,
   1.848 +              length: 0x03,
   1.849 +              value: [0x4F, 0x09, 0x04]}]
   1.850 +    },
   1.851 +    {tag: ICC_USIM_TYPE2_TAG,
   1.852 +     length: 0x05,
   1.853 +     value: [{tag: ICC_USIM_EFEMAIL_TAG,
   1.854 +              length: 0x03,
   1.855 +              value: [0x4F, 0x50, 0x0B]},
   1.856 +             {tag: ICC_USIM_EFANR_TAG,
   1.857 +              length: 0x03,
   1.858 +              value: [0x4F, 0x11, 0x02]},
   1.859 +             {tag: ICC_USIM_EFANR_TAG,
   1.860 +              length: 0x03,
   1.861 +              value: [0x4F, 0x12, 0x03]}]
   1.862 +    },
   1.863 +    {tag: ICC_USIM_TYPE3_TAG,
   1.864 +     length: 0x0A,
   1.865 +     value: [{tag: ICC_USIM_EFCCP1_TAG,
   1.866 +              length: 0x03,
   1.867 +              value: [0x4F, 0x3D, 0x0A]},
   1.868 +             {tag: ICC_USIM_EFEXT1_TAG,
   1.869 +              length: 0x03,
   1.870 +              value: [0x4F, 0x4A, 0x03]}]
   1.871 +    },
   1.872 +  ];
   1.873 +
   1.874 +  let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
   1.875 +  do_check_eq(pbr.adn.fileId, 0x4F3a);
   1.876 +  do_check_eq(pbr.iap.fileId, 0x4F25);
   1.877 +  do_check_eq(pbr.pbc.fileId, 0x4F09);
   1.878 +  do_check_eq(pbr.email.fileId, 0x4F50);
   1.879 +  do_check_eq(pbr.anr0.fileId, 0x4f11);
   1.880 +  do_check_eq(pbr.anr1.fileId, 0x4f12);
   1.881 +  do_check_eq(pbr.ccp1.fileId, 0x4F3D);
   1.882 +  do_check_eq(pbr.ext1.fileId, 0x4F4A);
   1.883 +
   1.884 +  run_next_test();
   1.885 +});
   1.886 +
   1.887 +/**
   1.888 + * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
   1.889 + */
   1.890 +add_test(function test_load_linear_fixed_ef() {
   1.891 +  let worker = newUint8Worker();
   1.892 +  let context = worker.ContextPool._contexts[0];
   1.893 +  let ril = context.RIL;
   1.894 +  let io = context.ICCIOHelper;
   1.895 +
   1.896 +  io.getResponse = function fakeGetResponse(options) {
   1.897 +    // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
   1.898 +    do_check_true(false);
   1.899 +    run_next_test();
   1.900 +  };
   1.901 +
   1.902 +  ril.iccIO = function fakeIccIO(options) {
   1.903 +    do_check_true(true);
   1.904 +    run_next_test();
   1.905 +  };
   1.906 +
   1.907 +  io.loadLinearFixedEF({recordSize: 0x20});
   1.908 +});
   1.909 +
   1.910 +/**
   1.911 + * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
   1.912 + */
   1.913 +add_test(function test_load_linear_fixed_ef() {
   1.914 +  let worker = newUint8Worker();
   1.915 +  let context = worker.ContextPool._contexts[0];
   1.916 +  let ril = context.RIL;
   1.917 +  let io = context.ICCIOHelper;
   1.918 +
   1.919 +  io.getResponse = function fakeGetResponse(options) {
   1.920 +    do_check_true(true);
   1.921 +    run_next_test();
   1.922 +  };
   1.923 +
   1.924 +  ril.iccIO = function fakeIccIO(options) {
   1.925 +    // When recordSize is not provided, loadLinearFixedEF should call getResponse.
   1.926 +    do_check_true(false);
   1.927 +    run_next_test();
   1.928 +  };
   1.929 +
   1.930 +  io.loadLinearFixedEF({});
   1.931 +});
   1.932 +
   1.933 +/**
   1.934 + * Verify ICCRecordHelper.readPBR
   1.935 + */
   1.936 +add_test(function test_read_pbr() {
   1.937 +  let worker = newUint8Worker();
   1.938 +  let context = worker.ContextPool._contexts[0];
   1.939 +  let helper = context.GsmPDUHelper;
   1.940 +  let record = context.ICCRecordHelper;
   1.941 +  let buf    = context.Buf;
   1.942 +  let io     = context.ICCIOHelper;
   1.943 +
   1.944 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
   1.945 +    let pbr_1 = [
   1.946 +      0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
   1.947 +    ];
   1.948 +
   1.949 +    // Write data size
   1.950 +    buf.writeInt32(pbr_1.length * 2);
   1.951 +
   1.952 +    // Write pbr
   1.953 +    for (let i = 0; i < pbr_1.length; i++) {
   1.954 +      helper.writeHexOctet(pbr_1[i]);
   1.955 +    }
   1.956 +
   1.957 +    // Write string delimiter
   1.958 +    buf.writeStringDelimiter(pbr_1.length * 2);
   1.959 +
   1.960 +    options.totalRecords = 2;
   1.961 +    if (options.callback) {
   1.962 +      options.callback(options);
   1.963 +    }
   1.964 +  };
   1.965 +
   1.966 +  io.loadNextRecord = function fakeLoadNextRecord(options) {
   1.967 +    let pbr_2 = [
   1.968 +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff
   1.969 +    ];
   1.970 +
   1.971 +    options.p1++;
   1.972 +    if (options.callback) {
   1.973 +      options.callback(options);
   1.974 +    }
   1.975 +  };
   1.976 +
   1.977 +  let successCb = function successCb(pbrs) {
   1.978 +    do_check_eq(pbrs[0].adn.fileId, 0x4f3a);
   1.979 +    do_check_eq(pbrs.length, 1);
   1.980 +  };
   1.981 +
   1.982 +  let errorCb = function errorCb(errorMsg) {
   1.983 +    do_print("Reading EF_PBR failed, msg = " + errorMsg);
   1.984 +    do_check_true(false);
   1.985 +  };
   1.986 +
   1.987 +  record.readPBR(successCb, errorCb);
   1.988 +
   1.989 +  // Check cache pbrs when 2nd call
   1.990 +  let ifLoadEF = false;
   1.991 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
   1.992 +    ifLoadEF = true;
   1.993 +  }
   1.994 +  record.readPBR(successCb, errorCb);
   1.995 +  do_check_false(ifLoadEF);
   1.996 +
   1.997 +  run_next_test();
   1.998 +});
   1.999 +
  1.1000 +/**
  1.1001 + * Verify ICCRecordHelper.readEmail
  1.1002 + */
  1.1003 +add_test(function test_read_email() {
  1.1004 +  let worker = newUint8Worker();
  1.1005 +  let context = worker.ContextPool._contexts[0];
  1.1006 +  let helper = context.GsmPDUHelper;
  1.1007 +  let record = context.ICCRecordHelper;
  1.1008 +  let buf    = context.Buf;
  1.1009 +  let io     = context.ICCIOHelper;
  1.1010 +  let recordSize;
  1.1011 +
  1.1012 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
  1.1013 +    let email_1 = [
  1.1014 +      0x65, 0x6D, 0x61, 0x69, 0x6C,
  1.1015 +      0x00, 0x6D, 0x6F, 0x7A, 0x69,
  1.1016 +      0x6C, 0x6C, 0x61, 0x2E, 0x63,
  1.1017 +      0x6F, 0x6D, 0x02, 0x23];
  1.1018 +
  1.1019 +    // Write data size
  1.1020 +    buf.writeInt32(email_1.length * 2);
  1.1021 +
  1.1022 +    // Write email
  1.1023 +    for (let i = 0; i < email_1.length; i++) {
  1.1024 +      helper.writeHexOctet(email_1[i]);
  1.1025 +    }
  1.1026 +
  1.1027 +    // Write string delimiter
  1.1028 +    buf.writeStringDelimiter(email_1.length * 2);
  1.1029 +
  1.1030 +    recordSize = email_1.length;
  1.1031 +    options.recordSize = recordSize;
  1.1032 +    if (options.callback) {
  1.1033 +      options.callback(options);
  1.1034 +    }
  1.1035 +  };
  1.1036 +
  1.1037 +  function doTestReadEmail(type, expectedResult) {
  1.1038 +    let fileId = 0x6a75;
  1.1039 +    let recordNumber = 1;
  1.1040 +
  1.1041 +    // fileId and recordNumber are dummy arguments.
  1.1042 +    record.readEmail(fileId, type, recordNumber, function(email) {
  1.1043 +      do_check_eq(email, expectedResult);
  1.1044 +    });
  1.1045 +  };
  1.1046 +
  1.1047 +  doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
  1.1048 +  doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
  1.1049 +  do_check_eq(record._emailRecordSize, recordSize);
  1.1050 +
  1.1051 +  run_next_test();
  1.1052 +});
  1.1053 +
  1.1054 +/**
  1.1055 + * Verify ICCRecordHelper.updateEmail
  1.1056 + */
  1.1057 +add_test(function test_update_email() {
  1.1058 +  const recordSize = 0x20;
  1.1059 +  const recordNumber = 1;
  1.1060 +  const fileId = 0x4f50;
  1.1061 +  const NUM_TESTS = 2;
  1.1062 +  let worker = newUint8Worker();
  1.1063 +  let context = worker.ContextPool._contexts[0];
  1.1064 +  let pduHelper = context.GsmPDUHelper;
  1.1065 +  let iccHelper = context.ICCPDUHelper;
  1.1066 +  let ril = context.RIL;
  1.1067 +  ril.appType = CARD_APPTYPE_USIM;
  1.1068 +  let recordHelper = context.ICCRecordHelper;
  1.1069 +  let buf = context.Buf;
  1.1070 +  let ioHelper = context.ICCIOHelper;
  1.1071 +  let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
  1.1072 +             adn: {sfi: 1}};
  1.1073 +  let count = 0;
  1.1074 +
  1.1075 +  // Override.
  1.1076 +  ioHelper.updateLinearFixedEF = function(options) {
  1.1077 +    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
  1.1078 +    options.command = ICC_COMMAND_UPDATE_RECORD;
  1.1079 +    options.p1 = options.recordNumber;
  1.1080 +    options.p2 = READ_RECORD_ABSOLUTE_MODE;
  1.1081 +    options.p3 = recordSize;
  1.1082 +    ril.iccIO(options);
  1.1083 +  };
  1.1084 +
  1.1085 +  function do_test(pbr, expectedEmail, expectedAdnRecordId) {
  1.1086 +    buf.sendParcel = function() {
  1.1087 +      count++;
  1.1088 +
  1.1089 +      // Request Type.
  1.1090 +      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
  1.1091 +
  1.1092 +      // Token : we don't care
  1.1093 +      this.readInt32();
  1.1094 +
  1.1095 +      // command.
  1.1096 +      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
  1.1097 +
  1.1098 +      // fileId.
  1.1099 +      do_check_eq(this.readInt32(), fileId);
  1.1100 +
  1.1101 +      // pathId.
  1.1102 +      do_check_eq(this.readString(),
  1.1103 +                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
  1.1104 +
  1.1105 +      // p1.
  1.1106 +      do_check_eq(this.readInt32(), recordNumber);
  1.1107 +
  1.1108 +      // p2.
  1.1109 +      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
  1.1110 +
  1.1111 +      // p3.
  1.1112 +      do_check_eq(this.readInt32(), recordSize);
  1.1113 +
  1.1114 +      // data.
  1.1115 +      let strLen = this.readInt32();
  1.1116 +      let email;
  1.1117 +      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
  1.1118 +        email = iccHelper.read8BitUnpackedToString(recordSize);
  1.1119 +      } else {
  1.1120 +        email = iccHelper.read8BitUnpackedToString(recordSize - 2);
  1.1121 +        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
  1.1122 +        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
  1.1123 +      }
  1.1124 +      this.readStringDelimiter(strLen);
  1.1125 +      do_check_eq(email, expectedEmail);
  1.1126 +
  1.1127 +      // pin2.
  1.1128 +      do_check_eq(this.readString(), null);
  1.1129 +
  1.1130 +      if (!ril.v5Legacy) {
  1.1131 +        // AID. Ignore because it's from modem.
  1.1132 +        this.readInt32();
  1.1133 +      }
  1.1134 +
  1.1135 +      if (count == NUM_TESTS) {
  1.1136 +        run_next_test();
  1.1137 +      }
  1.1138 +    };
  1.1139 +    recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
  1.1140 +  }
  1.1141 +
  1.1142 +  do_test(pbr, "test@mail.com");
  1.1143 +  pbr.email.fileType = ICC_USIM_TYPE2_TAG;
  1.1144 +  do_test(pbr, "test@mail.com", 1);
  1.1145 +});
  1.1146 +
  1.1147 +/**
  1.1148 + * Verify ICCRecordHelper.readANR
  1.1149 + */
  1.1150 +add_test(function test_read_anr() {
  1.1151 +  let worker = newUint8Worker();
  1.1152 +  let context = worker.ContextPool._contexts[0];
  1.1153 +  let helper = context.GsmPDUHelper;
  1.1154 +  let record = context.ICCRecordHelper;
  1.1155 +  let buf    = context.Buf;
  1.1156 +  let io     = context.ICCIOHelper;
  1.1157 +  let recordSize;
  1.1158 +
  1.1159 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
  1.1160 +    let anr_1 = [
  1.1161 +      0x01, 0x05, 0x81, 0x10, 0x32,
  1.1162 +      0x54, 0xF6, 0xFF, 0xFF];
  1.1163 +
  1.1164 +    // Write data size
  1.1165 +    buf.writeInt32(anr_1.length * 2);
  1.1166 +
  1.1167 +    // Write anr
  1.1168 +    for (let i = 0; i < anr_1.length; i++) {
  1.1169 +      helper.writeHexOctet(anr_1[i]);
  1.1170 +    }
  1.1171 +
  1.1172 +    // Write string delimiter
  1.1173 +    buf.writeStringDelimiter(anr_1.length * 2);
  1.1174 +
  1.1175 +    recordSize = anr_1.length;
  1.1176 +    options.recordSize = recordSize;
  1.1177 +    if (options.callback) {
  1.1178 +      options.callback(options);
  1.1179 +    }
  1.1180 +  };
  1.1181 +
  1.1182 +  function doTestReadAnr(fileType, expectedResult) {
  1.1183 +    let fileId = 0x4f11;
  1.1184 +    let recordNumber = 1;
  1.1185 +
  1.1186 +    // fileId and recordNumber are dummy arguments.
  1.1187 +    record.readANR(fileId, fileType, recordNumber, function(anr) {
  1.1188 +      do_check_eq(anr, expectedResult);
  1.1189 +    });
  1.1190 +  };
  1.1191 +
  1.1192 +  doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
  1.1193 +  do_check_eq(record._anrRecordSize, recordSize);
  1.1194 +
  1.1195 +  run_next_test();
  1.1196 +});
  1.1197 +
  1.1198 +/**
  1.1199 + * Verify ICCRecordHelper.updateANR
  1.1200 + */
  1.1201 +add_test(function test_update_anr() {
  1.1202 +  const recordSize = 0x20;
  1.1203 +  const recordNumber = 1;
  1.1204 +  const fileId = 0x4f11;
  1.1205 +  const NUM_TESTS = 2;
  1.1206 +  let worker = newUint8Worker();
  1.1207 +  let context = worker.ContextPool._contexts[0];
  1.1208 +  let pduHelper = context.GsmPDUHelper;
  1.1209 +  let iccHelper = context.ICCPDUHelper;
  1.1210 +  let ril = context.RIL;
  1.1211 +  ril.appType = CARD_APPTYPE_USIM;
  1.1212 +  let recordHelper = context.ICCRecordHelper;
  1.1213 +  let buf = context.Buf;
  1.1214 +  let ioHelper = context.ICCIOHelper;
  1.1215 +  let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
  1.1216 +             adn: {sfi: 1}};
  1.1217 +  let count = 0;
  1.1218 +
  1.1219 +  // Override.
  1.1220 +  ioHelper.updateLinearFixedEF = function(options) {
  1.1221 +    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
  1.1222 +    options.command = ICC_COMMAND_UPDATE_RECORD;
  1.1223 +    options.p1 = options.recordNumber;
  1.1224 +    options.p2 = READ_RECORD_ABSOLUTE_MODE;
  1.1225 +    options.p3 = recordSize;
  1.1226 +    ril.iccIO(options);
  1.1227 +  };
  1.1228 +
  1.1229 +  function do_test(pbr, expectedANR, expectedAdnRecordId) {
  1.1230 +    buf.sendParcel = function() {
  1.1231 +      count++;
  1.1232 +
  1.1233 +      // Request Type.
  1.1234 +      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
  1.1235 +
  1.1236 +      // Token : we don't care
  1.1237 +      this.readInt32();
  1.1238 +
  1.1239 +      // command.
  1.1240 +      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
  1.1241 +
  1.1242 +      // fileId.
  1.1243 +      do_check_eq(this.readInt32(), fileId);
  1.1244 +
  1.1245 +      // pathId.
  1.1246 +      do_check_eq(this.readString(),
  1.1247 +                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
  1.1248 +
  1.1249 +      // p1.
  1.1250 +      do_check_eq(this.readInt32(), recordNumber);
  1.1251 +
  1.1252 +      // p2.
  1.1253 +      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
  1.1254 +
  1.1255 +      // p3.
  1.1256 +      do_check_eq(this.readInt32(), recordSize);
  1.1257 +
  1.1258 +      // data.
  1.1259 +      let strLen = this.readInt32();
  1.1260 +      // EF_AAS, ignore.
  1.1261 +      pduHelper.readHexOctet();
  1.1262 +      do_check_eq(iccHelper.readNumberWithLength(), expectedANR);
  1.1263 +      // EF_CCP, ignore.
  1.1264 +      pduHelper.readHexOctet();
  1.1265 +      // EF_EXT1, ignore.
  1.1266 +      pduHelper.readHexOctet();
  1.1267 +      if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
  1.1268 +        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
  1.1269 +        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
  1.1270 +      }
  1.1271 +      this.readStringDelimiter(strLen);
  1.1272 +
  1.1273 +      // pin2.
  1.1274 +      do_check_eq(this.readString(), null);
  1.1275 +
  1.1276 +      if (!ril.v5Legacy) {
  1.1277 +        // AID. Ignore because it's from modem.
  1.1278 +        this.readInt32();
  1.1279 +      }
  1.1280 +
  1.1281 +      if (count == NUM_TESTS) {
  1.1282 +        run_next_test();
  1.1283 +      }
  1.1284 +    };
  1.1285 +    recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
  1.1286 +  }
  1.1287 +
  1.1288 +  do_test(pbr, "+123456789");
  1.1289 +  pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
  1.1290 +  do_test(pbr, "123456789", 1);
  1.1291 +});
  1.1292 +
  1.1293 +/**
  1.1294 + * Verify ICCRecordHelper.readIAP
  1.1295 + */
  1.1296 +add_test(function test_read_iap() {
  1.1297 +  let worker = newUint8Worker();
  1.1298 +  let context = worker.ContextPool._contexts[0];
  1.1299 +  let helper = context.GsmPDUHelper;
  1.1300 +  let record = context.ICCRecordHelper;
  1.1301 +  let buf    = context.Buf;
  1.1302 +  let io     = context.ICCIOHelper;
  1.1303 +  let recordSize;
  1.1304 +
  1.1305 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
  1.1306 +    let iap_1 = [0x01, 0x02];
  1.1307 +
  1.1308 +    // Write data size/
  1.1309 +    buf.writeInt32(iap_1.length * 2);
  1.1310 +
  1.1311 +    // Write iap.
  1.1312 +    for (let i = 0; i < iap_1.length; i++) {
  1.1313 +      helper.writeHexOctet(iap_1[i]);
  1.1314 +    }
  1.1315 +
  1.1316 +    // Write string delimiter.
  1.1317 +    buf.writeStringDelimiter(iap_1.length * 2);
  1.1318 +
  1.1319 +    recordSize = iap_1.length;
  1.1320 +    options.recordSize = recordSize;
  1.1321 +    if (options.callback) {
  1.1322 +      options.callback(options);
  1.1323 +    }
  1.1324 +  };
  1.1325 +
  1.1326 +  function doTestReadIAP(expectedIAP) {
  1.1327 +    const fileId = 0x4f17;
  1.1328 +    const recordNumber = 1;
  1.1329 +
  1.1330 +    let successCb = function successCb(iap) {
  1.1331 +      for (let i = 0; i < iap.length; i++) {
  1.1332 +        do_check_eq(expectedIAP[i], iap[i]);
  1.1333 +      }
  1.1334 +      run_next_test();
  1.1335 +    }.bind(this);
  1.1336 +
  1.1337 +    let errorCb = function errorCb(errorMsg) {
  1.1338 +      do_print(errorMsg);
  1.1339 +      do_check_true(false);
  1.1340 +      run_next_test();
  1.1341 +    }.bind(this);
  1.1342 +
  1.1343 +    record.readIAP(fileId, recordNumber, successCb, errorCb);
  1.1344 +  };
  1.1345 +
  1.1346 +  doTestReadIAP([1, 2]);
  1.1347 +});
  1.1348 +
  1.1349 +/**
  1.1350 + * Verify ICCRecordHelper.updateIAP
  1.1351 + */
  1.1352 +add_test(function test_update_iap() {
  1.1353 +  const recordSize = 2;
  1.1354 +  const recordNumber = 1;
  1.1355 +  const fileId = 0x4f17;
  1.1356 +  let worker = newUint8Worker();
  1.1357 +  let context = worker.ContextPool._contexts[0];
  1.1358 +  let pduHelper = context.GsmPDUHelper;
  1.1359 +  let ril = context.RIL;
  1.1360 +  ril.appType = CARD_APPTYPE_USIM;
  1.1361 +  let recordHelper = context.ICCRecordHelper;
  1.1362 +  let buf = context.Buf;
  1.1363 +  let ioHelper = context.ICCIOHelper;
  1.1364 +  let count = 0;
  1.1365 +
  1.1366 +  // Override.
  1.1367 +  ioHelper.updateLinearFixedEF = function(options) {
  1.1368 +    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
  1.1369 +    options.command = ICC_COMMAND_UPDATE_RECORD;
  1.1370 +    options.p1 = options.recordNumber;
  1.1371 +    options.p2 = READ_RECORD_ABSOLUTE_MODE;
  1.1372 +    options.p3 = recordSize;
  1.1373 +    ril.iccIO(options);
  1.1374 +  };
  1.1375 +
  1.1376 +  function do_test(expectedIAP) {
  1.1377 +    buf.sendParcel = function() {
  1.1378 +      // Request Type.
  1.1379 +      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
  1.1380 +
  1.1381 +      // Token : we don't care
  1.1382 +      this.readInt32();
  1.1383 +
  1.1384 +      // command.
  1.1385 +      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
  1.1386 +
  1.1387 +      // fileId.
  1.1388 +      do_check_eq(this.readInt32(), fileId);
  1.1389 +
  1.1390 +      // pathId.
  1.1391 +      do_check_eq(this.readString(),
  1.1392 +                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
  1.1393 +
  1.1394 +      // p1.
  1.1395 +      do_check_eq(this.readInt32(), recordNumber);
  1.1396 +
  1.1397 +      // p2.
  1.1398 +      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
  1.1399 +
  1.1400 +      // p3.
  1.1401 +      do_check_eq(this.readInt32(), recordSize);
  1.1402 +
  1.1403 +      // data.
  1.1404 +      let strLen = this.readInt32();
  1.1405 +      for (let i = 0; i < recordSize; i++) {
  1.1406 +        do_check_eq(expectedIAP[i], pduHelper.readHexOctet());
  1.1407 +      }
  1.1408 +      this.readStringDelimiter(strLen);
  1.1409 +
  1.1410 +      // pin2.
  1.1411 +      do_check_eq(this.readString(), null);
  1.1412 +
  1.1413 +      if (!ril.v5Legacy) {
  1.1414 +        // AID. Ignore because it's from modem.
  1.1415 +        this.readInt32();
  1.1416 +      }
  1.1417 +
  1.1418 +      run_next_test();
  1.1419 +    };
  1.1420 +    recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
  1.1421 +  }
  1.1422 +
  1.1423 +  do_test([1, 2]);
  1.1424 +});
  1.1425 +
  1.1426 +/**
  1.1427 + * Verify ICCRecordHelper.updateADNLike.
  1.1428 + */
  1.1429 +add_test(function test_update_adn_like() {
  1.1430 +  let worker = newUint8Worker();
  1.1431 +  let context = worker.ContextPool._contexts[0];
  1.1432 +  let ril = context.RIL;
  1.1433 +  let record = context.ICCRecordHelper;
  1.1434 +  let io = context.ICCIOHelper;
  1.1435 +  let pdu = context.ICCPDUHelper;
  1.1436 +  let buf = context.Buf;
  1.1437 +
  1.1438 +  ril.appType = CARD_APPTYPE_SIM;
  1.1439 +  const recordSize = 0x20;
  1.1440 +  let fileId;
  1.1441 +
  1.1442 +  // Override.
  1.1443 +  io.updateLinearFixedEF = function(options) {
  1.1444 +    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
  1.1445 +    options.command = ICC_COMMAND_UPDATE_RECORD;
  1.1446 +    options.p1 = options.recordNumber;
  1.1447 +    options.p2 = READ_RECORD_ABSOLUTE_MODE;
  1.1448 +    options.p3 = recordSize;
  1.1449 +    ril.iccIO(options);
  1.1450 +  };
  1.1451 +
  1.1452 +  buf.sendParcel = function() {
  1.1453 +    // Request Type.
  1.1454 +    do_check_eq(this.readInt32(), REQUEST_SIM_IO);
  1.1455 +
  1.1456 +    // Token : we don't care
  1.1457 +    this.readInt32();
  1.1458 +
  1.1459 +    // command.
  1.1460 +    do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
  1.1461 +
  1.1462 +    // fileId.
  1.1463 +    do_check_eq(this.readInt32(), fileId);
  1.1464 +
  1.1465 +    // pathId.
  1.1466 +    do_check_eq(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
  1.1467 +
  1.1468 +    // p1.
  1.1469 +    do_check_eq(this.readInt32(), 1);
  1.1470 +
  1.1471 +    // p2.
  1.1472 +    do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
  1.1473 +
  1.1474 +    // p3.
  1.1475 +    do_check_eq(this.readInt32(), 0x20);
  1.1476 +
  1.1477 +    // data.
  1.1478 +    let contact = pdu.readAlphaIdDiallingNumber(0x20);
  1.1479 +    do_check_eq(contact.alphaId, "test");
  1.1480 +    do_check_eq(contact.number, "123456");
  1.1481 +
  1.1482 +    // pin2.
  1.1483 +    if (fileId == ICC_EF_ADN) {
  1.1484 +      do_check_eq(this.readString(), null);
  1.1485 +    } else {
  1.1486 +      do_check_eq(this.readString(), "1111");
  1.1487 +    }
  1.1488 +
  1.1489 +    if (!ril.v5Legacy) {
  1.1490 +      // AID. Ignore because it's from modem.
  1.1491 +      this.readInt32();
  1.1492 +    }
  1.1493 +
  1.1494 +    if (fileId == ICC_EF_FDN) {
  1.1495 +      run_next_test();
  1.1496 +    }
  1.1497 +  };
  1.1498 +
  1.1499 +  fileId = ICC_EF_ADN;
  1.1500 +  record.updateADNLike(fileId,
  1.1501 +                       {recordId: 1, alphaId: "test", number: "123456"});
  1.1502 +
  1.1503 +  fileId = ICC_EF_FDN;
  1.1504 +  record.updateADNLike(fileId,
  1.1505 +                       {recordId: 1, alphaId: "test", number: "123456"},
  1.1506 +                       "1111");
  1.1507 +});
  1.1508 +
  1.1509 +/**
  1.1510 + * Verify ICCRecordHelper.findFreeRecordId.
  1.1511 + */
  1.1512 +add_test(function test_find_free_record_id() {
  1.1513 +  let worker = newUint8Worker();
  1.1514 +  let context = worker.ContextPool._contexts[0];
  1.1515 +  let pduHelper = context.GsmPDUHelper;
  1.1516 +  let recordHelper = context.ICCRecordHelper;
  1.1517 +  let buf = context.Buf;
  1.1518 +  let io  = context.ICCIOHelper;
  1.1519 +
  1.1520 +  function writeRecord (record) {
  1.1521 +    // Write data size
  1.1522 +    buf.writeInt32(record.length * 2);
  1.1523 +
  1.1524 +    for (let i = 0; i < record.length; i++) {
  1.1525 +      pduHelper.writeHexOctet(record[i]);
  1.1526 +    }
  1.1527 +
  1.1528 +    // Write string delimiter
  1.1529 +    buf.writeStringDelimiter(record.length * 2);
  1.1530 +  }
  1.1531 +
  1.1532 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
  1.1533 +    // Some random data.
  1.1534 +    let record = [0x12, 0x34, 0x56, 0x78, 0x90];
  1.1535 +    options.p1 = 1;
  1.1536 +    options.totalRecords = 2;
  1.1537 +    writeRecord(record);
  1.1538 +    if (options.callback) {
  1.1539 +      options.callback(options);
  1.1540 +    }
  1.1541 +  };
  1.1542 +
  1.1543 +  io.loadNextRecord = function fakeLoadNextRecord(options) {
  1.1544 +    // Unused bytes.
  1.1545 +    let record = [0xff, 0xff, 0xff, 0xff, 0xff];
  1.1546 +    options.p1++;
  1.1547 +    writeRecord(record);
  1.1548 +    if (options.callback) {
  1.1549 +      options.callback(options);
  1.1550 +    }
  1.1551 +  };
  1.1552 +
  1.1553 +  let fileId = 0x0000; // Dummy.
  1.1554 +  recordHelper.findFreeRecordId(
  1.1555 +    fileId,
  1.1556 +    function(recordId) {
  1.1557 +      do_check_eq(recordId, 2);
  1.1558 +      run_next_test();
  1.1559 +    }.bind(this),
  1.1560 +    function(errorMsg) {
  1.1561 +      do_print(errorMsg);
  1.1562 +      do_check_true(false);
  1.1563 +      run_next_test();
  1.1564 +    }.bind(this));
  1.1565 +});
  1.1566 +
  1.1567 +/**
  1.1568 + * Verify ICCContactHelper.readICCContacts
  1.1569 + */
  1.1570 +add_test(function test_read_icc_contacts() {
  1.1571 +  let worker = newUint8Worker();
  1.1572 +  let context = worker.ContextPool._contexts[0];
  1.1573 +  let record = context.ICCRecordHelper;
  1.1574 +  let contactHelper = context.ICCContactHelper;
  1.1575 +  let ril = context.RIL;
  1.1576 +
  1.1577 +  function do_test(aSimType, aContactType, aExpectedContact, aEnhancedPhoneBook) {
  1.1578 +    ril.appType = aSimType;
  1.1579 +    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
  1.1580 +    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ?
  1.1581 +                                    [0x0, 0x0C, 0x0, 0x0, 0x0]:
  1.1582 +                                    [0x0, 0x00, 0x0, 0x0, 0x0];
  1.1583 +
  1.1584 +    // Override some functions to test.
  1.1585 +    contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
  1.1586 +      onsuccess(1);
  1.1587 +    };
  1.1588 +
  1.1589 +    record.readPBR = function readPBR(onsuccess, onerror) {
  1.1590 +      onsuccess([{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}]);
  1.1591 +    };
  1.1592 +
  1.1593 +    record.readADNLike = function readADNLike(fileId, onsuccess, onerror) {
  1.1594 +      onsuccess([{recordId: 1, alphaId: "name", number: "111111"}])
  1.1595 +    };
  1.1596 +
  1.1597 +    record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
  1.1598 +      onsuccess("hello@mail.com");
  1.1599 +    };
  1.1600 +
  1.1601 +    record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
  1.1602 +      onsuccess("123456");
  1.1603 +    };
  1.1604 +
  1.1605 +    let onsuccess = function onsuccess(contacts) {
  1.1606 +      let contact = contacts[0];
  1.1607 +      for (let key in contact) {
  1.1608 +        do_print("check " + key);
  1.1609 +        if (Array.isArray(contact[key])) {
  1.1610 +          do_check_eq(contact[key][0], aExpectedContact[key]);
  1.1611 +        } else {
  1.1612 +          do_check_eq(contact[key], aExpectedContact[key]);
  1.1613 +        }
  1.1614 +      }
  1.1615 +    };
  1.1616 +
  1.1617 +    let onerror = function onerror(errorMsg) {
  1.1618 +      do_print("readICCContacts failed: " + errorMsg);
  1.1619 +      do_check_true(false);
  1.1620 +    };
  1.1621 +
  1.1622 +    contactHelper.readICCContacts(aSimType, aContactType, onsuccess, onerror);
  1.1623 +  }
  1.1624 +
  1.1625 +  let expectedContact1 = {
  1.1626 +    pbrIndex: 0,
  1.1627 +    recordId: 1,
  1.1628 +    alphaId:  "name",
  1.1629 +    number:   "111111"
  1.1630 +  };
  1.1631 +
  1.1632 +  let expectedContact2 = {
  1.1633 +    pbrIndex: 0,
  1.1634 +    recordId: 1,
  1.1635 +    alphaId:  "name",
  1.1636 +    number:   "111111",
  1.1637 +    email:    "hello@mail.com",
  1.1638 +    anr:      "123456"
  1.1639 +  };
  1.1640 +
  1.1641 +  // SIM
  1.1642 +  do_print("Test read SIM adn contacts");
  1.1643 +  do_test(CARD_APPTYPE_SIM, "adn", expectedContact1);
  1.1644 +
  1.1645 +  do_print("Test read SIM fdn contacts");
  1.1646 +  do_test(CARD_APPTYPE_SIM, "fdn", expectedContact1);
  1.1647 +
  1.1648 +  // USIM
  1.1649 +  do_print("Test read USIM adn contacts");
  1.1650 +  do_test(CARD_APPTYPE_USIM, "adn", expectedContact2);
  1.1651 +
  1.1652 +  do_print("Test read USIM fdn contacts");
  1.1653 +  do_test(CARD_APPTYPE_USIM, "fdn", expectedContact1);
  1.1654 +
  1.1655 +  // RUIM
  1.1656 +  do_print("Test read RUIM adn contacts");
  1.1657 +  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact1);
  1.1658 +
  1.1659 +  do_print("Test read RUIM fdn contacts");
  1.1660 +  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1);
  1.1661 +
  1.1662 +  // RUIM with enhanced phone book
  1.1663 +  do_print("Test read RUIM adn contacts with enhanced phone book");
  1.1664 +  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact2, true);
  1.1665 +
  1.1666 +  do_print("Test read RUIM fdn contacts with enhanced phone book");
  1.1667 +  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1, true);
  1.1668 +
  1.1669 +  run_next_test();
  1.1670 +});
  1.1671 +
  1.1672 +/**
  1.1673 + * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
  1.1674 + */
  1.1675 +add_test(function test_update_icc_contact() {
  1.1676 +  const ADN_RECORD_ID   = 100;
  1.1677 +  const ADN_SFI         = 1;
  1.1678 +  const IAP_FILE_ID     = 0x4f17;
  1.1679 +  const EMAIL_FILE_ID   = 0x4f50;
  1.1680 +  const EMAIL_RECORD_ID = 20;
  1.1681 +  const ANR0_FILE_ID    = 0x4f11;
  1.1682 +  const ANR0_RECORD_ID  = 30;
  1.1683 +
  1.1684 +  let worker = newUint8Worker();
  1.1685 +  let context = worker.ContextPool._contexts[0];
  1.1686 +  let recordHelper = context.ICCRecordHelper;
  1.1687 +  let contactHelper = context.ICCContactHelper;
  1.1688 +  let ril = context.RIL;
  1.1689 +
  1.1690 +  function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
  1.1691 +    ril.appType = aSimType;
  1.1692 +    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
  1.1693 +    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x0, 0x0C, 0x0, 0x0, 0x0]
  1.1694 +                                                  : [0x0, 0x00, 0x0, 0x0, 0x0];
  1.1695 +
  1.1696 +    recordHelper.readPBR = function(onsuccess, onerror) {
  1.1697 +      if (aFileType === ICC_USIM_TYPE1_TAG) {
  1.1698 +        onsuccess([{
  1.1699 +          adn:   {fileId: ICC_EF_ADN},
  1.1700 +          email: {fileId: EMAIL_FILE_ID,
  1.1701 +                  fileType: ICC_USIM_TYPE1_TAG},
  1.1702 +          anr0:  {fileId: ANR0_FILE_ID,
  1.1703 +                  fileType: ICC_USIM_TYPE1_TAG}
  1.1704 +        }]);
  1.1705 +      } else if (aFileType === ICC_USIM_TYPE2_TAG) {
  1.1706 +        onsuccess([{
  1.1707 +          adn:   {fileId: ICC_EF_ADN,
  1.1708 +                  sfi: ADN_SFI},
  1.1709 +          iap:   {fileId: IAP_FILE_ID},
  1.1710 +          email: {fileId: EMAIL_FILE_ID,
  1.1711 +                  fileType: ICC_USIM_TYPE2_TAG,
  1.1712 +                  indexInIAP: 0},
  1.1713 +          anr0:  {fileId: ANR0_FILE_ID,
  1.1714 +                  fileType: ICC_USIM_TYPE2_TAG,
  1.1715 +                  indexInIAP: 1}
  1.1716 +        }]);
  1.1717 +      }
  1.1718 +    };
  1.1719 +
  1.1720 +    recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
  1.1721 +      if (aContactType === "fdn") {
  1.1722 +        do_check_eq(fileId, ICC_EF_FDN);
  1.1723 +      } else if (aContactType === "adn") {
  1.1724 +        do_check_eq(fileId, ICC_EF_ADN);
  1.1725 +      }
  1.1726 +      do_check_eq(pin2, aPin2);
  1.1727 +      do_check_eq(contact.alphaId, aContact.alphaId);
  1.1728 +      do_check_eq(contact.number, aContact.number);
  1.1729 +      onsuccess();
  1.1730 +    };
  1.1731 +
  1.1732 +    recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
  1.1733 +      do_check_eq(fileId, IAP_FILE_ID);
  1.1734 +      do_check_eq(recordNumber, ADN_RECORD_ID);
  1.1735 +      onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
  1.1736 +                                : [0xff, 0xff]);
  1.1737 +    };
  1.1738 +
  1.1739 +    recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
  1.1740 +      do_check_eq(fileId, IAP_FILE_ID);
  1.1741 +      do_check_eq(recordNumber, ADN_RECORD_ID);
  1.1742 +      onsuccess();
  1.1743 +    };
  1.1744 +
  1.1745 +    recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
  1.1746 +      do_check_eq(pbr.email.fileId, EMAIL_FILE_ID);
  1.1747 +      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
  1.1748 +        do_check_eq(recordNumber, ADN_RECORD_ID);
  1.1749 +      } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
  1.1750 +        do_check_eq(recordNumber, EMAIL_RECORD_ID);
  1.1751 +      }
  1.1752 +      do_check_eq(email, aContact.email);
  1.1753 +      onsuccess();
  1.1754 +    };
  1.1755 +
  1.1756 +    recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
  1.1757 +      do_check_eq(pbr.anr0.fileId, ANR0_FILE_ID);
  1.1758 +      if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
  1.1759 +        do_check_eq(recordNumber, ADN_RECORD_ID);
  1.1760 +      } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
  1.1761 +        do_check_eq(recordNumber, ANR0_RECORD_ID);
  1.1762 +      }
  1.1763 +      if (Array.isArray(aContact.anr)) {
  1.1764 +        do_check_eq(number, aContact.anr[0]);
  1.1765 +      }
  1.1766 +      onsuccess();
  1.1767 +    };
  1.1768 +
  1.1769 +    recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
  1.1770 +      let recordId = 0;
  1.1771 +      if (fileId === EMAIL_FILE_ID) {
  1.1772 +        recordId = EMAIL_RECORD_ID;
  1.1773 +      } else if (fileId === ANR0_FILE_ID) {
  1.1774 +        recordId = ANR0_RECORD_ID;
  1.1775 +      }
  1.1776 +      onsuccess(recordId);
  1.1777 +    };
  1.1778 +
  1.1779 +    let isSuccess = false;
  1.1780 +    let onsuccess = function onsuccess() {
  1.1781 +      do_print("updateICCContact success");
  1.1782 +      isSuccess = true;
  1.1783 +    };
  1.1784 +
  1.1785 +    let onerror = function onerror(errorMsg) {
  1.1786 +      do_print("updateICCContact failed: " + errorMsg);
  1.1787 +    };
  1.1788 +
  1.1789 +    contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
  1.1790 +    do_check_true(isSuccess);
  1.1791 +  }
  1.1792 +
  1.1793 +  let contacts = [
  1.1794 +    {
  1.1795 +      pbrIndex: 0,
  1.1796 +      recordId: ADN_RECORD_ID,
  1.1797 +      alphaId:  "test",
  1.1798 +      number:   "123456",
  1.1799 +      email:    "test@mail.com",
  1.1800 +      anr:      ["+654321"]
  1.1801 +    },
  1.1802 +    // a contact without email and anr.
  1.1803 +    {
  1.1804 +      pbrIndex: 0,
  1.1805 +      recordId: ADN_RECORD_ID,
  1.1806 +      alphaId:  "test2",
  1.1807 +      number:   "123456",
  1.1808 +    },
  1.1809 +    // a contact with email but no anr.
  1.1810 +    {
  1.1811 +      pbrIndex: 0,
  1.1812 +      recordId: ADN_RECORD_ID,
  1.1813 +      alphaId:  "test3",
  1.1814 +      number:   "123456",
  1.1815 +      email:    "test@mail.com"
  1.1816 +    },
  1.1817 +    // a contact with anr but no email.
  1.1818 +    {
  1.1819 +      pbrIndex: 0,
  1.1820 +      recordId: ADN_RECORD_ID,
  1.1821 +      alphaId:  "test4",
  1.1822 +      number:   "123456",
  1.1823 +      anr:      ["+654321"]
  1.1824 +    }];
  1.1825 +
  1.1826 +  for (let i = 0; i < contacts.length; i++) {
  1.1827 +    let contact = contacts[i];
  1.1828 +    // SIM
  1.1829 +    do_print("Test update SIM adn contacts");
  1.1830 +    do_test(CARD_APPTYPE_SIM, "adn", contact);
  1.1831 +
  1.1832 +    do_print("Test update SIM fdn contacts");
  1.1833 +    do_test(CARD_APPTYPE_SIM, "fdn", contact, "1234");
  1.1834 +
  1.1835 +    // USIM
  1.1836 +    do_print("Test update USIM adn contacts");
  1.1837 +    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE1_TAG);
  1.1838 +    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true);
  1.1839 +    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false);
  1.1840 +
  1.1841 +    do_print("Test update USIM fdn contacts");
  1.1842 +    do_test(CARD_APPTYPE_USIM, "fdn", contact, "1234");
  1.1843 +
  1.1844 +    // RUIM
  1.1845 +    do_print("Test update RUIM adn contacts");
  1.1846 +    do_test(CARD_APPTYPE_RUIM, "adn", contact);
  1.1847 +
  1.1848 +    do_print("Test update RUIM fdn contacts");
  1.1849 +    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234");
  1.1850 +
  1.1851 +    // RUIM with enhanced phone book
  1.1852 +    do_print("Test update RUIM adn contacts with enhanced phone book");
  1.1853 +    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE1_TAG, null, true);
  1.1854 +    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true, true);
  1.1855 +    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false, true);
  1.1856 +
  1.1857 +    do_print("Test update RUIM fdn contacts with enhanced phone book");
  1.1858 +    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234", null, true);
  1.1859 +  }
  1.1860 +
  1.1861 +  run_next_test();
  1.1862 +});
  1.1863 +
  1.1864 +/**
  1.1865 + * Verify updateICCContact with removal of anr and email with File Type 1.
  1.1866 + */
  1.1867 +add_test(function test_update_icc_contact_with_remove_type1_attr() {
  1.1868 +  const ADN_RECORD_ID   = 100;
  1.1869 +  const IAP_FILE_ID     = 0x4f17;
  1.1870 +  const EMAIL_FILE_ID   = 0x4f50;
  1.1871 +  const EMAIL_RECORD_ID = 20;
  1.1872 +  const ANR0_FILE_ID    = 0x4f11;
  1.1873 +  const ANR0_RECORD_ID  = 30;
  1.1874 +
  1.1875 +  let worker = newUint8Worker();
  1.1876 +  let context = worker.ContextPool._contexts[0];
  1.1877 +  let recordHelper = context.ICCRecordHelper;
  1.1878 +  let contactHelper = context.ICCContactHelper;
  1.1879 +
  1.1880 +  recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
  1.1881 +    onsuccess();
  1.1882 +  };
  1.1883 +
  1.1884 +  let contact = {
  1.1885 +    pbrIndex: 0,
  1.1886 +    recordId: ADN_RECORD_ID,
  1.1887 +    alphaId:  "test2",
  1.1888 +    number:   "123456",
  1.1889 +  };
  1.1890 +
  1.1891 +  recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
  1.1892 +    onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
  1.1893 +  };
  1.1894 +
  1.1895 +  recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
  1.1896 +    do_check_true(email == null);
  1.1897 +    onsuccess();
  1.1898 +  };
  1.1899 +
  1.1900 +  recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
  1.1901 +    do_check_true(number == null);
  1.1902 +    onsuccess();
  1.1903 +  };
  1.1904 +
  1.1905 +  function do_test(type) {
  1.1906 +    recordHelper.readPBR = function(onsuccess, onerror) {
  1.1907 +      if (type == ICC_USIM_TYPE1_TAG) {
  1.1908 +        onsuccess([{
  1.1909 +          adn:   {fileId: ICC_EF_ADN},
  1.1910 +          email: {fileId: EMAIL_FILE_ID,
  1.1911 +                  fileType: ICC_USIM_TYPE1_TAG},
  1.1912 +          anr0:  {fileId: ANR0_FILE_ID,
  1.1913 +                  fileType: ICC_USIM_TYPE1_TAG}}]);
  1.1914 +      } else {
  1.1915 +        onsuccess([{
  1.1916 +          adn:   {fileId: ICC_EF_ADN},
  1.1917 +          iap:   {fileId: IAP_FILE_ID},
  1.1918 +          email: {fileId: EMAIL_FILE_ID,
  1.1919 +                  fileType: ICC_USIM_TYPE2_TAG,
  1.1920 +                  indexInIAP: 0},
  1.1921 +          anr0:  {fileId: ANR0_FILE_ID,
  1.1922 +                  fileType: ICC_USIM_TYPE2_TAG,
  1.1923 +                  indexInIAP: 1}}]);
  1.1924 +      }
  1.1925 +    };
  1.1926 +
  1.1927 +    let successCb = function() {
  1.1928 +      do_check_true(true);
  1.1929 +    };
  1.1930 +
  1.1931 +    let errorCb = function(errorMsg) {
  1.1932 +      do_print(errorMsg);
  1.1933 +      do_check_true(false);
  1.1934 +    };
  1.1935 +
  1.1936 +    contactHelper.updateICCContact(CARD_APPTYPE_USIM, "adn", contact, null, successCb, errorCb);
  1.1937 +  }
  1.1938 +
  1.1939 +  do_test(ICC_USIM_TYPE1_TAG);
  1.1940 +  do_test(ICC_USIM_TYPE2_TAG);
  1.1941 +
  1.1942 +  run_next_test();
  1.1943 +});
  1.1944 +
  1.1945 +/**
  1.1946 + * Verify ICCContactHelper.findFreeICCContact in SIM
  1.1947 + */
  1.1948 +add_test(function test_find_free_icc_contact_sim() {
  1.1949 +  let worker = newUint8Worker();
  1.1950 +  let context = worker.ContextPool._contexts[0];
  1.1951 +  let recordHelper = context.ICCRecordHelper;
  1.1952 +  let contactHelper = context.ICCContactHelper;
  1.1953 +  // Correct record Id starts with 1, so put a null element at index 0.
  1.1954 +  let records = [null];
  1.1955 +  const MAX_RECORDS = 3;
  1.1956 +  const PBR_INDEX = 0;
  1.1957 +
  1.1958 +  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
  1.1959 +    if (records.length > MAX_RECORDS) {
  1.1960 +      onerror("No free record found.");
  1.1961 +      return;
  1.1962 +    }
  1.1963 +
  1.1964 +    onsuccess(records.length);
  1.1965 +  };
  1.1966 +
  1.1967 +  let successCb = function(pbrIndex, recordId) {
  1.1968 +    do_check_eq(pbrIndex, PBR_INDEX);
  1.1969 +    records[recordId] = {};
  1.1970 +  };
  1.1971 +
  1.1972 +  let errorCb = function(errorMsg) {
  1.1973 +    do_print(errorMsg);
  1.1974 +    do_check_true(false);
  1.1975 +  };
  1.1976 +
  1.1977 +  for (let i = 0; i < MAX_RECORDS; i++) {
  1.1978 +    contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
  1.1979 +  }
  1.1980 +  // The 1st element, records[0], is null.
  1.1981 +  do_check_eq(records.length - 1, MAX_RECORDS);
  1.1982 +
  1.1983 +  // Now the EF is full, so finding a free one should result failure.
  1.1984 +  successCb = function(pbrIndex, recordId) {
  1.1985 +    do_check_true(false);
  1.1986 +  };
  1.1987 +
  1.1988 +  errorCb = function(errorMsg) {
  1.1989 +    do_check_true(errorMsg === "No free record found.");
  1.1990 +  };
  1.1991 +  contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
  1.1992 +
  1.1993 +  run_next_test();
  1.1994 +});
  1.1995 +
  1.1996 +/**
  1.1997 + * Verify ICCContactHelper.findFreeICCContact in USIM
  1.1998 + */
  1.1999 +add_test(function test_find_free_icc_contact_usim() {
  1.2000 +  let worker = newUint8Worker();
  1.2001 +  let context = worker.ContextPool._contexts[0];
  1.2002 +  let recordHelper = context.ICCRecordHelper;
  1.2003 +  let contactHelper = context.ICCContactHelper;
  1.2004 +  const ADN1_FILE_ID = 0x6f3a;
  1.2005 +  const ADN2_FILE_ID = 0x6f3b;
  1.2006 +  const MAX_RECORDS = 3;
  1.2007 +
  1.2008 +  // The adn in the first phonebook set has already two records, which means
  1.2009 +  // only 1 free record remained.
  1.2010 +  let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
  1.2011 +              {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
  1.2012 +
  1.2013 +  recordHelper.readPBR = function readPBR(onsuccess, onerror) {
  1.2014 +    onsuccess(pbrs);
  1.2015 +  };
  1.2016 +
  1.2017 +  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
  1.2018 +    let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
  1.2019 +    if (pbr.adn.records.length > MAX_RECORDS) {
  1.2020 +      onerror("No free record found.");
  1.2021 +      return;
  1.2022 +    }
  1.2023 +
  1.2024 +    onsuccess(pbr.adn.records.length);
  1.2025 +  };
  1.2026 +
  1.2027 +  let successCb = function(pbrIndex, recordId) {
  1.2028 +    do_check_eq(pbrIndex, 0);
  1.2029 +    pbrs[pbrIndex].adn.records[recordId] = {};
  1.2030 +  };
  1.2031 +
  1.2032 +  let errorCb = function(errorMsg) {
  1.2033 +    do_check_true(false);
  1.2034 +  };
  1.2035 +
  1.2036 +  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
  1.2037 +
  1.2038 +  // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
  1.2039 +  // will come from the 2nd phonebook set.
  1.2040 +  successCb = function(pbrIndex, recordId) {
  1.2041 +    do_check_eq(pbrIndex, 1);
  1.2042 +    do_check_eq(recordId, 1);
  1.2043 +  }
  1.2044 +  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
  1.2045 +
  1.2046 +  run_next_test();
  1.2047 +});
  1.2048 +
  1.2049 +/**
  1.2050 + * Test error message returned in onerror for readICCContacts.
  1.2051 + */
  1.2052 +add_test(function test_error_message_read_icc_contact () {
  1.2053 +  let worker = newUint8Worker();
  1.2054 +  let context = worker.ContextPool._contexts[0];
  1.2055 +  let ril = context.RIL;
  1.2056 +
  1.2057 +  function do_test(options, expectedErrorMsg) {
  1.2058 +    ril.sendChromeMessage = function(message) {
  1.2059 +      do_check_eq(message.errorMsg, expectedErrorMsg);
  1.2060 +    }
  1.2061 +    ril.readICCContacts(options);
  1.2062 +  }
  1.2063 +
  1.2064 +  // Error 1, didn't specify correct contactType.
  1.2065 +  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
  1.2066 +
  1.2067 +  // Error 2, specifying a non-supported contactType.
  1.2068 +  ril.appType = CARD_APPTYPE_USIM;
  1.2069 +  do_test({contactType: "sdn"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
  1.2070 +
  1.2071 +  // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
  1.2072 +  // but forget to add implemenetations for it.
  1.2073 +  USIM_PBR_FIELDS.push("pbc");
  1.2074 +  do_test({contactType: "adn"}, CONTACT_ERR_FIELD_NOT_SUPPORTED);
  1.2075 +
  1.2076 +  run_next_test();
  1.2077 +});
  1.2078 +
  1.2079 +/**
  1.2080 + * Test error message returned in onerror for updateICCContact.
  1.2081 + */
  1.2082 +add_test(function test_error_message_update_icc_contact() {
  1.2083 +  let worker = newUint8Worker();
  1.2084 +  let context = worker.ContextPool._contexts[0];
  1.2085 +  let ril = context.RIL;
  1.2086 +
  1.2087 +  const ICCID = "123456789";
  1.2088 +  ril.iccInfo.iccid = ICCID;
  1.2089 +
  1.2090 +  function do_test(options, expectedErrorMsg) {
  1.2091 +    ril.sendChromeMessage = function(message) {
  1.2092 +      do_check_eq(message.errorMsg, expectedErrorMsg);
  1.2093 +    }
  1.2094 +    ril.updateICCContact(options);
  1.2095 +  }
  1.2096 +
  1.2097 +  // Error 1, didn't specify correct contactType.
  1.2098 +  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
  1.2099 +
  1.2100 +  // Error 2, specifying a correct contactType, but without providing 'contact'.
  1.2101 +  do_test({contactType: "adn"}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
  1.2102 +
  1.2103 +  // Error 3, specifying a non-supported contactType.
  1.2104 +  ril.appType = CARD_APPTYPE_USIM;
  1.2105 +  do_test({contactType: "sdn", contact: {}}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
  1.2106 +
  1.2107 +  // Error 4, without supplying pin2.
  1.2108 +  do_test({contactType: "fdn", contact: {contactId: ICCID + "1"}}, GECKO_ERROR_SIM_PIN2);
  1.2109 +
  1.2110 +  // Error 5, No free record found in EF_ADN.
  1.2111 +  let record = context.ICCRecordHelper;
  1.2112 +  record.readPBR = function(onsuccess, onerror) {
  1.2113 +    onsuccess([{adn: {fileId: 0x4f3a}}]);
  1.2114 +  };
  1.2115 +
  1.2116 +  let io = context.ICCIOHelper;
  1.2117 +  io.loadLinearFixedEF = function(options) {
  1.2118 +    options.totalRecords = 1;
  1.2119 +    options.p1 = 1;
  1.2120 +    options.callback(options);
  1.2121 +  };
  1.2122 +
  1.2123 +  do_test({contactType: "adn", contact: {}}, CONTACT_ERR_NO_FREE_RECORD_FOUND);
  1.2124 +
  1.2125 +  // Error 6, ICC IO Error.
  1.2126 +  io.loadLinearFixedEF = function(options) {
  1.2127 +    ril[REQUEST_SIM_IO](0, {rilRequestError: ERROR_GENERIC_FAILURE});
  1.2128 +  };
  1.2129 +  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
  1.2130 +          GECKO_ERROR_GENERIC_FAILURE);
  1.2131 +
  1.2132 +  // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
  1.2133 +  // but forget to add implemenetations for it.
  1.2134 +  USIM_PBR_FIELDS.push("pbc");
  1.2135 +  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
  1.2136 +          CONTACT_ERR_FIELD_NOT_SUPPORTED);
  1.2137 +
  1.2138 +  // Error 8, EF_PBR doesn't exist.
  1.2139 +  record.readPBR = function(onsuccess, onerror) {
  1.2140 +    onsuccess([]);
  1.2141 +  };
  1.2142 +
  1.2143 +  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
  1.2144 +          CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
  1.2145 +
  1.2146 +  run_next_test();
  1.2147 +});
  1.2148 +
  1.2149 +add_test(function test_process_icc_io_error() {
  1.2150 +  let worker = newUint8Worker();
  1.2151 +  let context = worker.ContextPool._contexts[0];
  1.2152 +  let ioHelper = context.ICCIOHelper;
  1.2153 +
  1.2154 +  function do_test(errorCode, expectedErrorMsg) {
  1.2155 +    let called = false;
  1.2156 +    function errorCb(errorMsg) {
  1.2157 +      called = true;
  1.2158 +      do_check_eq(errorMsg, expectedErrorMsg);
  1.2159 +    }
  1.2160 +
  1.2161 +    ioHelper.processICCIOError({rilRequestError: errorCode,
  1.2162 +                                fileId: 0xffff,
  1.2163 +                                command: 0xff,
  1.2164 +                                sw1: 0xff,
  1.2165 +                                sw2: 0xff,
  1.2166 +                                onerror: errorCb});
  1.2167 +    do_check_true(called);
  1.2168 +  }
  1.2169 +
  1.2170 +  for (let i = 0; i < ERROR_REJECTED_BY_REMOTE + 1; i++) {
  1.2171 +    do_test(i, RIL_ERROR_TO_GECKO_ERROR[i]);
  1.2172 +  }
  1.2173 +
  1.2174 +  run_next_test();
  1.2175 +});
  1.2176 +
  1.2177 +add_test(function test_personalization_state() {
  1.2178 +  let worker = newUint8Worker();
  1.2179 +  let context = worker.ContextPool._contexts[0];
  1.2180 +  let ril = context.RIL;
  1.2181 +
  1.2182 +  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
  1.2183 +
  1.2184 +  function testPersonalization(isCdma, cardPersoState, geckoCardState) {
  1.2185 +    let iccStatus = {
  1.2186 +      cardState: CARD_STATE_PRESENT,
  1.2187 +      gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
  1.2188 +      cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
  1.2189 +      apps: [
  1.2190 +        {
  1.2191 +          app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
  1.2192 +          perso_substate: cardPersoState
  1.2193 +        }],
  1.2194 +    };
  1.2195 +
  1.2196 +    ril._isCdma = isCdma;
  1.2197 +    ril._processICCStatus(iccStatus);
  1.2198 +    do_check_eq(ril.cardState, geckoCardState);
  1.2199 +  }
  1.2200 +
  1.2201 +  // Test GSM personalization state.
  1.2202 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
  1.2203 +                      GECKO_CARDSTATE_NETWORK_LOCKED);
  1.2204 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
  1.2205 +                      GECKO_CARDSTATE_CORPORATE_LOCKED);
  1.2206 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
  1.2207 +                      GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
  1.2208 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
  1.2209 +                      GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
  1.2210 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
  1.2211 +                      GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
  1.2212 +  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
  1.2213 +                      GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
  1.2214 +  testPersonalization(false, CARD_PERSOSUBSTATE_READY,
  1.2215 +                      GECKO_CARDSTATE_PERSONALIZATION_READY);
  1.2216 +
  1.2217 +  // Test CDMA personalization state.
  1.2218 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
  1.2219 +                      GECKO_CARDSTATE_NETWORK1_LOCKED);
  1.2220 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
  1.2221 +                      GECKO_CARDSTATE_NETWORK2_LOCKED);
  1.2222 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
  1.2223 +                      GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
  1.2224 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
  1.2225 +                      GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
  1.2226 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
  1.2227 +                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
  1.2228 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
  1.2229 +                      GECKO_CARDSTATE_RUIM_LOCKED);
  1.2230 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
  1.2231 +                      GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
  1.2232 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
  1.2233 +                      GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
  1.2234 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
  1.2235 +                      GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
  1.2236 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
  1.2237 +                      GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
  1.2238 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
  1.2239 +                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
  1.2240 +  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
  1.2241 +                      GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
  1.2242 +
  1.2243 +  run_next_test();
  1.2244 +});
  1.2245 +
  1.2246 +/**
  1.2247 + * Verify SIM app_state in _processICCStatus
  1.2248 + */
  1.2249 +add_test(function test_card_app_state() {
  1.2250 +  let worker = newUint8Worker();
  1.2251 +  let context = worker.ContextPool._contexts[0];
  1.2252 +  let ril = context.RIL;
  1.2253 +
  1.2254 +  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
  1.2255 +
  1.2256 +  function testCardAppState(cardAppState, geckoCardState) {
  1.2257 +    let iccStatus = {
  1.2258 +      cardState: CARD_STATE_PRESENT,
  1.2259 +      gsmUmtsSubscriptionAppIndex: 0,
  1.2260 +      apps: [
  1.2261 +      {
  1.2262 +        app_state: cardAppState
  1.2263 +      }],
  1.2264 +    };
  1.2265 +
  1.2266 +    ril._processICCStatus(iccStatus);
  1.2267 +    do_check_eq(ril.cardState, geckoCardState);
  1.2268 +  }
  1.2269 +
  1.2270 +  testCardAppState(CARD_APPSTATE_ILLEGAL,
  1.2271 +                   GECKO_CARDSTATE_ILLEGAL);
  1.2272 +  testCardAppState(CARD_APPSTATE_PIN,
  1.2273 +                   GECKO_CARDSTATE_PIN_REQUIRED);
  1.2274 +  testCardAppState(CARD_APPSTATE_PUK,
  1.2275 +                   GECKO_CARDSTATE_PUK_REQUIRED);
  1.2276 +  testCardAppState(CARD_APPSTATE_READY,
  1.2277 +                   GECKO_CARDSTATE_READY);
  1.2278 +  testCardAppState(CARD_APPSTATE_UNKNOWN,
  1.2279 +                   GECKO_CARDSTATE_UNKNOWN);
  1.2280 +  testCardAppState(CARD_APPSTATE_DETECTED,
  1.2281 +                   GECKO_CARDSTATE_UNKNOWN);
  1.2282 +
  1.2283 +  run_next_test();
  1.2284 +});
  1.2285 +
  1.2286 +/**
  1.2287 + * Verify permanent blocked for ICC.
  1.2288 + */
  1.2289 +add_test(function test_icc_permanent_blocked() {
  1.2290 +  let worker = newUint8Worker();
  1.2291 +  let context = worker.ContextPool._contexts[0];
  1.2292 +  let ril = context.RIL;
  1.2293 +
  1.2294 +  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
  1.2295 +
  1.2296 +  function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
  1.2297 +    let iccStatus = {
  1.2298 +      cardState: CARD_STATE_PRESENT,
  1.2299 +      gsmUmtsSubscriptionAppIndex: 0,
  1.2300 +      universalPINState: universalPINState,
  1.2301 +      apps: [
  1.2302 +      {
  1.2303 +        pin1_replaced: pin1_replaced,
  1.2304 +        pin1: pin1
  1.2305 +      }]
  1.2306 +    };
  1.2307 +
  1.2308 +    ril._processICCStatus(iccStatus);
  1.2309 +    do_check_eq(ril.cardState, GECKO_CARDSTATE_PERMANENT_BLOCKED);
  1.2310 +  }
  1.2311 +
  1.2312 +  testPermanentBlocked(1,
  1.2313 +                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
  1.2314 +                       CARD_PINSTATE_UNKNOWN);
  1.2315 +  testPermanentBlocked(1,
  1.2316 +                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
  1.2317 +                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
  1.2318 +  testPermanentBlocked(0,
  1.2319 +                       CARD_PINSTATE_UNKNOWN,
  1.2320 +                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
  1.2321 +
  1.2322 +  run_next_test();
  1.2323 +});
  1.2324 +
  1.2325 +/**
  1.2326 + * Verify iccSetCardLock - Facility Lock.
  1.2327 + */
  1.2328 +add_test(function test_set_icc_card_lock_facility_lock() {
  1.2329 +  let worker = newUint8Worker();
  1.2330 +  let context = worker.ContextPool._contexts[0];
  1.2331 +  let aid = "123456789";
  1.2332 +  let ril = context.RIL;
  1.2333 +  ril.aid = aid;
  1.2334 +  ril.v5Legacy = false;
  1.2335 +  let buf = context.Buf;
  1.2336 +
  1.2337 +  let GECKO_CARDLOCK_TO_FACILITIY_LOCK = {};
  1.2338 +  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
  1.2339 +  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
  1.2340 +
  1.2341 +  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
  1.2342 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_PIN] = "pin";
  1.2343 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_FDN] = "pin2";
  1.2344 +
  1.2345 +  const pin = "1234";
  1.2346 +  const pin2 = "4321";
  1.2347 +  let GECKO_CARDLOCK_TO_PASSWORD = {};
  1.2348 +  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_PIN] = pin;
  1.2349 +  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_FDN] = pin2;
  1.2350 +
  1.2351 +  const serviceClass = ICC_SERVICE_CLASS_VOICE |
  1.2352 +                       ICC_SERVICE_CLASS_DATA  |
  1.2353 +                       ICC_SERVICE_CLASS_FAX;
  1.2354 +
  1.2355 +  function do_test(aLock, aPassword, aEnabled) {
  1.2356 +    buf.sendParcel = function fakeSendParcel () {
  1.2357 +      // Request Type.
  1.2358 +      do_check_eq(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
  1.2359 +
  1.2360 +      // Token : we don't care
  1.2361 +      this.readInt32();
  1.2362 +
  1.2363 +      let parcel = this.readStringList();
  1.2364 +      do_check_eq(parcel.length, 5);
  1.2365 +      do_check_eq(parcel[0], GECKO_CARDLOCK_TO_FACILITIY_LOCK[aLock]);
  1.2366 +      do_check_eq(parcel[1], aEnabled ? "1" : "0");
  1.2367 +      do_check_eq(parcel[2], GECKO_CARDLOCK_TO_PASSWORD[aLock]);
  1.2368 +      do_check_eq(parcel[3], serviceClass.toString());
  1.2369 +      do_check_eq(parcel[4], aid);
  1.2370 +    };
  1.2371 +
  1.2372 +    let lock = {lockType: aLock,
  1.2373 +                enabled: aEnabled};
  1.2374 +    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
  1.2375 +
  1.2376 +    ril.iccSetCardLock(lock);
  1.2377 +  }
  1.2378 +
  1.2379 +  do_test(GECKO_CARDLOCK_PIN, pin, true);
  1.2380 +  do_test(GECKO_CARDLOCK_PIN, pin, false);
  1.2381 +  do_test(GECKO_CARDLOCK_FDN, pin2, true);
  1.2382 +  do_test(GECKO_CARDLOCK_FDN, pin2, false);
  1.2383 +
  1.2384 +  run_next_test();
  1.2385 +});
  1.2386 +
  1.2387 +/**
  1.2388 + * Verify iccUnlockCardLock.
  1.2389 + */
  1.2390 +add_test(function test_unlock_card_lock_corporateLocked() {
  1.2391 +  let worker = newUint8Worker();
  1.2392 +  let context = worker.ContextPool._contexts[0];
  1.2393 +  let ril = context.RIL;
  1.2394 +  let buf = context.Buf;
  1.2395 +  const pin = "12345678";
  1.2396 +  const puk = "12345678";
  1.2397 +
  1.2398 +  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
  1.2399 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK] = "pin";
  1.2400 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1] = "pin";
  1.2401 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2] = "pin";
  1.2402 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK] = "pin";
  1.2403 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK] = "pin";
  1.2404 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK] = "pin";
  1.2405 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK] = "pin";
  1.2406 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK] = "pin";
  1.2407 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK_PUK] = "puk";
  1.2408 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1_PUK] = "puk";
  1.2409 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2_PUK] = "puk";
  1.2410 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK_PUK] = "puk";
  1.2411 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK_PUK] = "puk";
  1.2412 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK_PUK] = "puk";
  1.2413 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK_PUK] = "puk";
  1.2414 +  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK_PUK] = "puk";
  1.2415 +
  1.2416 +  function do_test(aLock, aPassword) {
  1.2417 +    buf.sendParcel = function fakeSendParcel () {
  1.2418 +      // Request Type.
  1.2419 +      do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
  1.2420 +
  1.2421 +      // Token : we don't care
  1.2422 +      this.readInt32();
  1.2423 +
  1.2424 +      let lockType = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock];
  1.2425 +      // Lock Type
  1.2426 +      do_check_eq(this.readInt32(), lockType);
  1.2427 +
  1.2428 +      // Pin/Puk.
  1.2429 +      do_check_eq(this.readString(), aPassword);
  1.2430 +    };
  1.2431 +
  1.2432 +    let lock = {lockType: aLock};
  1.2433 +    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
  1.2434 +    ril.iccUnlockCardLock(lock);
  1.2435 +  }
  1.2436 +
  1.2437 +  do_test(GECKO_CARDLOCK_NCK, pin);
  1.2438 +  do_test(GECKO_CARDLOCK_NCK1, pin);
  1.2439 +  do_test(GECKO_CARDLOCK_NCK2, pin);
  1.2440 +  do_test(GECKO_CARDLOCK_HNCK, pin);
  1.2441 +  do_test(GECKO_CARDLOCK_CCK, pin);
  1.2442 +  do_test(GECKO_CARDLOCK_SPCK, pin);
  1.2443 +  do_test(GECKO_CARDLOCK_RCCK, pin);
  1.2444 +  do_test(GECKO_CARDLOCK_RSPCK, pin);
  1.2445 +  do_test(GECKO_CARDLOCK_NCK_PUK, puk);
  1.2446 +  do_test(GECKO_CARDLOCK_NCK1_PUK, puk);
  1.2447 +  do_test(GECKO_CARDLOCK_NCK2_PUK, puk);
  1.2448 +  do_test(GECKO_CARDLOCK_HNCK_PUK, puk);
  1.2449 +  do_test(GECKO_CARDLOCK_CCK_PUK, puk);
  1.2450 +  do_test(GECKO_CARDLOCK_SPCK_PUK, puk);
  1.2451 +  do_test(GECKO_CARDLOCK_RCCK_PUK, puk);
  1.2452 +  do_test(GECKO_CARDLOCK_RSPCK_PUK, puk);
  1.2453 +
  1.2454 +  run_next_test();
  1.2455 +});
  1.2456 +
  1.2457 +/**
  1.2458 + * Verify MCC and MNC parsing
  1.2459 + */
  1.2460 +add_test(function test_mcc_mnc_parsing() {
  1.2461 +  let worker = newUint8Worker();
  1.2462 +  let context = worker.ContextPool._contexts[0];
  1.2463 +  let helper = context.ICCUtilsHelper;
  1.2464 +
  1.2465 +  function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
  1.2466 +    let result = helper.parseMccMncFromImsi(imsi, mncLength);
  1.2467 +
  1.2468 +    if (!imsi) {
  1.2469 +      do_check_eq(result, null);
  1.2470 +      return;
  1.2471 +    }
  1.2472 +
  1.2473 +    do_check_eq(result.mcc, expectedMcc);
  1.2474 +    do_check_eq(result.mnc, expectedMnc);
  1.2475 +  }
  1.2476 +
  1.2477 +  // Test the imsi is null.
  1.2478 +  do_test(null, null, null, null);
  1.2479 +
  1.2480 +  // Test MCC is Taiwan
  1.2481 +  do_test("466923202422409", 0x02, "466", "92");
  1.2482 +  do_test("466923202422409", 0x03, "466", "923");
  1.2483 +  do_test("466923202422409", null, "466", "92");
  1.2484 +
  1.2485 +  // Test MCC is US
  1.2486 +  do_test("310260542718417", 0x02, "310", "26");
  1.2487 +  do_test("310260542718417", 0x03, "310", "260");
  1.2488 +  do_test("310260542718417", null, "310", "260");
  1.2489 +
  1.2490 +  run_next_test();
  1.2491 + });
  1.2492 +
  1.2493 + /**
  1.2494 +  * Verify reading EF_AD and parsing MCC/MNC
  1.2495 +  */
  1.2496 +add_test(function test_reading_ad_and_parsing_mcc_mnc() {
  1.2497 +  let worker = newUint8Worker();
  1.2498 +  let context = worker.ContextPool._contexts[0];
  1.2499 +  let record = context.SimRecordHelper;
  1.2500 +  let helper = context.GsmPDUHelper;
  1.2501 +  let ril    = context.RIL;
  1.2502 +  let buf    = context.Buf;
  1.2503 +  let io     = context.ICCIOHelper;
  1.2504 +
  1.2505 +  function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
  1.2506 +    ril.iccInfoPrivate.imsi = imsi;
  1.2507 +
  1.2508 +    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
  1.2509 +      let ad = [0x00, 0x00, 0x00];
  1.2510 +      if (mncLengthInEf) {
  1.2511 +        ad.push(mncLengthInEf);
  1.2512 +      }
  1.2513 +
  1.2514 +      // Write data size
  1.2515 +      buf.writeInt32(ad.length * 2);
  1.2516 +
  1.2517 +      // Write data
  1.2518 +      for (let i = 0; i < ad.length; i++) {
  1.2519 +        helper.writeHexOctet(ad[i]);
  1.2520 +      }
  1.2521 +
  1.2522 +      // Write string delimiter
  1.2523 +      buf.writeStringDelimiter(ad.length * 2);
  1.2524 +
  1.2525 +      if (options.callback) {
  1.2526 +        options.callback(options);
  1.2527 +      }
  1.2528 +    };
  1.2529 +
  1.2530 +    record.readAD();
  1.2531 +
  1.2532 +    do_check_eq(ril.iccInfo.mcc, expectedMcc);
  1.2533 +    do_check_eq(ril.iccInfo.mnc, expectedMnc);
  1.2534 +  }
  1.2535 +
  1.2536 +  do_test(undefined, "466923202422409", "466", "92" );
  1.2537 +  do_test(0x03,      "466923202422409", "466", "923");
  1.2538 +  do_test(undefined, "310260542718417", "310", "260");
  1.2539 +  do_test(0x02,      "310260542718417", "310", "26" );
  1.2540 +
  1.2541 +  run_next_test();
  1.2542 +});
  1.2543 +
  1.2544 +add_test(function test_reading_optional_efs() {
  1.2545 +  let worker = newUint8Worker();
  1.2546 +  let context = worker.ContextPool._contexts[0];
  1.2547 +  let record = context.SimRecordHelper;
  1.2548 +  let gsmPdu = context.GsmPDUHelper;
  1.2549 +  let ril    = context.RIL;
  1.2550 +  let buf    = context.Buf;
  1.2551 +  let io     = context.ICCIOHelper;
  1.2552 +
  1.2553 +  function buildSST(supportedEf) {
  1.2554 +    let sst = [];
  1.2555 +    let len = supportedEf.length;
  1.2556 +    for (let i = 0; i < len; i++) {
  1.2557 +      let index, bitmask, iccService;
  1.2558 +      if (ril.appType === CARD_APPTYPE_SIM) {
  1.2559 +        iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
  1.2560 +        iccService -= 1;
  1.2561 +        index = Math.floor(iccService / 4);
  1.2562 +        bitmask = 2 << ((iccService % 4) << 1);
  1.2563 +      } else if (ril.appType === CARD_APPTYPE_USIM){
  1.2564 +        iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
  1.2565 +        iccService -= 1;
  1.2566 +        index = Math.floor(iccService / 8);
  1.2567 +        bitmask = 1 << ((iccService % 8) << 0);
  1.2568 +      }
  1.2569 +
  1.2570 +      if (sst) {
  1.2571 +        sst[index] |= bitmask;
  1.2572 +      }
  1.2573 +    }
  1.2574 +    return sst;
  1.2575 +  }
  1.2576 +
  1.2577 +  ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
  1.2578 +    // Ignore updateCellBroadcastConfig after reading SST
  1.2579 +  };
  1.2580 +
  1.2581 +  function do_test(sst, supportedEf) {
  1.2582 +    // Clone supportedEf to local array for testing
  1.2583 +    let testEf = supportedEf.slice(0);
  1.2584 +
  1.2585 +    record.readMSISDN = function fakeReadMSISDN() {
  1.2586 +      testEf.splice(testEf.indexOf("MSISDN"), 1);
  1.2587 +    };
  1.2588 +
  1.2589 +    record.readMBDN = function fakeReadMBDN() {
  1.2590 +      testEf.splice(testEf.indexOf("MDN"), 1);
  1.2591 +    };
  1.2592 +
  1.2593 +    record.readMWIS = function fakeReadMWIS() {
  1.2594 +      testEf.splice(testEf.indexOf("MWIS"), 1);
  1.2595 +    };
  1.2596 +
  1.2597 +    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
  1.2598 +      // Write data size
  1.2599 +      buf.writeInt32(sst.length * 2);
  1.2600 +
  1.2601 +      // Write data
  1.2602 +      for (let i = 0; i < sst.length; i++) {
  1.2603 +         gsmPdu.writeHexOctet(sst[i] || 0);
  1.2604 +      }
  1.2605 +
  1.2606 +      // Write string delimiter
  1.2607 +      buf.writeStringDelimiter(sst.length * 2);
  1.2608 +
  1.2609 +      if (options.callback) {
  1.2610 +        options.callback(options);
  1.2611 +      }
  1.2612 +
  1.2613 +      if (testEf.length !== 0) {
  1.2614 +        do_print("Un-handled EF: " + JSON.stringify(testEf));
  1.2615 +        do_check_true(false);
  1.2616 +      }
  1.2617 +    };
  1.2618 +
  1.2619 +    record.readSST();
  1.2620 +  }
  1.2621 +
  1.2622 +  // TODO: Add all necessary optional EFs eventually
  1.2623 +  let supportedEf = ["MSISDN", "MDN", "MWIS"];
  1.2624 +  ril.appType = CARD_APPTYPE_SIM;
  1.2625 +  do_test(buildSST(supportedEf), supportedEf);
  1.2626 +  ril.appType = CARD_APPTYPE_USIM;
  1.2627 +  do_test(buildSST(supportedEf), supportedEf);
  1.2628 +
  1.2629 +  run_next_test();
  1.2630 +});
  1.2631 +
  1.2632 +/**
  1.2633 + * Verify fetchSimRecords.
  1.2634 + */
  1.2635 +add_test(function test_fetch_sim_recodes() {
  1.2636 +  let worker = newWorker();
  1.2637 +  let context = worker.ContextPool._contexts[0];
  1.2638 +  let RIL = context.RIL;
  1.2639 +  let iccRecord = context.ICCRecordHelper;
  1.2640 +  let simRecord = context.SimRecordHelper;
  1.2641 +
  1.2642 +  function testFetchSimRecordes(expectCalled) {
  1.2643 +    let ifCalled = [];
  1.2644 +
  1.2645 +    RIL.getIMSI = function() {
  1.2646 +      ifCalled.push("getIMSI");
  1.2647 +    };
  1.2648 +
  1.2649 +    simRecord.readAD = function() {
  1.2650 +      ifCalled.push("readAD");
  1.2651 +    };
  1.2652 +
  1.2653 +    simRecord.readSST = function() {
  1.2654 +      ifCalled.push("readSST");
  1.2655 +    };
  1.2656 +
  1.2657 +    simRecord.fetchSimRecords();
  1.2658 +
  1.2659 +    for (let i = 0; i < expectCalled.length; i++ ) {
  1.2660 +      if (ifCalled[i] != expectCalled[i]) {
  1.2661 +        do_print(expectCalled[i] + " is not called.");
  1.2662 +        do_check_true(false);
  1.2663 +      }
  1.2664 +    }
  1.2665 +  }
  1.2666 +
  1.2667 +  let expectCalled = ["getIMSI", "readAD", "readSST"];
  1.2668 +  testFetchSimRecordes(expectCalled);
  1.2669 +
  1.2670 +  run_next_test();
  1.2671 +});
  1.2672 +
  1.2673 +add_test(function test_fetch_icc_recodes() {
  1.2674 +  let worker = newWorker();
  1.2675 +  let context = worker.ContextPool._contexts[0];
  1.2676 +  let RIL = context.RIL;
  1.2677 +  let iccRecord = context.ICCRecordHelper;
  1.2678 +  let simRecord = context.SimRecordHelper;
  1.2679 +  let ruimRecord = context.RuimRecordHelper;
  1.2680 +  let fetchTag = 0x00;
  1.2681 +
  1.2682 +  simRecord.fetchSimRecords = function() {
  1.2683 +    fetchTag = 0x01;
  1.2684 +  };
  1.2685 +
  1.2686 +  ruimRecord.fetchRuimRecords = function() {
  1.2687 +    fetchTag = 0x02;
  1.2688 +  };
  1.2689 +
  1.2690 +  RIL.appType = CARD_APPTYPE_SIM;
  1.2691 +  iccRecord.fetchICCRecords();
  1.2692 +  do_check_eq(fetchTag, 0x01);
  1.2693 +
  1.2694 +  RIL.appType = CARD_APPTYPE_RUIM;
  1.2695 +  iccRecord.fetchICCRecords();
  1.2696 +  do_check_eq(fetchTag, 0x02);
  1.2697 +
  1.2698 +  RIL.appType = CARD_APPTYPE_USIM;
  1.2699 +  iccRecord.fetchICCRecords();
  1.2700 +  do_check_eq(fetchTag, 0x01);
  1.2701 +
  1.2702 +  run_next_test();
  1.2703 +});
  1.2704 +
  1.2705 +/**
  1.2706 + * Verify SimRecordHelper.readMWIS
  1.2707 + */
  1.2708 +add_test(function test_read_mwis() {
  1.2709 +  let worker = newUint8Worker();
  1.2710 +  let context = worker.ContextPool._contexts[0];
  1.2711 +  let helper = context.GsmPDUHelper;
  1.2712 +  let recordHelper = context.SimRecordHelper;
  1.2713 +  let buf    = context.Buf;
  1.2714 +  let io     = context.ICCIOHelper;
  1.2715 +  let mwisData;
  1.2716 +  let postedMessage;
  1.2717 +
  1.2718 +  worker.postMessage = function fakePostMessage(message) {
  1.2719 +    postedMessage = message;
  1.2720 +  };
  1.2721 +
  1.2722 +  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
  1.2723 +    if (mwisData) {
  1.2724 +      // Write data size
  1.2725 +      buf.writeInt32(mwisData.length * 2);
  1.2726 +
  1.2727 +      // Write MWIS
  1.2728 +      for (let i = 0; i < mwisData.length; i++) {
  1.2729 +        helper.writeHexOctet(mwisData[i]);
  1.2730 +      }
  1.2731 +
  1.2732 +      // Write string delimiter
  1.2733 +      buf.writeStringDelimiter(mwisData.length * 2);
  1.2734 +
  1.2735 +      options.recordSize = mwisData.length;
  1.2736 +      if (options.callback) {
  1.2737 +        options.callback(options);
  1.2738 +      }
  1.2739 +    } else {
  1.2740 +      do_print("mwisData[] is not set.");
  1.2741 +    }
  1.2742 +  };
  1.2743 +
  1.2744 +  function buildMwisData(isActive, msgCount) {
  1.2745 +    if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
  1.2746 +      msgCount = 0;
  1.2747 +    } else if (msgCount > 255) {
  1.2748 +      msgCount = 255;
  1.2749 +    }
  1.2750 +
  1.2751 +    mwisData =  [ (isActive) ? 0x01 : 0x00,
  1.2752 +                  msgCount,
  1.2753 +                  0xFF, 0xFF, 0xFF ];
  1.2754 +  }
  1.2755 +
  1.2756 +  function do_test(isActive, msgCount) {
  1.2757 +    buildMwisData(isActive, msgCount);
  1.2758 +    recordHelper.readMWIS();
  1.2759 +
  1.2760 +    do_check_eq("iccmwis", postedMessage.rilMessageType);
  1.2761 +    do_check_eq(isActive, postedMessage.mwi.active);
  1.2762 +    do_check_eq((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
  1.2763 +  }
  1.2764 +
  1.2765 +  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
  1.2766 +  do_test(true, 1);
  1.2767 +  do_test(true, 255);
  1.2768 +
  1.2769 +  do_test(false, 0);
  1.2770 +  do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
  1.2771 +
  1.2772 +  run_next_test();
  1.2773 +});
  1.2774 +
  1.2775 +/**
  1.2776 + * Verify SimRecordHelper.updateMWIS
  1.2777 + */
  1.2778 +add_test(function test_update_mwis() {
  1.2779 +  let worker = newUint8Worker();
  1.2780 +  let context = worker.ContextPool._contexts[0];
  1.2781 +  let pduHelper = context.GsmPDUHelper;
  1.2782 +  let ril = context.RIL;
  1.2783 +  ril.appType = CARD_APPTYPE_USIM;
  1.2784 +  ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
  1.2785 +  let recordHelper = context.SimRecordHelper;
  1.2786 +  let buf = context.Buf;
  1.2787 +  let ioHelper = context.ICCIOHelper;
  1.2788 +  let recordSize = ril.iccInfoPrivate.mwis.length;
  1.2789 +  let recordNum = 1;
  1.2790 +
  1.2791 +  ioHelper.updateLinearFixedEF = function(options) {
  1.2792 +    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
  1.2793 +    options.command = ICC_COMMAND_UPDATE_RECORD;
  1.2794 +    options.p1 = options.recordNumber;
  1.2795 +    options.p2 = READ_RECORD_ABSOLUTE_MODE;
  1.2796 +    options.p3 = recordSize;
  1.2797 +    ril.iccIO(options);
  1.2798 +  };
  1.2799 +
  1.2800 +  function do_test(isActive, count) {
  1.2801 +    let mwis = ril.iccInfoPrivate.mwis;
  1.2802 +    let isUpdated = false;
  1.2803 +
  1.2804 +    function buildMwisData() {
  1.2805 +      let result = mwis.slice(0);
  1.2806 +      result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
  1.2807 +      result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
  1.2808 +
  1.2809 +      return result;
  1.2810 +    }
  1.2811 +
  1.2812 +    buf.sendParcel = function() {
  1.2813 +      isUpdated = true;
  1.2814 +
  1.2815 +      // Request Type.
  1.2816 +      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
  1.2817 +
  1.2818 +      // Token : we don't care
  1.2819 +      this.readInt32();
  1.2820 +
  1.2821 +      // command.
  1.2822 +      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
  1.2823 +
  1.2824 +      // fileId.
  1.2825 +      do_check_eq(this.readInt32(), ICC_EF_MWIS);
  1.2826 +
  1.2827 +      // pathId.
  1.2828 +      do_check_eq(this.readString(),
  1.2829 +                  EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
  1.2830 +
  1.2831 +      // p1.
  1.2832 +      do_check_eq(this.readInt32(), recordNum);
  1.2833 +
  1.2834 +      // p2.
  1.2835 +      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
  1.2836 +
  1.2837 +      // p3.
  1.2838 +      do_check_eq(this.readInt32(), recordSize);
  1.2839 +
  1.2840 +      // data.
  1.2841 +      let strLen = this.readInt32();
  1.2842 +      do_check_eq(recordSize * 2, strLen);
  1.2843 +      let expectedMwis = buildMwisData();
  1.2844 +      for (let i = 0; i < recordSize; i++) {
  1.2845 +        do_check_eq(expectedMwis[i], pduHelper.readHexOctet());
  1.2846 +      }
  1.2847 +      this.readStringDelimiter(strLen);
  1.2848 +
  1.2849 +      // pin2.
  1.2850 +      do_check_eq(this.readString(), null);
  1.2851 +
  1.2852 +      if (!ril.v5Legacy) {
  1.2853 +        // AID. Ignore because it's from modem.
  1.2854 +        this.readInt32();
  1.2855 +      }
  1.2856 +    };
  1.2857 +
  1.2858 +    do_check_false(isUpdated);
  1.2859 +
  1.2860 +    recordHelper.updateMWIS({ active: isActive,
  1.2861 +                              msgCount: count });
  1.2862 +
  1.2863 +    do_check_true((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
  1.2864 +  }
  1.2865 +
  1.2866 +  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
  1.2867 +  do_test(true, 1);
  1.2868 +  do_test(true, 255);
  1.2869 +
  1.2870 +  do_test(false, 0);
  1.2871 +
  1.2872 +  // Test if Path ID is correct for SIM.
  1.2873 +  ril.appType = CARD_APPTYPE_SIM;
  1.2874 +  do_test(false, 0);
  1.2875 +
  1.2876 +  // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
  1.2877 +  // EF_MWIS is not loaded/available.
  1.2878 +  delete ril.iccInfoPrivate.mwis;
  1.2879 +  do_test(false, 0);
  1.2880 +
  1.2881 +  run_next_test();
  1.2882 +});
  1.2883 +
  1.2884 +/**
  1.2885 + * Verify the call flow of receiving Class 2 SMS stored in SIM:
  1.2886 + * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
  1.2887 + * 2. SimRecordHelper.readSMS().
  1.2888 + * 3. sendChromeMessage() with rilMessageType == "sms-received".
  1.2889 + */
  1.2890 +add_test(function test_read_new_sms_on_sim() {
  1.2891 +  // Instead of reusing newUint8Worker defined in this file,
  1.2892 +  // we define our own worker to fake the methods in WorkerBuffer dynamically.
  1.2893 +  function newSmsOnSimWorkerHelper() {
  1.2894 +    let _postedMessage;
  1.2895 +    let _worker = newWorker({
  1.2896 +      postRILMessage: function(data) {
  1.2897 +      },
  1.2898 +      postMessage: function(message) {
  1.2899 +        _postedMessage = message;
  1.2900 +      }
  1.2901 +    });
  1.2902 +
  1.2903 +    _worker.debug = do_print;
  1.2904 +
  1.2905 +    return {
  1.2906 +      get postedMessage() {
  1.2907 +        return _postedMessage;
  1.2908 +      },
  1.2909 +      get worker() {
  1.2910 +        return _worker;
  1.2911 +      },
  1.2912 +      fakeWokerBuffer: function() {
  1.2913 +        let context = _worker.ContextPool._contexts[0];
  1.2914 +        let index = 0; // index for read
  1.2915 +        let buf = [];
  1.2916 +        context.Buf.writeUint8 = function(value) {
  1.2917 +          buf.push(value);
  1.2918 +        };
  1.2919 +        context.Buf.readUint8 = function() {
  1.2920 +          return buf[index++];
  1.2921 +        };
  1.2922 +        context.Buf.seekIncoming = function(offset) {
  1.2923 +          index += offset;
  1.2924 +        };
  1.2925 +        context.Buf.getReadAvailable = function() {
  1.2926 +          return buf.length - index;
  1.2927 +        };
  1.2928 +      }
  1.2929 +    };
  1.2930 +  }
  1.2931 +
  1.2932 +  let workerHelper = newSmsOnSimWorkerHelper();
  1.2933 +  let worker = workerHelper.worker;
  1.2934 +  let context = worker.ContextPool._contexts[0];
  1.2935 +
  1.2936 +  context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
  1.2937 +      // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
  1.2938 +      let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
  1.2939 +                       // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
  1.2940 +                       // 1. Record length == 176 bytes.
  1.2941 +                       // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
  1.2942 +                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  1.2943 +                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  1.2944 +                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  1.2945 +                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
  1.2946 +
  1.2947 +      workerHelper.fakeWokerBuffer();
  1.2948 +
  1.2949 +      context.Buf.writeString(SimSmsPduHex);
  1.2950 +
  1.2951 +      options.recordSize = 176; // Record length is fixed to 176 bytes.
  1.2952 +      if (options.callback) {
  1.2953 +        options.callback(options);
  1.2954 +      }
  1.2955 +  };
  1.2956 +
  1.2957 +  function newSmsOnSimParcel() {
  1.2958 +    let data = new Uint8Array(4 + 4); // Int32List with 1 element.
  1.2959 +    let offset = 0;
  1.2960 +
  1.2961 +    function writeInt(value) {
  1.2962 +      data[offset++] = value & 0xFF;
  1.2963 +      data[offset++] = (value >>  8) & 0xFF;
  1.2964 +      data[offset++] = (value >> 16) & 0xFF;
  1.2965 +      data[offset++] = (value >> 24) & 0xFF;
  1.2966 +    }
  1.2967 +
  1.2968 +    writeInt(1); // Length of Int32List
  1.2969 +    writeInt(1); // RecordNum = 1.
  1.2970 +
  1.2971 +    return newIncomingParcel(-1,
  1.2972 +                             RESPONSE_TYPE_UNSOLICITED,
  1.2973 +                             UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
  1.2974 +                             data);
  1.2975 +  }
  1.2976 +
  1.2977 +  function do_test() {
  1.2978 +    worker.onRILMessage(0, newSmsOnSimParcel());
  1.2979 +
  1.2980 +    let postedMessage = workerHelper.postedMessage;
  1.2981 +
  1.2982 +    do_check_eq("sms-received", postedMessage.rilMessageType);
  1.2983 +    do_check_eq("+0123456789", postedMessage.SMSC);
  1.2984 +    do_check_eq("+9876543210", postedMessage.sender);
  1.2985 +    do_check_eq("How are you?", postedMessage.body);
  1.2986 +  }
  1.2987 +
  1.2988 +  do_test();
  1.2989 +
  1.2990 +  run_next_test();
  1.2991 +});
  1.2992 +
  1.2993 +// Test ICC_COMMAND_GET_RESPONSE with FCP template format.
  1.2994 +/**
  1.2995 + * Verify transparent structure with FCP template format.
  1.2996 + */
  1.2997 +add_test(function test_fcp_template_for_transparent_structure() {
  1.2998 +  let worker = newUint8Worker();
  1.2999 +  let context = worker.ContextPool._contexts[0];
  1.3000 +  let pduHelper = context.GsmPDUHelper;
  1.3001 +  let berHelper = context.BerTlvHelper;
  1.3002 +
  1.3003 +  let tag_test = [
  1.3004 +    0x62,
  1.3005 +    0x22,
  1.3006 +    0x82, 0x02, 0x41, 0x21,
  1.3007 +    0x83, 0x02, 0x2F, 0xE2,
  1.3008 +    0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
  1.3009 +    0x8A, 0x01, 0x05,
  1.3010 +    0x8B, 0x03, 0x2F, 0x06, 0x0B,
  1.3011 +    0x80, 0x02, 0x00, 0x0A,
  1.3012 +    0x88, 0x01, 0x10];
  1.3013 +
  1.3014 +  for (let i = 0; i < tag_test.length; i++) {
  1.3015 +    pduHelper.writeHexOctet(tag_test[i]);
  1.3016 +  }
  1.3017 +
  1.3018 +  let berTlv = berHelper.decode(tag_test.length);
  1.3019 +  let iter = Iterator(berTlv.value);
  1.3020 +  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
  1.3021 +  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_TRANSPARENT]);
  1.3022 +
  1.3023 +  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
  1.3024 +  do_check_eq(tlv.value.fileId, 0x2FE2);
  1.3025 +
  1.3026 +  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
  1.3027 +  do_check_eq(tlv.value.fileSizeData, 0x0A);
  1.3028 +
  1.3029 +  run_next_test();
  1.3030 +});
  1.3031 +
  1.3032 +/**
  1.3033 + * Verify linear fixed structure with FCP template format.
  1.3034 + */
  1.3035 +add_test(function test_fcp_template_for_linear_fixed_structure() {
  1.3036 +  let worker = newUint8Worker();
  1.3037 +  let context = worker.ContextPool._contexts[0];
  1.3038 +  let pduHelper = context.GsmPDUHelper;
  1.3039 +  let berHelper = context.BerTlvHelper;
  1.3040 +
  1.3041 +  let tag_test = [
  1.3042 +    0x62,
  1.3043 +    0x1E,
  1.3044 +    0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
  1.3045 +    0x83, 0x02, 0x6F, 0x40,
  1.3046 +    0xA5, 0x03, 0x92, 0x01, 0x00,
  1.3047 +    0x8A, 0x01, 0x07,
  1.3048 +    0x8B, 0x03, 0x6F, 0x06, 0x02,
  1.3049 +    0x80, 0x02, 0x00, 0x1A,
  1.3050 +    0x88, 0x00];
  1.3051 +
  1.3052 +  for (let i = 0; i < tag_test.length; i++) {
  1.3053 +    pduHelper.writeHexOctet(tag_test[i]);
  1.3054 +  }
  1.3055 +
  1.3056 +  let berTlv = berHelper.decode(tag_test.length);
  1.3057 +  let iter = Iterator(berTlv.value);
  1.3058 +  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
  1.3059 +  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED]);
  1.3060 +  do_check_eq(tlv.value.recordLength, 0x1A);
  1.3061 +  do_check_eq(tlv.value.numOfRecords, 0x01);
  1.3062 +
  1.3063 +  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
  1.3064 +  do_check_eq(tlv.value.fileId, 0x6F40);
  1.3065 +
  1.3066 +  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
  1.3067 +  do_check_eq(tlv.value.fileSizeData, 0x1A);
  1.3068 +
  1.3069 +  run_next_test();
  1.3070 +});
  1.3071 +
  1.3072 +add_test(function test_icc_io_get_response_for_transparent_structure() {
  1.3073 +  let worker = newUint8Worker();
  1.3074 +  let context = worker.ContextPool._contexts[0];
  1.3075 +  let buf = context.Buf;
  1.3076 +  let iccioHelper = context.ICCIOHelper;
  1.3077 +  let pduHelper = context.GsmPDUHelper;
  1.3078 +
  1.3079 +  let responseArray = [
  1.3080 +    // SIM response.
  1.3081 +    [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
  1.3082 +     0x02, 0x00, 0x00],
  1.3083 +    // USIM response.
  1.3084 +    [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
  1.3085 +     0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
  1.3086 +     0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
  1.3087 +  ];
  1.3088 +
  1.3089 +  for (let i = 0; i < responseArray.length; i++) {
  1.3090 +    let strLen = responseArray[i].length * 2;
  1.3091 +    buf.writeInt32(strLen);
  1.3092 +    for (let j = 0; j < responseArray[i].length; j++) {
  1.3093 +      pduHelper.writeHexOctet(responseArray[i][j]);
  1.3094 +    }
  1.3095 +    buf.writeStringDelimiter(strLen);
  1.3096 +
  1.3097 +    let options = {fileId: ICC_EF_ICCID,
  1.3098 +                   type: EF_TYPE_TRANSPARENT};
  1.3099 +    iccioHelper.processICCIOGetResponse(options);
  1.3100 +
  1.3101 +    do_check_eq(options.fileSize, 0x0A);
  1.3102 +  }
  1.3103 +
  1.3104 +  run_next_test();
  1.3105 +});
  1.3106 +
  1.3107 +add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
  1.3108 +  let worker = newUint8Worker();
  1.3109 +  let context = worker.ContextPool._contexts[0];
  1.3110 +  let buf = context.Buf;
  1.3111 +  let iccioHelper = context.ICCIOHelper;
  1.3112 +  let pduHelper = context.GsmPDUHelper;
  1.3113 +
  1.3114 +  let responseArray = [
  1.3115 +    // SIM response.
  1.3116 +    [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
  1.3117 +     0x02, 0x01, 0x1A],
  1.3118 +    // USIM response.
  1.3119 +    [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
  1.3120 +     0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
  1.3121 +     0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
  1.3122 +  ];
  1.3123 +
  1.3124 +  for (let i = 0; i < responseArray.length; i++) {
  1.3125 +    let strLen = responseArray[i].length * 2;
  1.3126 +    buf.writeInt32(strLen);
  1.3127 +    for (let j = 0; j < responseArray[i].length; j++) {
  1.3128 +      pduHelper.writeHexOctet(responseArray[i][j]);
  1.3129 +    }
  1.3130 +    buf.writeStringDelimiter(strLen);
  1.3131 +
  1.3132 +    let options = {fileId: ICC_EF_MSISDN,
  1.3133 +                   type: EF_TYPE_LINEAR_FIXED};
  1.3134 +    iccioHelper.processICCIOGetResponse(options);
  1.3135 +
  1.3136 +    do_check_eq(options.fileSize, 0x1A);
  1.3137 +    do_check_eq(options.recordSize, 0x1A);
  1.3138 +    do_check_eq(options.totalRecords, 0x01);
  1.3139 +  }
  1.3140 +
  1.3141 +  run_next_test();
  1.3142 +});
  1.3143 +
  1.3144 +/**
  1.3145 + * Verify reading EF_ICCID.
  1.3146 + */
  1.3147 +add_test(function test_handling_iccid() {
  1.3148 +  let worker = newUint8Worker();
  1.3149 +  let context = worker.ContextPool._contexts[0];
  1.3150 +  let record = context.ICCRecordHelper;
  1.3151 +  let helper = context.GsmPDUHelper;
  1.3152 +  let ril = context.RIL;
  1.3153 +  let buf = context.Buf;
  1.3154 +  let io = context.ICCIOHelper;
  1.3155 +
  1.3156 +  ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
  1.3157 +  };
  1.3158 +
  1.3159 +  function do_test(rawICCID, expectedICCID) {
  1.3160 +    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
  1.3161 +      // Write data size
  1.3162 +      buf.writeInt32(rawICCID.length);
  1.3163 +
  1.3164 +      // Write data
  1.3165 +      for (let i = 0; i < rawICCID.length; i += 2) {
  1.3166 +        helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
  1.3167 +      }
  1.3168 +
  1.3169 +      // Write string delimiter
  1.3170 +      buf.writeStringDelimiter(rawICCID.length);
  1.3171 +
  1.3172 +      if (options.callback) {
  1.3173 +        options.callback(options);
  1.3174 +      }
  1.3175 +    };
  1.3176 +
  1.3177 +    record.readICCID();
  1.3178 +
  1.3179 +    do_check_eq(ril.iccInfo.iccid, expectedICCID);
  1.3180 +  }
  1.3181 +
  1.3182 +  // Invalid char at high nibbile + low nibbile contains 0xF.
  1.3183 +  do_test("9868002E90909F001519", "89860020909");
  1.3184 +  // Invalid char at low nibbile.
  1.3185 +  do_test("986800E2909090001519", "8986002090909005191");
  1.3186 +  // Valid ICCID.
  1.3187 +  do_test("98101430121181157002", "89014103211118510720");
  1.3188 +
  1.3189 +  run_next_test();
  1.3190 +});

mercurial