/*
* 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"));
}
}