|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 MARIONETTE_TIMEOUT = 60000; |
|
5 |
|
6 const LEN_7BIT = 160; |
|
7 const LEN_7BIT_WITH_8BIT_REF = 153; |
|
8 const LEN_7BIT_WITH_16BIT_REF = 152; |
|
9 const LEN_UCS2 = 70; |
|
10 const LEN_UCS2_WITH_8BIT_REF = 67; |
|
11 const LEN_UCS2_WITH_16BIT_REF = 66; |
|
12 |
|
13 SpecialPowers.setBoolPref("dom.sms.enabled", true); |
|
14 let currentStrict7BitEncoding = false; |
|
15 SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", |
|
16 currentStrict7BitEncoding); |
|
17 SpecialPowers.addPermission("sms", true, document); |
|
18 |
|
19 let manager = window.navigator.mozMobileMessage; |
|
20 ok(manager instanceof MozMobileMessageManager, |
|
21 "manager is instance of " + manager.constructor); |
|
22 |
|
23 function times(str, n) { |
|
24 return (new Array(n + 1)).join(str); |
|
25 } |
|
26 |
|
27 let tasks = { |
|
28 // List of test fuctions. Each of them should call |tasks.next()| when |
|
29 // completed or |tasks.finish()| to jump to the last one. |
|
30 _tasks: [], |
|
31 _nextTaskIndex: 0, |
|
32 |
|
33 push: function(func) { |
|
34 this._tasks.push(func); |
|
35 }, |
|
36 |
|
37 next: function() { |
|
38 let index = this._nextTaskIndex++; |
|
39 let task = this._tasks[index]; |
|
40 try { |
|
41 task(); |
|
42 } catch (ex) { |
|
43 ok(false, "test task[" + index + "] throws: " + ex); |
|
44 // Run last task as clean up if possible. |
|
45 if (index != this._tasks.length - 1) { |
|
46 this.finish(); |
|
47 } |
|
48 } |
|
49 }, |
|
50 |
|
51 finish: function() { |
|
52 this._tasks[this._tasks.length - 1](); |
|
53 }, |
|
54 |
|
55 run: function() { |
|
56 this.next(); |
|
57 } |
|
58 }; |
|
59 |
|
60 function addTest(text, strict7BitEncoding, expected) { |
|
61 tasks.push(function() { |
|
62 if (strict7BitEncoding != currentStrict7BitEncoding) { |
|
63 currentStrict7BitEncoding = strict7BitEncoding; |
|
64 SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", |
|
65 currentStrict7BitEncoding); |
|
66 } |
|
67 |
|
68 let domRequest = manager.getSegmentInfoForText(text); |
|
69 ok(domRequest, "DOMRequest object returned."); |
|
70 |
|
71 domRequest.onsuccess = function(e) { |
|
72 log("Received 'onsuccess' DOMRequest event."); |
|
73 |
|
74 let result = e.target.result; |
|
75 if (!result) { |
|
76 ok(false, "getSegmentInfoForText() result is not valid."); |
|
77 tasks.finish(); |
|
78 return; |
|
79 } |
|
80 |
|
81 is(result.segments, expected[0], "segments"); |
|
82 is(result.charsPerSegment, expected[1], "charsPerSegment"); |
|
83 is(result.charsAvailableInLastSegment, expected[2], |
|
84 "charsAvailableInLastSegment"); |
|
85 |
|
86 tasks.next(); |
|
87 }; |
|
88 |
|
89 domRequest.onerror = function(e) { |
|
90 ok(false, "Failed to call getSegmentInfoForText()."); |
|
91 tasks.finish(); |
|
92 }; |
|
93 }); |
|
94 } |
|
95 |
|
96 // GSM 7Bit Alphabets: |
|
97 // |
|
98 // 'a' is in GSM default locking shift table, so it takes 1 septet. |
|
99 addTest("a", false, [1, LEN_7BIT, LEN_7BIT - 1]); |
|
100 // '\u20ac' is in GSM default single shift table, so it takes 2 septets. |
|
101 addTest("\u20ac", false, [1, LEN_7BIT, LEN_7BIT - 2]); |
|
102 // SP is defined in both locking shift and single shift tables. |
|
103 addTest(" ", false, [1, LEN_7BIT, LEN_7BIT - 1]); |
|
104 // Some combinations. |
|
105 addTest("a\u20ac", false, [1, LEN_7BIT, LEN_7BIT - 3]); |
|
106 addTest("a ", false, [1, LEN_7BIT, LEN_7BIT - 2]); |
|
107 addTest("\u20aca", false, [1, LEN_7BIT, LEN_7BIT - 3]); |
|
108 addTest("\u20ac ", false, [1, LEN_7BIT, LEN_7BIT - 3]); |
|
109 addTest(" \u20ac", false, [1, LEN_7BIT, LEN_7BIT - 3]); |
|
110 addTest(" a", false, [1, LEN_7BIT, LEN_7BIT - 2]); |
|
111 |
|
112 // GSM 7Bit Alphabets (multipart): |
|
113 // |
|
114 // Exactly 160 locking shift table chararacters. |
|
115 addTest(times("a", LEN_7BIT), false, [1, LEN_7BIT, 0]); |
|
116 // 161 locking shift table chararacters. We'll have |161 - 153 = 8| septets in |
|
117 // the 2nd segment. |
|
118 addTest(times("a", LEN_7BIT + 1), false, |
|
119 [2, LEN_7BIT_WITH_8BIT_REF, LEN_7BIT_WITH_8BIT_REF - 8]); |
|
120 // |LEN_7BIT_WITH_8BIT_REF * 2| locking shift table chararacters. |
|
121 addTest(times("a", LEN_7BIT_WITH_8BIT_REF * 2), false, |
|
122 [2, LEN_7BIT_WITH_8BIT_REF, 0]); |
|
123 // |LEN_7BIT_WITH_8BIT_REF * 2 + 1| locking shift table chararacters. |
|
124 addTest(times("a", LEN_7BIT_WITH_8BIT_REF * 2 + 1), false, |
|
125 [3, LEN_7BIT_WITH_8BIT_REF, LEN_7BIT_WITH_8BIT_REF - 1]); |
|
126 // Exactly 80 single shift table chararacters. |
|
127 addTest(times("\u20ac", LEN_7BIT / 2), false, [1, LEN_7BIT, 0]); |
|
128 // 81 single shift table chararacters. Because |Math.floor(153 / 2) = 76|, it |
|
129 // should left 5 septets in the 2nd segment. |
|
130 addTest(times("\u20ac", LEN_7BIT / 2 + 1), false, |
|
131 [2, LEN_7BIT_WITH_8BIT_REF, LEN_7BIT_WITH_8BIT_REF - 10]); |
|
132 // |1 + 2 * 76| single shift table chararacters. We have only |153 - 76 * 2 = 1| |
|
133 // space left, but each single shift table character takes 2, so it will be |
|
134 // filled in the 3rd segment. |
|
135 addTest(times("\u20ac", 1 + 2 * Math.floor(LEN_7BIT_WITH_8BIT_REF / 2)), false, |
|
136 [3, LEN_7BIT_WITH_8BIT_REF, LEN_7BIT_WITH_8BIT_REF - 2]); |
|
137 // |2 * 76| single shift table chararacters + 1 locking shift table chararacter. |
|
138 addTest("a" + times("\u20ac", 2 * Math.floor(LEN_7BIT_WITH_8BIT_REF / 2)), false, |
|
139 [2, LEN_7BIT_WITH_8BIT_REF, 1]); |
|
140 addTest(times("\u20ac", 2 * Math.floor(LEN_7BIT_WITH_8BIT_REF / 2)) + "a", false, |
|
141 [2, LEN_7BIT_WITH_8BIT_REF, 0]); |
|
142 |
|
143 // UCS2: |
|
144 // |
|
145 // '\u6afb' should be encoded as UCS2. |
|
146 addTest("\u6afb", false, [1, LEN_UCS2, LEN_UCS2 - 1]); |
|
147 // Combination of GSM 7bit alphabets. |
|
148 addTest("\u6afba", false, [1, LEN_UCS2, LEN_UCS2 - 2]); |
|
149 addTest("\u6afb\u20ac", false, [1, LEN_UCS2, LEN_UCS2 - 2]); |
|
150 addTest("\u6afb ", false, [1, LEN_UCS2, LEN_UCS2 - 2]); |
|
151 |
|
152 // UCS2 (multipart): |
|
153 // |
|
154 // Exactly 70 UCS2 chararacters. |
|
155 addTest(times("\u6afb", LEN_UCS2), false, [1, LEN_UCS2, 0]); |
|
156 // 71 UCS2 chararacters. We'll have |71 - 67 = 4| chararacters in the 2nd |
|
157 // segment. |
|
158 addTest(times("\u6afb", LEN_UCS2 + 1), false, |
|
159 [2, LEN_UCS2_WITH_8BIT_REF, LEN_UCS2_WITH_8BIT_REF - 4]); |
|
160 // |LEN_UCS2_WITH_8BIT_REF * 2| ucs2 chararacters. |
|
161 addTest(times("\u6afb", LEN_UCS2_WITH_8BIT_REF * 2), false, |
|
162 [2, LEN_UCS2_WITH_8BIT_REF, 0]); |
|
163 // |LEN_7BIT_WITH_8BIT_REF * 2 + 1| ucs2 chararacters. |
|
164 addTest(times("\u6afb", LEN_UCS2_WITH_8BIT_REF * 2 + 1), false, |
|
165 [3, LEN_UCS2_WITH_8BIT_REF, LEN_UCS2_WITH_8BIT_REF - 1]); |
|
166 |
|
167 // Strict 7-Bit Encoding: |
|
168 // |
|
169 // Should have no effect on GSM default alphabet characters. |
|
170 addTest("\u0041", true, [1, LEN_7BIT, LEN_7BIT - 1]); |
|
171 // "\u00c0"(À) should be mapped to "\u0041"(A). |
|
172 addTest("\u00c0", true, [1, LEN_7BIT, LEN_7BIT - 1]); |
|
173 // Mixing mapped characters with unmapped ones. |
|
174 addTest("\u00c0\u0041", true, [1, LEN_7BIT, LEN_7BIT - 2]); |
|
175 addTest("\u0041\u00c0", true, [1, LEN_7BIT, LEN_7BIT - 2]); |
|
176 // UCS2 characters should be mapped to '*'. |
|
177 addTest("\u1234", true, [1, LEN_7BIT, LEN_7BIT - 1]); |
|
178 |
|
179 |
|
180 // WARNING: All tasks should be pushed before this!!! |
|
181 tasks.push(function cleanUp() { |
|
182 SpecialPowers.removePermission("sms", document); |
|
183 SpecialPowers.clearUserPref("dom.sms.enabled"); |
|
184 SpecialPowers.clearUserPref("dom.sms.strict7BitEncoding"); |
|
185 finish(); |
|
186 }); |
|
187 |
|
188 tasks.run(); |