/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this); function run_test() { run_next_test(); } /** * Verify reading EF_AD and parsing MCC/MNC */ add_test(function test_reading_ad_and_parsing_mcc_mnc() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) { ril.iccInfoPrivate.imsi = imsi; io.loadTransparentEF = function fakeLoadTransparentEF(options) { let ad = [0x00, 0x00, 0x00]; if (typeof mncLengthInEf === 'number') { ad.push(mncLengthInEf); } // Write data size buf.writeInt32(ad.length * 2); // Write data for (let i = 0; i < ad.length; i++) { helper.writeHexOctet(ad[i]); } // Write string delimiter buf.writeStringDelimiter(ad.length * 2); if (options.callback) { options.callback(options); } }; record.readAD(); equal(ril.iccInfo.mcc, expectedMcc); equal(ril.iccInfo.mnc, expectedMnc); } do_test(undefined, "466923202422409", "466", "92" ); do_test(0x00, "466923202422409", "466", "92" ); do_test(0x01, "466923202422409", "466", "92" ); do_test(0x02, "466923202422409", "466", "92" ); do_test(0x03, "466923202422409", "466", "923"); do_test(0x04, "466923202422409", "466", "92" ); do_test(0xff, "466923202422409", "466", "92" ); do_test(undefined, "310260542718417", "310", "260"); do_test(0x00, "310260542718417", "310", "260"); do_test(0x01, "310260542718417", "310", "260"); do_test(0x02, "310260542718417", "310", "26" ); do_test(0x03, "310260542718417", "310", "260"); do_test(0x04, "310260542718417", "310", "260"); do_test(0xff, "310260542718417", "310", "260"); run_next_test(); }); add_test(function test_reading_optional_efs() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let gsmPdu = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; function buildSST(supportedEf) { let sst = []; let len = supportedEf.length; for (let i = 0; i < len; i++) { let index, bitmask, iccService; if (ril.appType === CARD_APPTYPE_SIM) { iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]]; iccService -= 1; index = Math.floor(iccService / 4); bitmask = 2 << ((iccService % 4) << 1); } else if (ril.appType === CARD_APPTYPE_USIM){ iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]]; iccService -= 1; index = Math.floor(iccService / 8); bitmask = 1 << ((iccService % 8) << 0); } if (sst) { sst[index] |= bitmask; } } return sst; } ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() { // Ignore updateCellBroadcastConfig after reading SST }; function do_test(sst, supportedEf) { // Clone supportedEf to local array for testing let testEf = supportedEf.slice(0); record.readMSISDN = function fakeReadMSISDN() { testEf.splice(testEf.indexOf("MSISDN"), 1); }; record.readMBDN = function fakeReadMBDN() { testEf.splice(testEf.indexOf("MDN"), 1); }; record.readMWIS = function fakeReadMWIS() { testEf.splice(testEf.indexOf("MWIS"), 1); }; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(sst.length * 2); // Write data for (let i = 0; i < sst.length; i++) { gsmPdu.writeHexOctet(sst[i] || 0); } // Write string delimiter buf.writeStringDelimiter(sst.length * 2); if (options.callback) { options.callback(options); } if (testEf.length !== 0) { do_print("Un-handled EF: " + JSON.stringify(testEf)); ok(false); } }; record.readSST(); } // TODO: Add all necessary optional EFs eventually let supportedEf = ["MSISDN", "MDN", "MWIS"]; ril.appType = CARD_APPTYPE_SIM; do_test(buildSST(supportedEf), supportedEf); ril.appType = CARD_APPTYPE_USIM; do_test(buildSST(supportedEf), supportedEf); run_next_test(); }); /** * Verify fetchSimRecords. */ add_test(function test_fetch_sim_records() { let worker = newWorker(); let context = worker.ContextPool._contexts[0]; let RIL = context.RIL; let iccRecord = context.ICCRecordHelper; let simRecord = context.SimRecordHelper; function testFetchSimRecordes(expectCalled, expectCphsSuccess) { let ifCalled = []; RIL.getIMSI = function() { ifCalled.push("getIMSI"); }; simRecord.readAD = function() { ifCalled.push("readAD"); }; simRecord.readCphsInfo = function(onsuccess, onerror) { ifCalled.push("readCphsInfo"); if (expectCphsSuccess) { onsuccess(); } else { onerror(); } }; simRecord.readSST = function() { ifCalled.push("readSST"); }; simRecord.fetchSimRecords(); for (let i = 0; i < expectCalled.length; i++ ) { if (ifCalled[i] != expectCalled[i]) { do_print(expectCalled[i] + " is not called."); ok(false); } } } let expectCalled = ["getIMSI", "readAD", "readCphsInfo", "readSST"]; testFetchSimRecordes(expectCalled, true); testFetchSimRecordes(expectCalled, false); run_next_test(); }); /** * Verify SimRecordHelper.readMWIS */ add_test(function test_read_mwis() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let helper = context.GsmPDUHelper; let recordHelper = context.SimRecordHelper; let buf = context.Buf; let io = context.ICCIOHelper; let mwisData; let postedMessage; worker.postMessage = function fakePostMessage(message) { postedMessage = message; }; io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { if (mwisData) { // Write data size buf.writeInt32(mwisData.length * 2); // Write MWIS for (let i = 0; i < mwisData.length; i++) { helper.writeHexOctet(mwisData[i]); } // Write string delimiter buf.writeStringDelimiter(mwisData.length * 2); options.recordSize = mwisData.length; if (options.callback) { options.callback(options); } } else { do_print("mwisData[] is not set."); } }; function buildMwisData(isActive, msgCount) { if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) { msgCount = 0; } else if (msgCount > 255) { msgCount = 255; } mwisData = [ (isActive) ? 0x01 : 0x00, msgCount, 0xFF, 0xFF, 0xFF ]; } function do_test(isActive, msgCount) { buildMwisData(isActive, msgCount); recordHelper.readMWIS(); equal("iccmwis", postedMessage.rilMessageType); equal(isActive, postedMessage.mwi.active); equal((isActive) ? msgCount : 0, postedMessage.mwi.msgCount); } do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN); do_test(true, 1); do_test(true, 255); do_test(false, 0); do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount. run_next_test(); }); /** * Verify SimRecordHelper.updateMWIS */ add_test(function test_update_mwis() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let pduHelper = context.GsmPDUHelper; let ril = context.RIL; ril.appType = CARD_APPTYPE_USIM; ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00]; let recordHelper = context.SimRecordHelper; let buf = context.Buf; let ioHelper = context.ICCIOHelper; let recordSize = ril.iccInfoPrivate.mwis.length; let recordNum = 1; ioHelper.updateLinearFixedEF = function(options) { options.pathId = context.ICCFileHelper.getEFPath(options.fileId); options.command = ICC_COMMAND_UPDATE_RECORD; options.p1 = options.recordNumber; options.p2 = READ_RECORD_ABSOLUTE_MODE; options.p3 = recordSize; ril.iccIO(options); }; function do_test(isActive, count) { let mwis = ril.iccInfoPrivate.mwis; let isUpdated = false; function buildMwisData() { let result = mwis.slice(0); result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE); result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count; return result; } buf.sendParcel = function() { isUpdated = true; // Request Type. equal(this.readInt32(), REQUEST_SIM_IO); // Token : we don't care this.readInt32(); // command. equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD); // fileId. equal(this.readInt32(), ICC_EF_MWIS); // pathId. equal(this.readString(), EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM)); // p1. equal(this.readInt32(), recordNum); // p2. equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE); // p3. equal(this.readInt32(), recordSize); // data. let strLen = this.readInt32(); equal(recordSize * 2, strLen); let expectedMwis = buildMwisData(); for (let i = 0; i < recordSize; i++) { equal(expectedMwis[i], pduHelper.readHexOctet()); } this.readStringDelimiter(strLen); // pin2. equal(this.readString(), null); // AID. Ignore because it's from modem. this.readInt32(); }; ok(!isUpdated); recordHelper.updateMWIS({ active: isActive, msgCount: count }); ok((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated); } do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN); do_test(true, 1); do_test(true, 255); do_test(false, 0); // Test if Path ID is correct for SIM. ril.appType = CARD_APPTYPE_SIM; do_test(false, 0); // Test if loadLinearFixedEF() is not invoked in updateMWIS() when // EF_MWIS is not loaded/available. delete ril.iccInfoPrivate.mwis; do_test(false, 0); run_next_test(); }); /** * Verify the call flow of receiving Class 2 SMS stored in SIM: * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM. * 2. SimRecordHelper.readSMS(). * 3. sendChromeMessage() with rilMessageType == "sms-received". */ add_test(function test_read_new_sms_on_sim() { // Instead of reusing newUint8Worker defined in this file, // we define our own worker to fake the methods in WorkerBuffer dynamically. function newSmsOnSimWorkerHelper() { let _postedMessage; let _worker = newWorker({ postRILMessage: function(data) { }, postMessage: function(message) { _postedMessage = message; } }); _worker.debug = do_print; return { get postedMessage() { return _postedMessage; }, get worker() { return _worker; }, fakeWokerBuffer: function() { let context = _worker.ContextPool._contexts[0]; let index = 0; // index for read let buf = []; context.Buf.writeUint8 = function(value) { buf.push(value); }; context.Buf.readUint8 = function() { return buf[index++]; }; context.Buf.seekIncoming = function(offset) { index += offset; }; context.Buf.getReadAvailable = function() { return buf.length - index; }; } }; } let workerHelper = newSmsOnSimWorkerHelper(); let worker = workerHelper.worker; let context = worker.ContextPool._contexts[0]; context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you? let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07" // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102: // 1. Record length == 176 bytes. // 2. Any bytes in the record following the TPDU shall be filled with 'FF'. + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; workerHelper.fakeWokerBuffer(); context.Buf.writeString(SimSmsPduHex); options.recordSize = 176; // Record length is fixed to 176 bytes. if (options.callback) { options.callback(options); } }; function newSmsOnSimParcel() { let data = new Uint8Array(4 + 4); // Int32List with 1 element. let offset = 0; function writeInt(value) { data[offset++] = value & 0xFF; data[offset++] = (value >> 8) & 0xFF; data[offset++] = (value >> 16) & 0xFF; data[offset++] = (value >> 24) & 0xFF; } writeInt(1); // Length of Int32List writeInt(1); // RecordNum = 1. return newIncomingParcel(-1, RESPONSE_TYPE_UNSOLICITED, UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM, data); } function do_test() { worker.onRILMessage(0, newSmsOnSimParcel()); let postedMessage = workerHelper.postedMessage; equal("sms-received", postedMessage.rilMessageType); equal("+0123456789", postedMessage.SMSC); equal("+9876543210", postedMessage.sender); equal("How are you?", postedMessage.body); } do_test(); run_next_test(); }); /** * Verify the result of updateDisplayCondition after reading EF_SPDI | EF_SPN. */ add_test(function test_update_display_condition() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; function do_test_spdi() { // No EF_SPN, but having EF_SPDI. // It implies "ril.iccInfoPrivate.spnDisplayCondition = undefined;". io.loadTransparentEF = function fakeLoadTransparentEF(options) { // PLMN lists are : 234-136 and 466-92. let spdi = [0xA3, 0x0B, 0x80, 0x09, 0x32, 0x64, 0x31, 0x64, 0x26, 0x9F, 0xFF, 0xFF, 0xFF]; // Write data size. buf.writeInt32(spdi.length * 2); // Write data. for (let i = 0; i < spdi.length; i++) { helper.writeHexOctet(spdi[i]); } // Write string delimiter. buf.writeStringDelimiter(spdi.length * 2); if (options.callback) { options.callback(options); } }; record.readSPDI(); equal(ril.iccInfo.isDisplayNetworkNameRequired, true); equal(ril.iccInfo.isDisplaySpnRequired, false); } function do_test_spn(displayCondition, expectedPlmnNameDisplay, expectedSpnDisplay) { io.loadTransparentEF = function fakeLoadTransparentEF(options) { // "Android" as Service Provider Name. let spn = [0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64]; if (typeof displayCondition === 'number') { spn.unshift(displayCondition); } // Write data size. buf.writeInt32(spn.length * 2); // Write data. for (let i = 0; i < spn.length; i++) { helper.writeHexOctet(spn[i]); } // Write string delimiter. buf.writeStringDelimiter(spn.length * 2); if (options.callback) { options.callback(options); } }; record.readSPN(); equal(ril.iccInfo.isDisplayNetworkNameRequired, expectedPlmnNameDisplay); equal(ril.iccInfo.isDisplaySpnRequired, expectedSpnDisplay); } // Create empty operator object. ril.operator = {}; // Setup SIM MCC-MNC to 310-260 as home network. ril.iccInfo.mcc = 310; ril.iccInfo.mnc = 260; do_test_spdi(); // No network. do_test_spn(0x00, true, true); do_test_spn(0x01, true, true); do_test_spn(0x02, true, false); do_test_spn(0x03, true, false); // Home network. ril.operator.mcc = 310; ril.operator.mnc = 260; do_test_spn(0x00, false, true); do_test_spn(0x01, true, true); do_test_spn(0x02, false, true); do_test_spn(0x03, true, true); // Not HPLMN but in PLMN list. ril.iccInfoPrivate.SPDI = [{"mcc":"234","mnc":"136"},{"mcc":"466","mnc":"92"}]; ril.operator.mcc = 466; ril.operator.mnc = 92; do_test_spn(0x00, false, true); do_test_spn(0x01, true, true); do_test_spn(0x02, false, true); do_test_spn(0x03, true, true); ril.iccInfoPrivate.SPDI = null; // reset SPDI to null; // Non-Home network. ril.operator.mcc = 466; ril.operator.mnc = 01; do_test_spn(0x00, true, true); do_test_spn(0x01, true, true); do_test_spn(0x02, true, false); do_test_spn(0x03, true, false); run_next_test(); }); /** * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_BASIC */ add_test(function test_reading_img_basic() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [ {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06], iidf: [ [/* Header */ 0x05, 0x05, /* Image body */ 0x11, 0x33, 0x55, 0xfe]], expected: [ {width: 0x05, height: 0x05, codingScheme: ICC_IMG_CODING_SCHEME_BASIC, body: [0x11, 0x33, 0x55, 0xfe]}]}, {img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06, /* Padding */ 0xff, 0xff], iidf: [ [/* Header */ 0x05, 0x05, /* Image body */ 0x11, 0x33, 0x55, 0xfe]], expected: [ {width: 0x05, height: 0x05, codingScheme: ICC_IMG_CODING_SCHEME_BASIC, body: [0x11, 0x33, 0x55, 0xfe]}]}, {img: [0x02, 0x10, 0x01, 0x11, 0x4f, 0x04, 0x00, 0x05, 0x00, 0x04, 0x10, 0x01, 0x11, 0x4f, 0x05, 0x00, 0x05, 0x00, 0x04], iidf: [ [/* Data offset */ 0xff, 0xff, 0xff, 0xff, 0xff, /* Header */ 0x10, 0x01, /* Image body */ 0x11, 0x99, /* Trailing data */ 0xff, 0xff, 0xff], [/* Data offset */ 0xff, 0xff, 0xff, 0xff, 0xff, /* Header */ 0x10, 0x01, /* Image body */ 0x99, 0x11]], expected: [ {width: 0x10, height: 0x01, codingScheme: ICC_IMG_CODING_SCHEME_BASIC, body: [0x11, 0x99]}, {width: 0x10, height: 0x01, codingScheme: ICC_IMG_CODING_SCHEME_BASIC, body: [0x99, 0x11]}]}, {img: [0x01, 0x28, 0x20, 0x11, 0x4f, 0xac, 0x00, 0x0b, 0x00, 0xa2], iidf: [ [/* Data offset */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Header */ 0x28, 0x20, /* Image body */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]], expected: [ {width: 0x28, height: 0x20, codingScheme: ICC_IMG_CODING_SCHEME_BASIC, body: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f]}]}]; function do_test(img, iidf, expected) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img.length * 2); // Write data for (let i = 0; i < img.length; i++) { helper.writeHexOctet(img[i]); } // Write string delimiter buf.writeStringDelimiter(img.length * 2); if (options.callback) { options.callback(options); } }; let instanceIndex = 0; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(iidf[instanceIndex].length * 2); // Write data for (let i = 0; i < iidf[instanceIndex].length; i++) { helper.writeHexOctet(iidf[instanceIndex][i]); } // Write string delimiter buf.writeStringDelimiter(iidf[instanceIndex].length * 2); instanceIndex++; if (options.callback) { options.callback(options); } }; let onsuccess = function(icons) { equal(icons.length, expected.length); for (let i = 0; i < icons.length; i++) { let icon = icons[i]; let exp = expected[i]; equal(icon.width, exp.width); equal(icon.height, exp.height); equal(icon.codingScheme, exp.codingScheme); equal(icon.body.length, exp.body.length); for (let j = 0; j < icon.body.length; j++) { equal(icon.body[j], exp.body[j]); } } }; record.readIMG(0, onsuccess); } for (let i = 0; i< test_data.length; i++) { do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected); } run_next_test(); }); /** * Verify reading EF_IMG and EF_IIDF with the case data length is not enough */ add_test(function test_reading_img_length_error() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [ {/* Offset length not enough, should be 4. */ img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x04, 0x00, 0x06], iidf: [0xff, 0xff, 0xff, // Offset. 0x05, 0x05, 0x11, 0x22, 0x33, 0xfe]}, {/* iidf data length not enough, should be 6. */ img: [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06], iidf: [0x05, 0x05, 0x11, 0x22, 0x33]}]; function do_test(img, iidf) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img.length * 2); // Write data for (let i = 0; i < img.length; i++) { helper.writeHexOctet(img[i]); } // Write string delimiter buf.writeStringDelimiter(img.length * 2); if (options.callback) { options.callback(options); } }; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(iidf.length * 2); // Write data for (let i = 0; i < iidf.length; i++) { helper.writeHexOctet(iidf[i]); } // Write string delimiter buf.writeStringDelimiter(iidf.length * 2); if (options.callback) { options.callback(options); } }; let onsuccess = function() { do_print("onsuccess shouldn't be called."); ok(false); }; let onerror = function() { do_print("onerror called as expected."); ok(true); }; record.readIMG(0, onsuccess, onerror); } for (let i = 0; i < test_data.length; i++) { do_test(test_data[i].img, test_data[i].iidf); } run_next_test(); }); /** * Verify reading EF_IMG and EF_IIDF with an invalid fileId */ add_test(function test_reading_img_invalid_fileId() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; // Test invalid fileId: 0x5f00. let img_test = [0x01, 0x05, 0x05, 0x11, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x06]; let iidf_test = [0x05, 0x05, 0x11, 0x22, 0x33, 0xfe]; io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img_test.length * 2); // Write data for (let i = 0; i < img_test.length; i++) { helper.writeHexOctet(img_test[i]); } // Write string delimiter buf.writeStringDelimiter(img_test.length * 2); if (options.callback) { options.callback(options); } }; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(iidf_test.length * 2); // Write data for (let i = 0; i < iidf_test.length; i++) { helper.writeHexOctet(iidf_test[i]); } // Write string delimiter buf.writeStringDelimiter(iidf_test.length * 2); if (options.callback) { options.callback(options); } }; let onsuccess = function() { do_print("onsuccess shouldn't be called."); ok(false); }; let onerror = function() { do_print("onerror called as expected."); ok(true); }; record.readIMG(0, onsuccess, onerror); run_next_test(); }); /** * Verify reading EF_IMG with a wrong record length */ add_test(function test_reading_img_wrong_record_length() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [ [0x01, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00], [0x02, 0x05, 0x05, 0x11, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06]]; function do_test(img) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img.length * 2); // Write data for (let i = 0; i < img.length; i++) { helper.writeHexOctet(img[i]); } // Write string delimiter buf.writeStringDelimiter(img.length * 2); if (options.callback) { options.callback(options); } }; let onsuccess = function() { do_print("onsuccess shouldn't be called."); ok(false); }; let onerror = function() { do_print("onerror called as expected."); ok(true); }; record.readIMG(0, onsuccess, onerror); } for (let i = 0; i < test_data.length; i++) { do_test(test_data[i]); } run_next_test(); }); /** * Verify reading EF_IMG and EF_IIDF with ICC_IMG_CODING_SCHEME_COLOR */ add_test(function test_reading_img_color() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [ {img: [0x01, 0x05, 0x05, 0x21, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13], iidf: [ [/* Header */ 0x05, 0x05, 0x03, 0x08, 0x00, 0x13, /* Image body */ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, /* Clut entries */ 0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22, 0x30, 0x31, 0x32, 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x60, 0x61, 0x62, 0x70, 0x71, 0x72]], expected: [ {width: 0x05, height: 0x05, codingScheme: ICC_IMG_CODING_SCHEME_COLOR, bitsPerImgPoint: 0x03, numOfClutEntries: 0x08, body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0], clut: [0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22, 0x30, 0x31, 0x32, 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x60, 0x61, 0x62, 0x70, 0x71, 0x72]}]}, {img: [0x02, 0x01, 0x06, 0x21, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01, 0x06, 0x21, 0x4f, 0x44, 0x00, 0x02, 0x00, 0x08], iidf: [ [/* Data offset */ 0xff, 0xff, /* Header */ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d, /* Image body */ 0x40, 0x50, /* Clut offset */ 0xaa, 0xbb, 0xcc, /* Clut entries */ 0x01, 0x03, 0x05, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65], [/* Data offset */ 0xff, 0xff, /* Header */ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d, /* Image body */ 0x4f, 0x5f, /* Clut offset */ 0xaa, 0xbb, 0xcc, /* Clut entries */ 0x11, 0x13, 0x15, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]], expected: [ {width: 0x01, height: 0x06, codingScheme: ICC_IMG_CODING_SCHEME_COLOR, bitsPerImgPoint: 0x02, numOfClutEntries: 0x04, body: [0x40, 0x50], clut: [0x01, 0x03, 0x05, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]}, {width: 0x01, height: 0x06, codingScheme: ICC_IMG_CODING_SCHEME_COLOR, bitsPerImgPoint: 0x02, numOfClutEntries: 0x04, body: [0x4f, 0x5f], clut: [0x11, 0x13, 0x15, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]}]}]; function do_test(img, iidf, expected) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img.length * 2); // Write data for (let i = 0; i < img.length; i++) { helper.writeHexOctet(img[i]); } // Write string delimiter buf.writeStringDelimiter(img.length * 2); if (options.callback) { options.callback(options); } }; let instanceIndex = 0; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(iidf[instanceIndex].length * 2); // Write data for (let i = 0; i < iidf[instanceIndex].length; i++) { helper.writeHexOctet(iidf[instanceIndex][i]); } // Write string delimiter buf.writeStringDelimiter(iidf[instanceIndex].length * 2); instanceIndex++; if (options.callback) { options.callback(options); } }; let onsuccess = function(icons) { equal(icons.length, expected.length); for (let i = 0; i < icons.length; i++) { let icon = icons[i]; let exp = expected[i]; equal(icon.width, exp.width); equal(icon.height, exp.height); equal(icon.codingScheme, exp.codingScheme); equal(icon.body.length, exp.body.length); for (let j = 0; j < icon.body.length; j++) { equal(icon.body[j], exp.body[j]); } equal(icon.clut.length, exp.clut.length); for (let j = 0; j < icon.clut.length; j++) { equal(icon.clut[j], exp.clut[j]); } } }; record.readIMG(0, onsuccess); } for (let i = 0; i< test_data.length; i++) { do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected); } run_next_test(); }); /** * Verify reading EF_IMG and EF_IIDF with * ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY */ add_test(function test_reading_img_color() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let helper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [ {img: [0x01, 0x05, 0x05, 0x22, 0x4f, 0x11, 0x00, 0x00, 0x00, 0x13], iidf: [ [/* Header */ 0x05, 0x05, 0x03, 0x08, 0x00, 0x13, /* Image body */ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, /* Clut entries */ 0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22, 0x30, 0x31, 0x32, 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x60, 0x61, 0x62, 0x70, 0x71, 0x72]], expected: [ {width: 0x05, height: 0x05, codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY, bitsPerImgPoint: 0x03, numOfClutEntries: 0x08, body: [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0], clut: [0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22, 0x30, 0x31, 0x32, 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x60, 0x61, 0x62, 0x70, 0x71, 0x72]}]}, {img: [0x02, 0x01, 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08, 0x01, 0x06, 0x22, 0x4f, 0x33, 0x00, 0x02, 0x00, 0x08], iidf: [ [/* Data offset */ 0xff, 0xff, /* Header */ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d, /* Image body */ 0x40, 0x50, /* Clut offset */ 0x0a, 0x0b, 0x0c, /* Clut entries */ 0x01, 0x03, 0x05, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65], [/* Data offset */ 0xff, 0xff, /* Header */ 0x01, 0x06, 0x02, 0x04, 0x00, 0x0d, /* Image body */ 0x4f, 0x5f, /* Clut offset */ 0x0a, 0x0b, 0x0c, /* Clut entries */ 0x11, 0x13, 0x15, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]], expected: [ {width: 0x01, height: 0x06, codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY, bitsPerImgPoint: 0x02, numOfClutEntries: 0x04, body: [0x40, 0x50], clut: [0x01, 0x03, 0x05, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]}, {width: 0x01, height: 0x06, codingScheme: ICC_IMG_CODING_SCHEME_COLOR_TRANSPARENCY, bitsPerImgPoint: 0x02, numOfClutEntries: 0x04, body: [0x4f, 0x5f], clut: [0x11, 0x13, 0x15, 0x21, 0x23, 0x25, 0x41, 0x43, 0x45, 0x61, 0x63, 0x65]}]}]; function do_test(img, iidf, expected) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size buf.writeInt32(img.length * 2); // Write data for (let i = 0; i < img.length; i++) { helper.writeHexOctet(img[i]); } // Write string delimiter buf.writeStringDelimiter(img.length * 2); if (options.callback) { options.callback(options); } }; let instanceIndex = 0; io.loadTransparentEF = function fakeLoadTransparentEF(options) { // Write data size buf.writeInt32(iidf[instanceIndex].length * 2); // Write data for (let i = 0; i < iidf[instanceIndex].length; i++) { helper.writeHexOctet(iidf[instanceIndex][i]); } // Write string delimiter buf.writeStringDelimiter(iidf[instanceIndex].length * 2); instanceIndex++; if (options.callback) { options.callback(options); } }; let onsuccess = function(icons) { equal(icons.length, expected.length); for (let i = 0; i < icons.length; i++) { let icon = icons[i]; let exp = expected[i]; equal(icon.width, exp.width); equal(icon.height, exp.height); equal(icon.codingScheme, exp.codingScheme); equal(icon.body.length, exp.body.length); for (let j = 0; j < icon.body.length; j++) { equal(icon.body[j], exp.body[j]); } equal(icon.clut.length, exp.clut.length); for (let j = 0; j < icon.clut.length; j++) { equal(icon.clut[j], exp.clut[j]); } } }; record.readIMG(0, onsuccess); } for (let i = 0; i< test_data.length; i++) { do_test(test_data[i].img, test_data[i].iidf, test_data[i].expected); } run_next_test(); }); /** * Verify SimRecordHelper.readCphsInfo */ add_test(function test_read_cphs_info() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let RIL = context.RIL; let pduHelper = context.GsmPDUHelper; let recordHelper = context.SimRecordHelper; let buf = context.Buf; let io = context.ICCIOHelper; let cphsPDU = new Uint8Array(3); io.loadTransparentEF = function(options) { if (cphsPDU) { // Write data size buf.writeInt32(cphsPDU.length * 2); // Write CPHS INFO for (let i = 0; i < cphsPDU.length; i++) { pduHelper.writeHexOctet(cphsPDU[i]); } // Write string delimiter buf.writeStringDelimiter(cphsPDU.length * 2); if (options.callback) { options.callback(options); } } else { do_print("cphsPDU[] is not set."); } }; function do_test(cphsInfo, cphsSt) { let onsuccess = false; let onerror = false; delete RIL.iccInfoPrivate.cphsSt; cphsPDU.set(cphsInfo); recordHelper.readCphsInfo(() => { onsuccess = true; }, () => { onerror = true; }); ok((cphsSt) ? onsuccess : onerror); ok(!((cphsSt) ? onerror : onsuccess)); if (cphsSt) { equal(RIL.iccInfoPrivate.cphsSt.length, cphsSt.length); for (let i = 0; i < cphsSt.length; i++) { equal(RIL.iccInfoPrivate.cphsSt[i], cphsSt[i]); } } else { equal(RIL.iccInfoPrivate.cphsSt, cphsSt); } } do_test([ 0x01, // Phase 1 0xFF, // All available & activated 0x03 // All available & activated ], [ 0x3F, // All services except ONSF(bit 8-7) are available and activated. 0x00 // INFO_NUM shall not be available & activated. ]); do_test([ 0x02, // Phase 2 0xFF, // All available & activated 0x03 // All available & activated ], [ 0xF3, // All services except ONSF are available and activated. 0x03 // INFO_NUM shall not be available & activated. ]); do_test([ 0x03, // Phase 3 0xFF, // All available & activated 0x03 // All available & activated ], undefined); // RIL.iccInfoPrivate.cphsSt shall be remained as 'undefined'. run_next_test(); }); /** * Verify SimRecordHelper.readMBDN/SimRecordHelper.readCphsMBN */ add_test(function test_read_voicemail_number() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let RIL = context.RIL; let pduHelper = context.GsmPDUHelper; let recordHelper = context.SimRecordHelper; let buf = context.Buf; let io = context.ICCIOHelper; let postedMessage; worker.postMessage = function(message) { postedMessage = message; }; io.loadLinearFixedEF = function(options) { let mbnData = [ 0x56, 0x6F, 0x69, 0x63, 0x65, 0x6D, 0x61, 0x69, 0x6C, 0xFF, // Alpha Identifier: Voicemail 0x03, // Length of BCD number: 3 0x80, // TOA: Unknown 0x11, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Dialing Number: 111 0xFF, // Capability/Configuration Record Identifier 0xFF // Extension Record Identifier ]; // Write data size buf.writeInt32(mbnData.length * 2); // Write MBN for (let i = 0; i < mbnData.length; i++) { pduHelper.writeHexOctet(mbnData[i]); } // Write string delimiter buf.writeStringDelimiter(mbnData.length * 2); options.recordSize = mbnData.length; if (options.callback) { options.callback(options); } }; function do_test(funcName, msgCount) { postedMessage = null; delete RIL.iccInfoPrivate.mbdn; recordHelper[funcName](); equal("iccmbdn", postedMessage.rilMessageType); equal("Voicemail", postedMessage.alphaId); equal("111", postedMessage.number); } do_test("readMBDN"); do_test("readCphsMBN"); run_next_test(); }); /** * Verify the recovery from SimRecordHelper.readCphsMBN() if MBDN is not valid * or is empty after SimRecordHelper.readMBDN(). */ add_test(function test_read_mbdn_recovered_from_cphs_mbn() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let RIL = context.RIL; let pduHelper = context.GsmPDUHelper; let recordHelper = context.SimRecordHelper; let iccUtilsHelper = context.ICCUtilsHelper; let buf = context.Buf; let io = context.ICCIOHelper; io.loadLinearFixedEF = function(options) { let mbnData = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]; // Write data size buf.writeInt32(mbnData.length * 2); // Write MBN for (let i = 0; i < mbnData.length; i++) { pduHelper.writeHexOctet(mbnData[i]); } // Write string delimiter buf.writeStringDelimiter(mbnData.length * 2); options.recordSize = mbnData.length; if (options.callback) { options.callback(options); } }; iccUtilsHelper.isCphsServiceAvailable = function(geckoService) { return geckoService == "MBN"; }; let isRecovered = false; recordHelper.readCphsMBN = function(onComplete) { isRecovered = true; }; recordHelper.readMBDN(); equal(RIL.iccInfoPrivate.mbdn, undefined); ok(isRecovered); run_next_test(); }); /** * Verify reading EF_PNN with different coding scheme. */ add_test(function test_pnn_with_different_coding_scheme() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let pduHelper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [{ // Cell Broadcast data coding scheme - "Test1" pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03], expectedResult: "Test1" },{ // UCS2 with 0x80 - "Test1" pnn: [0x43, 0x0C, 0x90, 0x80, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31], expectedResult: "Test1" },{ // UCS2 with 0x81 - "Mozilla\u694a" pnn: [0x43, 0x0E, 0x90, 0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff], expectedResult: "Mozilla\u694a" },{ // UCS2 with 0x82 - "Mozilla\u694a" pnn: [0x43, 0x0F, 0x90, 0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff], expectedResult: "Mozilla\u694a" }]; function do_test_pnn(pnn, expectedResult) { io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { // Write data size. buf.writeInt32(pnn.length * 2); // Write data. for (let i = 0; i < pnn.length; i++) { pduHelper.writeHexOctet(pnn[i]); } // Write string delimiter. buf.writeStringDelimiter(pnn.length * 2); if (options.callback) { options.callback(options); } }; record.readPNN(); equal(ril.iccInfoPrivate.PNN[0].fullName, expectedResult); // Reset PNN info for next test ril.iccInfoPrivate.PNN = null; } ril.appType = CARD_APPTYPE_SIM; for (let i = 0; i < test_data.length; i++) { do_test_pnn(test_data[i].pnn, test_data[i].expectedResult); } run_next_test(); }); /** * Verify reading EF_PNN with different content. */ add_test(function test_pnn_with_different_content() { let worker = newUint8Worker(); let context = worker.ContextPool._contexts[0]; let record = context.SimRecordHelper; let pduHelper = context.GsmPDUHelper; let ril = context.RIL; let buf = context.Buf; let io = context.ICCIOHelper; let test_data = [{ // [0]: {"fullName":"Test1","shortName":"Test1"} pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03, 0x45, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x1E, 0x03], expectedResult: {"fullName": "Test1","shortName": "Test1"} },{ // [1]: {"fullName":"Test2"} pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x2E, 0x03], expectedResult: {"fullName": "Test2"} },{ // [2]: undefined pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], },{ // [3]: {"fullName": "Test4"} pnn: [0x43, 0x06, 0x85, 0xD4, 0xF2, 0x9C, 0x4E, 0x03], expectedResult: {"fullName": "Test4"} },{ // [4]: undefined pnn: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], }]; function do_test_pnn() { ril.iccIO = function fakeIccIO(options) { let index = options.p1 - 1; let pnn = test_data[index].pnn; // Write data size. buf.writeInt32(pnn.length * 2); // Write data. for (let i = 0; i < pnn.length; i++) { pduHelper.writeHexOctet(pnn[i]); } // Write string delimiter. buf.writeStringDelimiter(pnn.length * 2); if (options.callback) { options.callback(options); } }; io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) { options.p1 = 1; options.totalRecords = test_data.length; ril.iccIO(options); }; record.readPNN(); equal(test_data.length, ril.iccInfoPrivate.PNN.length); for (let i = 0; i < test_data.length; i++) { if (test_data[i].expectedResult) { equal(test_data[i].expectedResult.fullName, ril.iccInfoPrivate.PNN[i].fullName); equal(test_data[i].expectedResult.shortName, ril.iccInfoPrivate.PNN[i].shortName); } else { equal(test_data[i].expectedResult, ril.iccInfoPrivate.PNN[i]); } } } ril.appType = CARD_APPTYPE_SIM; do_test_pnn(); run_next_test(); });