Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
6 const ESCAPE = "\uffff";
7 const RESCTL = "\ufffe";
9 function run_test() {
10 run_next_test();
11 }
13 /**
14 * Verify receiving SMS-DELIVERY messages
15 */
17 function hexToNibble(nibble) {
18 nibble &= 0x0f;
19 if (nibble < 10) {
20 nibble += 48; // ASCII '0'
21 } else {
22 nibble += 55; // ASCII 'A'
23 }
24 return nibble;
25 }
27 function pduToParcelData(pdu) {
28 let dataLength = 4 + pdu.length * 4 + 4;
29 let data = new Uint8Array(dataLength);
30 let offset = 0;
32 // String length
33 data[offset++] = pdu.length & 0xFF;
34 data[offset++] = (pdu.length >> 8) & 0xFF;
35 data[offset++] = (pdu.length >> 16) & 0xFF;
36 data[offset++] = (pdu.length >> 24) & 0xFF;
38 // PDU data
39 for (let i = 0; i < pdu.length; i++) {
40 let hi = (pdu[i] >>> 4) & 0x0F;
41 let lo = pdu[i] & 0x0F;
43 data[offset++] = hexToNibble(hi);
44 data[offset++] = 0;
45 data[offset++] = hexToNibble(lo);
46 data[offset++] = 0;
47 }
49 // String delimitor
50 data[offset++] = 0;
51 data[offset++] = 0;
52 data[offset++] = 0;
53 data[offset++] = 0;
55 return data;
56 }
58 function compose7bitPdu(lst, sst, data, septets) {
59 if ((lst == 0) && (sst == 0)) {
60 return [0x00, // SMSC
61 PDU_MTI_SMS_DELIVER, // firstOctet
62 1, 0x00, 0, // senderAddress
63 0x00, // protocolIdentifier
64 PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
65 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
66 septets] // userDataLength
67 .concat(data);
68 }
70 return [0x00, // SMSC
71 PDU_MTI_SMS_DELIVER | PDU_UDHI, // firstOctet
72 1, 0x00, 0, // senderAddress
73 0x00, // protocolIdentifier
74 PDU_DCS_MSG_CODING_7BITS_ALPHABET, // dataCodingScheme
75 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
76 8 + septets, // userDataLength
77 6, // user data header length
78 PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT, 1, lst, // PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT
79 PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT, 1, sst] // PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT
80 .concat(data);
81 }
83 function composeUcs2Pdu(rawBytes) {
84 return [0x00, // SMSC
85 PDU_MTI_SMS_DELIVER, // firstOctet
86 1, 0x00, 0, // senderAddress
87 0x00, // protocolIdentifier
88 PDU_DCS_MSG_CODING_16BITS_ALPHABET, // dataCodingScheme
89 0, 0, 0, 0, 0, 0, 0, // y m d h m s tz
90 rawBytes.length] // userDataLength
91 .concat(rawBytes);
92 }
94 function newSmsParcel(pdu) {
95 return newIncomingParcel(-1,
96 RESPONSE_TYPE_UNSOLICITED,
97 UNSOLICITED_RESPONSE_NEW_SMS,
98 pduToParcelData(pdu));
99 }
101 function removeSpecialChar(str, needle) {
102 for (let i = 0; i < needle.length; i++) {
103 let pos;
104 while ((pos = str.indexOf(needle[i])) >= 0) {
105 str = str.substring(0, pos) + str.substring(pos + 1);
106 }
107 }
108 return str;
109 }
111 function newWriteHexOctetAsUint8Worker() {
112 let worker = newWorker({
113 postRILMessage: function(data) {
114 // Do nothing
115 },
116 postMessage: function(message) {
117 // Do nothing
118 }
119 });
121 let context = worker.ContextPool._contexts[0];
122 context.GsmPDUHelper.writeHexOctet = function(value) {
123 context.Buf.writeUint8(value);
124 };
126 return worker;
127 }
129 function add_test_receiving_sms(expected, pdu) {
130 add_test(function test_receiving_sms() {
131 let worker = newWorker({
132 postRILMessage: function(data) {
133 // Do nothing
134 },
135 postMessage: function(message) {
136 do_print("fullBody: " + message.fullBody);
137 do_check_eq(expected, message.fullBody)
138 }
139 });
141 do_print("expect: " + expected);
142 do_print("pdu: " + pdu);
143 worker.onRILMessage(0, newSmsParcel(pdu));
145 run_next_test();
146 });
147 }
149 let test_receiving_7bit_alphabets__ril;
150 let test_receiving_7bit_alphabets__worker;
151 function test_receiving_7bit_alphabets(lst, sst) {
152 if (!test_receiving_7bit_alphabets__ril) {
153 test_receiving_7bit_alphabets__ril = newRadioInterface();
154 test_receiving_7bit_alphabets__worker = newWriteHexOctetAsUint8Worker();
155 }
156 let ril = test_receiving_7bit_alphabets__ril;
157 let worker = test_receiving_7bit_alphabets__worker;
158 let context = worker.ContextPool._contexts[0];
159 let helper = context.GsmPDUHelper;
160 let buf = context.Buf;
162 function get7bitRawBytes(expected) {
163 buf.outgoingIndex = 0;
164 helper.writeStringAsSeptets(expected, 0, lst, sst);
166 let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
167 return Array.slice(subArray);
168 }
170 let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst];
171 let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst];
173 let text = removeSpecialChar(langTable + langShiftTable, ESCAPE + RESCTL);
174 for (let i = 0; i < text.length;) {
175 let len = Math.min(70, text.length - i);
176 let expected = text.substring(i, i + len);
177 let septets = ril._countGsm7BitSeptets(expected, langTable, langShiftTable);
178 let rawBytes = get7bitRawBytes(expected);
179 let pdu = compose7bitPdu(lst, sst, rawBytes, septets);
180 add_test_receiving_sms(expected, pdu);
182 i += len;
183 }
184 }
186 function test_receiving_ucs2_alphabets(text) {
187 let worker = test_receiving_7bit_alphabets__worker;
188 let context = worker.ContextPool._contexts[0];
189 let buf = context.Buf;
191 function getUCS2RawBytes(expected) {
192 buf.outgoingIndex = 0;
193 context.GsmPDUHelper.writeUCS2String(expected);
195 let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex);
196 return Array.slice(subArray);
197 }
199 for (let i = 0; i < text.length;) {
200 let len = Math.min(70, text.length - i);
201 let expected = text.substring(i, i + len);
202 let rawBytes = getUCS2RawBytes(expected);
203 let pdu = composeUcs2Pdu(rawBytes);
204 add_test_receiving_sms(expected, pdu);
206 i += len;
207 }
208 }
210 let ucs2str = "";
211 for (let lst = 0; lst < PDU_NL_LOCKING_SHIFT_TABLES.length; lst++) {
212 ucs2str += PDU_NL_LOCKING_SHIFT_TABLES[lst];
213 for (let sst = 0; sst < PDU_NL_SINGLE_SHIFT_TABLES.length; sst++) {
214 test_receiving_7bit_alphabets(lst, sst);
216 if (lst == 0) {
217 ucs2str += PDU_NL_SINGLE_SHIFT_TABLES[sst];
218 }
219 }
220 }
221 test_receiving_ucs2_alphabets(ucs2str);
223 // Bug 820220: B2G SMS: wrong order and truncated content in multi-part messages
224 add_test(function test_sendSMS_UCS2_without_langIndex_langShiftIndex_defined() {
225 let worker = newWriteHexOctetAsUint8Worker();
226 let context = worker.ContextPool._contexts[0];
228 context.Buf.sendParcel = function() {
229 // Each sendParcel() call represents one outgoing segment of a multipart
230 // SMS message. Here, we have the first segment send, so it's "Hello "
231 // only.
232 //
233 // 4(parcel size) + 4(request type) + 4(token)
234 // + 4(two messages) + 4(null SMSC) + 4(message string length)
235 // + 1(first octet) + 1(message reference)
236 // + 2(DA len, TOA) + 4(addr)
237 // + 1(pid) + 1(dcs)
238 // + 1(UDL) + 6(UDHL, type, len, ref, max, seq)
239 // + 12(2 * strlen("Hello "))
240 // + 4(two delimitors) = 57
241 //
242 // If we have additional 6(type, len, langIndex, type len, langShiftIndex)
243 // octets here, then bug 809553 is not fixed.
244 do_check_eq(this.outgoingIndex, 57);
246 run_next_test();
247 };
249 context.RIL.sendSMS({
250 number: "1",
251 segmentMaxSeq: 2,
252 fullBody: "Hello World!",
253 dcs: PDU_DCS_MSG_CODING_16BITS_ALPHABET,
254 segmentRef16Bit: false,
255 userDataHeaderLength: 5,
256 requestStatusReport: true,
257 segments: [
258 {
259 body: "Hello ",
260 encodedBodyLength: 12,
261 }, {
262 body: "World!",
263 encodedBodyLength: 12,
264 }
265 ],
266 });
267 });