|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this); |
|
5 |
|
6 const ESCAPE = "\uffff"; |
|
7 const RESCTL = "\ufffe"; |
|
8 |
|
9 function run_test() { |
|
10 run_next_test(); |
|
11 } |
|
12 |
|
13 /** |
|
14 * Verify receiving SMS-DELIVERY messages |
|
15 */ |
|
16 |
|
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 } |
|
26 |
|
27 function pduToParcelData(pdu) { |
|
28 let dataLength = 4 + pdu.length * 4 + 4; |
|
29 let data = new Uint8Array(dataLength); |
|
30 let offset = 0; |
|
31 |
|
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; |
|
37 |
|
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; |
|
42 |
|
43 data[offset++] = hexToNibble(hi); |
|
44 data[offset++] = 0; |
|
45 data[offset++] = hexToNibble(lo); |
|
46 data[offset++] = 0; |
|
47 } |
|
48 |
|
49 // String delimitor |
|
50 data[offset++] = 0; |
|
51 data[offset++] = 0; |
|
52 data[offset++] = 0; |
|
53 data[offset++] = 0; |
|
54 |
|
55 return data; |
|
56 } |
|
57 |
|
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 } |
|
69 |
|
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 } |
|
82 |
|
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 } |
|
93 |
|
94 function newSmsParcel(pdu) { |
|
95 return newIncomingParcel(-1, |
|
96 RESPONSE_TYPE_UNSOLICITED, |
|
97 UNSOLICITED_RESPONSE_NEW_SMS, |
|
98 pduToParcelData(pdu)); |
|
99 } |
|
100 |
|
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 } |
|
110 |
|
111 function newWriteHexOctetAsUint8Worker() { |
|
112 let worker = newWorker({ |
|
113 postRILMessage: function(data) { |
|
114 // Do nothing |
|
115 }, |
|
116 postMessage: function(message) { |
|
117 // Do nothing |
|
118 } |
|
119 }); |
|
120 |
|
121 let context = worker.ContextPool._contexts[0]; |
|
122 context.GsmPDUHelper.writeHexOctet = function(value) { |
|
123 context.Buf.writeUint8(value); |
|
124 }; |
|
125 |
|
126 return worker; |
|
127 } |
|
128 |
|
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 }); |
|
140 |
|
141 do_print("expect: " + expected); |
|
142 do_print("pdu: " + pdu); |
|
143 worker.onRILMessage(0, newSmsParcel(pdu)); |
|
144 |
|
145 run_next_test(); |
|
146 }); |
|
147 } |
|
148 |
|
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; |
|
161 |
|
162 function get7bitRawBytes(expected) { |
|
163 buf.outgoingIndex = 0; |
|
164 helper.writeStringAsSeptets(expected, 0, lst, sst); |
|
165 |
|
166 let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex); |
|
167 return Array.slice(subArray); |
|
168 } |
|
169 |
|
170 let langTable = PDU_NL_LOCKING_SHIFT_TABLES[lst]; |
|
171 let langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[sst]; |
|
172 |
|
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); |
|
181 |
|
182 i += len; |
|
183 } |
|
184 } |
|
185 |
|
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; |
|
190 |
|
191 function getUCS2RawBytes(expected) { |
|
192 buf.outgoingIndex = 0; |
|
193 context.GsmPDUHelper.writeUCS2String(expected); |
|
194 |
|
195 let subArray = buf.outgoingBytes.subarray(0, buf.outgoingIndex); |
|
196 return Array.slice(subArray); |
|
197 } |
|
198 |
|
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); |
|
205 |
|
206 i += len; |
|
207 } |
|
208 } |
|
209 |
|
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); |
|
215 |
|
216 if (lst == 0) { |
|
217 ucs2str += PDU_NL_SINGLE_SHIFT_TABLES[sst]; |
|
218 } |
|
219 } |
|
220 } |
|
221 test_receiving_ucs2_alphabets(ucs2str); |
|
222 |
|
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]; |
|
227 |
|
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); |
|
245 |
|
246 run_next_test(); |
|
247 }; |
|
248 |
|
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 }); |