/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.uicc.IccUtils; import junit.framework.TestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.SmallTest; public class GsmAlphabetTest extends TestCase { private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac"; @SmallTest public void test7bitWithHeader() throws Exception { SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); concatRef.refNumber = 1; concatRef.seqNumber = 2; concatRef.msgCount = 2; concatRef.isEightBits = true; SmsHeader header = new SmsHeader(); header.concatRef = concatRef; String message = "aaaaaaaaaabbbbbbbbbbcccccccccc"; byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, SmsHeader.toByteArray(header), 0, 0); int septetCount = GsmAlphabet.countGsmSeptetsUsingTables(message, true, 0, 0); String parsedMessage = GsmAlphabet.gsm7BitPackedToString( userData, SmsHeader.toByteArray(header).length+2, septetCount, 1, 0, 0); assertEquals(message, parsedMessage); } // TODO: This method should *really* be a series of individual test methods. // However, it's a SmallTest because it executes quickly. @SmallTest public void testBasic() throws Exception { // '@' maps to char 0 assertEquals(0, GsmAlphabet.charToGsm('@')); // `a (a with grave accent) maps to last GSM character assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0')); // // These are the extended chars // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE // for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) { assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE, GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i))); } // euro symbol assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE, GsmAlphabet.charToGsm('\u20ac')); // An unmappable char (the 'cent' char) maps to a space assertEquals(GsmAlphabet.charToGsm(' '), GsmAlphabet.charToGsm('\u00a2')); // unmappable = space = 1 septet assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2')); // // Test extended table // for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) { assertEquals(sGsmExtendedChars.charAt(i), GsmAlphabet.gsmExtendedToChar( GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i)))); } // Unmappable extended char assertEquals(GsmAlphabet.charToGsm(' '), GsmAlphabet.charToGsmExtended('@')); // // gsmToChar() // assertEquals('@', GsmAlphabet.gsmToChar(0)); // `a (a with grave accent) maps to last GSM character assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f)); assertEquals('\uffff', GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE)); // Out-of-range/unmappable value assertEquals(' ', GsmAlphabet.gsmToChar(0x80)); // // gsmExtendedToChar() // assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28)); // No double-escapes assertEquals(' ', GsmAlphabet.gsmExtendedToChar( GsmAlphabet.GSM_EXTENDED_ESCAPE)); // Reserved for extension to extension table (mapped to space) assertEquals(' ', GsmAlphabet.gsmExtendedToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE)); // Unmappable (mapped to character in default or national locking shift table) assertEquals('@', GsmAlphabet.gsmExtendedToChar(0)); assertEquals('\u00e0', GsmAlphabet.gsmExtendedToChar(0x7f)); // // stringTo7BitPacked, gsm7BitPackedToString // byte[] packed; StringBuilder testString = new StringBuilder(300); // Check all alignment cases for (int i = 0; i < 9; i++, testString.append('@')) { packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); assertEquals(testString.toString(), GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0])); } // Check full non-extended alphabet for (int i = 0; i < 0x80; i++) { char c; if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) { continue; } c = GsmAlphabet.gsmToChar(i); testString.append(c); // These are all non-extended chars, so it should be // one septet per char assertEquals(1, GsmAlphabet.countGsmSeptets(c)); } packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); assertEquals(testString.toString(), GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0])); // Test extended chars too testString.append(sGsmExtendedChars); for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) { // These are all extended chars, so it should be // two septets per char assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i))); } packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); assertEquals(testString.toString(), GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0])); // stringTo7BitPacked handles up to 255 septets testString.setLength(0); for (int i = 0; i < 255; i++) { testString.append('@'); } packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); assertEquals(testString.toString(), GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0])); // > 255 septets throws runtime exception testString.append('@'); try { GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); fail("expected exception"); } catch (EncodeException ex) { // exception expected } // Try 254 septets with 127 extended chars testString.setLength(0); for (int i = 0; i < (255 / 2); i++) { testString.append('{'); } packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); assertEquals(testString.toString(), GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0])); // > 255 septets throws runtime exception testString.append('{'); try { GsmAlphabet.stringToGsm7BitPacked(testString.toString(), 0, 0); fail("expected exception"); } catch (EncodeException ex) { // exception expected } // Reserved for extension to extension table (mapped to space) packed = new byte[]{(byte)(0x1b | 0x80), 0x1b >> 1}; assertEquals(" ", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2)); // Unmappable (mapped to character in default alphabet table) packed[0] = 0x1b; packed[1] = 0x00; assertEquals("@", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2)); packed[0] = (byte)(0x1b | 0x80); packed[1] = (byte)(0x7f >> 1); assertEquals("\u00e0", GsmAlphabet.gsm7BitPackedToString(packed, 0, 2)); // // 8 bit unpacked format // // Note: we compare hex strings here // because Assert doesn't have array comparisons byte unpacked[]; unpacked = IccUtils.hexStringToBytes("566F696365204D61696C"); assertEquals("Voice Mail", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); assertEquals(IccUtils.bytesToHexString(unpacked), IccUtils.bytesToHexString( GsmAlphabet.stringToGsm8BitPacked("Voice Mail"))); unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars); // two bytes for every extended char assertEquals(2 * sGsmExtendedChars.length(), unpacked.length); assertEquals(sGsmExtendedChars, GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); // should be two bytes per extended char assertEquals(2 * sGsmExtendedChars.length(), unpacked.length); // Test truncation of unaligned extended chars unpacked = new byte[3]; GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked, 0, unpacked.length); // Should be one extended char and an 0xff at the end assertEquals(0xff, 0xff & unpacked[2]); assertEquals(sGsmExtendedChars.substring(0, 1), GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); // Test truncation of normal chars unpacked = new byte[3]; GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked, 0, unpacked.length); assertEquals("abc", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); // Test truncation of mixed normal and extended chars unpacked = new byte[3]; GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked, 0, unpacked.length); assertEquals("a{", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); // Test padding after normal char unpacked = new byte[3]; GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked, 0, unpacked.length); assertEquals("a", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); assertEquals(0xff, 0xff & unpacked[1]); assertEquals(0xff, 0xff & unpacked[2]); // Test malformed input -- escape char followed by end of field unpacked[0] = 0; unpacked[1] = 0; unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE; assertEquals("@@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length)); // non-zero offset assertEquals("@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); // test non-zero offset unpacked[0] = 0; GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked, 1, unpacked.length - 1); assertEquals(0, unpacked[0]); assertEquals("ab", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); // test non-zero offset with truncated extended char unpacked[0] = 0; GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked, 1, unpacked.length - 1); assertEquals(0, unpacked[0]); assertEquals("a", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); // Reserved for extension to extension table (mapped to space) unpacked[0] = 0x1b; unpacked[1] = 0x1b; assertEquals(" ", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2)); // Unmappable (mapped to character in default or national locking shift table) unpacked[1] = 0x00; assertEquals("@", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2)); unpacked[1] = 0x7f; assertEquals("\u00e0", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, 2)); } @SmallTest public void testGsm8BitUpackedWithEuckr() throws Exception { // Some feature phones in Korea store contacts as euc-kr. // Test this situations. byte unpacked[]; // Test general alphabet strings. unpacked = IccUtils.hexStringToBytes("61626320646566FF"); assertEquals("abc def", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); // Test korean strings. unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF"); assertEquals("\uD14C\uC2A4\uD2B8", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); // Test gsm Extented Characters. unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars); assertEquals(sGsmExtendedChars, GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); } }