GsmAlphabetTest.java revision c38bb60d867c5d61d90b7179a9ed2b2d1848124f
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony;
18
19import com.android.internal.telephony.GsmAlphabet;
20
21import junit.framework.TestCase;
22
23import android.test.suitebuilder.annotation.LargeTest;
24import android.test.suitebuilder.annotation.SmallTest;
25
26public class GsmAlphabetTest extends TestCase {
27
28    private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
29
30    @SmallTest
31    public void test7bitWithHeader() throws Exception {
32        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
33        concatRef.refNumber = 1;
34        concatRef.seqNumber = 2;
35        concatRef.msgCount = 2;
36        concatRef.isEightBits = true;
37        SmsHeader header = new SmsHeader();
38        header.concatRef = concatRef;
39
40        String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
41        byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message,
42                SmsHeader.toByteArray(header), 0, 0);
43        int septetCount = GsmAlphabet.countGsmSeptetsUsingTables(message, true, 0, 0);
44        String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
45                userData, SmsHeader.toByteArray(header).length+2, septetCount, 1, 0, 0);
46        assertEquals(message, parsedMessage);
47    }
48
49    // TODO: This method should *really* be a series of individual test methods.
50    // However, it's a SmallTest because it executes quickly.
51    @SmallTest
52    public void testBasic() throws Exception {
53        // '@' maps to char 0
54        assertEquals(0, GsmAlphabet.charToGsm('@'));
55
56        // `a (a with grave accent) maps to last GSM character
57        assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0'));
58
59        //
60        // These are the extended chars
61        // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE
62        //
63
64        for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
65            assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
66                    GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i)));
67
68        }
69
70        // euro symbol
71        assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
72                GsmAlphabet.charToGsm('\u20ac'));
73
74        // An unmappable char (the 'cent' char) maps to a space
75        assertEquals(GsmAlphabet.charToGsm(' '),
76                GsmAlphabet.charToGsm('\u00a2'));
77
78        // unmappable = space = 1 septet
79        assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2'));
80
81        //
82        // Test extended table
83        //
84
85        for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
86            assertEquals(sGsmExtendedChars.charAt(i),
87                    GsmAlphabet.gsmExtendedToChar(
88                            GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i))));
89
90        }
91
92        // Unmappable extended char
93        assertEquals(GsmAlphabet.charToGsm(' '),
94                GsmAlphabet.charToGsmExtended('@'));
95
96        //
97        // gsmToChar()
98        //
99
100        assertEquals('@', GsmAlphabet.gsmToChar(0));
101
102        // `a (a with grave accent) maps to last GSM character
103        assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f));
104
105        assertEquals('\uffff',
106                GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
107
108        // Out-of-range/unmappable value
109        assertEquals(' ', GsmAlphabet.gsmToChar(0x80));
110
111        //
112        // gsmExtendedToChar()
113        //
114
115        assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28));
116
117        // No double-escapes
118        assertEquals(' ', GsmAlphabet.gsmExtendedToChar(
119                GsmAlphabet.GSM_EXTENDED_ESCAPE));
120
121        // Reserved for extension to extension table (mapped to space)
122        assertEquals(' ', GsmAlphabet.gsmExtendedToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
123
124        // Unmappable (mapped to character in default or national locking shift table)
125        assertEquals('@', GsmAlphabet.gsmExtendedToChar(0));
126        assertEquals('\u00e0', GsmAlphabet.gsmExtendedToChar(0x7f));
127
128        //
129        // stringTo7BitPacked, gsm7BitPackedToString
130        //
131
132        byte[] packed;
133        StringBuilder testString = new StringBuilder(300);
134
135        // Check all alignment cases
136        for (int i = 0; i < 9; i++, testString.append('@')) {
137            packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
138            assertEquals(testString.toString(),
139                    GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
140        }
141
142        // Check full non-extended alphabet
143        for (int i = 0; i < 0x80; i++) {
144            char c;
145
146            if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
147                continue;
148            }
149
150            c = GsmAlphabet.gsmToChar(i);
151            testString.append(c);
152
153            // These are all non-extended chars, so it should be
154            // one septet per char
155            assertEquals(1, GsmAlphabet.countGsmSeptets(c));
156        }
157
158        packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
159        assertEquals(testString.toString(),
160                GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
161
162        // Test extended chars too
163
164        testString.append(sGsmExtendedChars);
165
166        for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
167            // These are all extended chars, so it should be
168            // two septets per char
169            assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i)));
170
171        }
172
173        packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
174        assertEquals(testString.toString(),
175                GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
176
177        // stringTo7BitPacked handles up to 255 septets
178
179        testString.setLength(0);
180        for (int i = 0; i < 255; i++) {
181            testString.append('@');
182        }
183
184        packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
185        assertEquals(testString.toString(),
186                GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
187
188        // > 255 septets throws runtime exception
189        testString.append('@');
190
191        try {
192            GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
193            fail("expected exception");
194        } catch (EncodeException ex) {
195            // exception expected
196        }
197
198        // Try 254 septets with 127 extended chars
199
200        testString.setLength(0);
201        for (int i = 0; i < (255 / 2); i++) {
202            testString.append('{');
203        }
204
205        packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
206        assertEquals(testString.toString(),
207                GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
208
209        // > 255 septets throws runtime exception
210        testString.append('{');
211
212        try {
213            GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0);
214            fail("expected exception");
215        } catch (EncodeException ex) {
216            // exception expected
217        }
218
219        // Reserved for extension to extension table (mapped to space)
220        packed = new byte[]{(byte)(0x1b | 0x80), 0x1b >> 1};
221        assertEquals(" ", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
222
223        // Unmappable (mapped to character in default alphabet table)
224        packed[0] = 0x1b;
225        packed[1] = 0x00;
226        assertEquals("@", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
227        packed[0] = (byte)(0x1b | 0x80);
228        packed[1] = (byte)(0x7f >> 1);
229        assertEquals("\u00e0", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2));
230
231        //
232        // 8 bit unpacked format
233        //
234        // Note: we compare hex strings here
235        // because Assert doesn't have array comparisons
236
237        byte unpacked[];
238
239        unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
240        assertEquals("Voice Mail",
241                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
242
243        assertEquals(IccUtils.bytesToHexString(unpacked),
244                IccUtils.bytesToHexString(
245                        GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
246
247        unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
248        // two bytes for every extended char
249        assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
250        assertEquals(sGsmExtendedChars,
251                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
252
253        // should be two bytes per extended char
254        assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
255
256        // Test truncation of unaligned extended chars
257        unpacked = new byte[3];
258        GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked,
259                0, unpacked.length);
260
261        // Should be one extended char and an 0xff at the end
262
263        assertEquals(0xff, 0xff & unpacked[2]);
264        assertEquals(sGsmExtendedChars.substring(0, 1),
265                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
266
267        // Test truncation of normal chars
268        unpacked = new byte[3];
269        GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
270                0, unpacked.length);
271
272        assertEquals("abc",
273                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
274
275        // Test truncation of mixed normal and extended chars
276        unpacked = new byte[3];
277        GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked,
278                0, unpacked.length);
279
280        assertEquals("a{",
281                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
282
283        // Test padding after normal char
284        unpacked = new byte[3];
285        GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked,
286                0, unpacked.length);
287
288        assertEquals("a",
289                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
290
291        assertEquals(0xff, 0xff & unpacked[1]);
292        assertEquals(0xff, 0xff & unpacked[2]);
293
294        // Test malformed input -- escape char followed by end of field
295        unpacked[0] = 0;
296        unpacked[1] = 0;
297        unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE;
298
299        assertEquals("@@",
300                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
301
302        // non-zero offset
303        assertEquals("@",
304                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
305
306        // test non-zero offset
307        unpacked[0] = 0;
308        GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
309                1, unpacked.length - 1);
310
311
312        assertEquals(0, unpacked[0]);
313
314        assertEquals("ab",
315                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
316
317        // test non-zero offset with truncated extended char
318        unpacked[0] = 0;
319
320        GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked,
321                1, unpacked.length - 1);
322
323        assertEquals(0, unpacked[0]);
324
325        assertEquals("a",
326                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
327
328        // Reserved for extension to extension table (mapped to space)
329        unpacked[0] = 0x1b;
330        unpacked[1] = 0x1b;
331        assertEquals(" ", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
332
333        // Unmappable (mapped to character in default or national locking shift table)
334        unpacked[1] = 0x00;
335        assertEquals("@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
336        unpacked[1] = 0x7f;
337        assertEquals("\u00e0", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2));
338    }
339
340    @SmallTest
341    public void testGsm8BitUpackedWithEuckr() throws Exception {
342        // Some feature phones in Korea store contacts as euc-kr.
343        // Test this situations.
344        byte unpacked[];
345
346        // Test general alphabet strings.
347        unpacked = IccUtils.hexStringToBytes("61626320646566FF");
348        assertEquals("abc def",
349                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
350
351        // Test korean strings.
352        unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF");
353        assertEquals("\uD14C\uC2A4\uD2B8",
354                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
355
356        // Test gsm Extented Characters.
357        unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
358        assertEquals(sGsmExtendedChars,
359                GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr"));
360    }
361}
362