10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2010 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.SmsMessage;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager;
2199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Savilleimport android.telephony.Rlog;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.AndroidTestCase;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.LargeTest;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.MediumTest;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.test.suitebuilder.annotation.SmallTest;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.SmsConstants;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Test cases to verify selection of the optimal 7 bit encoding tables
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * (for all combinations of enabled national language tables) for messages
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * containing Turkish, Spanish, Portuguese, Greek, and other symbols
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * present in the GSM default and national language tables defined in
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 3GPP TS 23.038. Also verifies correct SMS encoding for CDMA, which only
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * supports the GSM 7 bit default alphabet, ASCII 8 bit, and UCS-2.
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Tests both encoding variations: unsupported characters mapped to space,
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and unsupported characters force entire message to UCS-2.
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class SmsMessageBodyTest extends AndroidTestCase {
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String TAG = "SmsMessageBodyTest";
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // ASCII chars in the GSM 7 bit default alphabet
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sAsciiChars = "@$_ !\"#%&'()*+,-./0123456789" +
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ":;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\r";
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Unicode chars in the GSM 7 bit default alphabet and both locking shift tables
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmDefaultChars = "\u00a3\u00a5\u00e9\u00c7\u0394\u00c9" +
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u00dc\u00a7\u00fc\u00e0";
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Unicode chars in the GSM 7 bit default table and Turkish locking shift tables
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmDefaultAndTurkishTables = "\u00f9\u00f2\u00c5\u00e5\u00df" +
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u00a4\u00c4\u00d6\u00d1\u00e4\u00f6\u00f1";
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Unicode chars in the GSM 7 bit default table but not the locking shift tables
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmDefaultTableOnly = "\u00e8\u00ec\u00d8\u00f8\u00c6\u00e6" +
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u00a1\u00bf";
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // ASCII chars in the GSM default extension table
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmExtendedAsciiChars = "{}[]\f";
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in GSM default extension table and Portuguese locking shift table
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmExtendedPortugueseLocking = "^\\|~";
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Euro currency symbol
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGsmExtendedEuroSymbol = "\u20ac";
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc.
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" +
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" +
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" +
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" +
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" +
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" +
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" +
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u00a2\u00a9\u00ae\u2122";
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in Turkish single shift and locking shift tables
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sTurkishChars = "\u0131\u011e\u011f\u015e\u015f\u0130";
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in Spanish single shift table and Portuguese single and locking shift tables
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sPortugueseAndSpanishChars = "\u00c1\u00e1\u00cd\u00ed"
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            + "\u00d3\u00f3\u00da\u00fa";
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in all national language tables but not in the standard GSM alphabets
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sNationalLanguageTablesOnly = "\u00e7";
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in Portuguese single shift and locking shift tables
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sPortugueseChars = "\u00ea\u00d4\u00f4\u00c0\u00c2\u00e2"
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            + "\u00ca\u00c3\u00d5\u00e3\u00f5";
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // chars in Portuguese locking shift table only
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sPortugueseLockingShiftChars = "\u00aa\u221e\u00ba`";
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Greek letters in GSM alphabet missing from Portuguese locking and single shift tables
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGreekLettersNotInPortugueseTables = "\u039b\u039e";
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Greek letters in GSM alphabet and Portuguese single shift (but not locking shift) table
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String sGreekLettersInPortugueseShiftTable =
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            "\u03a6\u0393\u03a9\u03a0\u03a8\u03a3\u0398";
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // List of classes of characters in SMS tables
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String[] sCharacterClasses = {
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmExtendedAsciiChars,
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmExtendedPortugueseLocking,
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmDefaultChars,
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmDefaultAndTurkishTables,
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmDefaultTableOnly,
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGsmExtendedEuroSymbol,
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sUnicodeChars,
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sTurkishChars,
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sPortugueseChars,
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sPortugueseLockingShiftChars,
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sPortugueseAndSpanishChars,
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGreekLettersNotInPortugueseTables,
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sGreekLettersInPortugueseShiftTable,
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sNationalLanguageTablesOnly,
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sAsciiChars
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int sNumCharacterClasses = sCharacterClasses.length;
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // For each character class, whether it is present in a particular char table.
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // First three entries are locking shift tables, followed by four single shift tables
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final boolean[][] sCharClassPresenceInTables = {
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // ASCII chars in all GSM extension tables
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, false, true, true, true, true},
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // ASCII chars in all GSM extension tables and Portuguese locking shift table
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, true, true, true, true, true},
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // non-ASCII chars in GSM default alphabet and all locking tables
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, true, true, false, false, false, false},
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // non-ASCII chars in GSM default alphabet and Turkish locking shift table
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, true, false, false, false, false, false},
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // non-ASCII chars in GSM default alphabet table only
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, false, false, false, false, false, false},
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Euro symbol is present in several tables
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, true, true, true, true, true, true},
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Unicode characters not present in any 7 bit tables
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, false, false, false, false, false},
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Characters specific to Turkish language
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, true, false, false, true, false, false},
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Characters in Portuguese single shift and locking shift tables
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, true, false, false, false, true},
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Characters in Portuguese locking shift table only
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, true, false, false, false, false},
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Chars in Spanish single shift and Portuguese single and locking shift tables
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, false, true, false, false, true, true},
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Greek letters in GSM default alphabet missing from Portuguese tables
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, true, false, false, false, false, false},
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Greek letters in GSM alphabet and Portuguese single shift table
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, true, false, false, false, false, true},
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Chars in all national language tables but not the standard GSM tables
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {false, true, true, false, true, true, true},
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // ASCII chars in GSM default alphabet
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {true, true, true, false, false, false, false}
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int sTestLengthCount = 12;
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[] sSeptetTestLengths =
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {  0,   1,   2, 80, 159, 160, 161, 240, 305, 306, 307, 320};
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[] sUnicodeTestLengths =
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {  0,   1,   2, 35,  69,  70,  71, 100, 133, 134, 135, 160};
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[] sTestMsgCounts =
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {  1,   1,   1,  1,   1,   1,   2,   2,   2,   2,   3,   3};
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[] sSeptetUnitsRemaining =
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {160, 159, 158, 80,   1,   0, 145,  66,   1,   0, 152, 139};
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[] sUnicodeUnitsRemaining =
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            { 70,  69,  68, 35,   1,   0,  63,  34,   1,   0,  66,  41};
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Combinations of enabled GSM national language single shift tables
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[][] sEnabledSingleShiftTables = {
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // GSM default alphabet only
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1},        // Turkish (single shift only)
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1},        // Turkish (single and locking shift)
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {2},        // Spanish
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {3},        // Portuguese (single shift only)
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {3},        // Portuguese (single and locking shift)
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2},     // Turkish + Spanish (single shift only)
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2},     // Turkish + Spanish (single and locking shift)
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 3},     // Turkish + Portuguese (single shift only)
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 3},     // Turkish + Portuguese (single and locking shift)
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {2, 3},     // Spanish + Portuguese (single shift only)
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {2, 3},     // Spanish + Portuguese (single and locking shift)
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2, 3},  // Turkish, Spanish, Portuguese (single shift only)
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2, 3},  // Turkish, Spanish, Portuguese (single and locking shift)
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Combinations of enabled GSM national language locking shift tables
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[][] sEnabledLockingShiftTables = {
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // GSM default alphabet only
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Turkish (single shift only)
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1},        // Turkish (single and locking shift)
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Spanish (no locking shift table)
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Portuguese (single shift only)
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {3},        // Portuguese (single and locking shift)
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Turkish + Spanish (single shift only)
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1},        // Turkish + Spanish (single and locking shift)
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Turkish + Portuguese (single shift only)
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 3},     // Turkish + Portuguese (single and locking shift)
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Spanish + Portuguese (single shift only)
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {3},        // Spanish + Portuguese (single and locking shift)
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {},         // Turkish, Spanish, Portuguese (single shift only)
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 3},     // Turkish, Spanish, Portuguese (single and locking shift)
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} // all language tables
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // LanguagePair counter indexes to check for each entry above
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int[][] sLanguagePairIndexesByEnabledIndex = {
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0},                            // default tables only
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1},                         // Turkish (single shift only)
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 4, 5},                   // Turkish (single and locking shift)
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 2},                         // Spanish
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 3},                         // Portuguese (single shift only)
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 3, 8, 11},                  // Portuguese (single and locking shift)
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 2},                      // Turkish + Spanish (single shift only)
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 2, 4, 5, 6},             // Turkish + Spanish (single and locking shift)
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 3},                      // Turkish + Portuguese (single shift only)
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 3, 4, 5, 7, 8, 9, 11},   // Turkish + Portuguese (single and locking shift)
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 2, 3},                      // Spanish + Portuguese (single shift only)
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 2, 3, 8, 10, 11},           // Spanish + Portuguese (single and locking shift)
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 2, 3},                   // all languages (single shift only)
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, // all languages (single and locking shift)
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}  // all languages (no Indic chars in test)
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * User data header requires one octet for length. Count as one septet, because
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * all combinations of header elements below will have at least one free bit
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * when padding to the nearest septet boundary.
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int UDH_SEPTET_COST_LENGTH = 1;
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Using a non-default language locking shift table OR single shift table
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * requires a user data header of 3 octets, or 4 septets, plus UDH length.
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4;
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Using a non-default language locking shift table AND single shift table
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * requires a user data header of 6 octets, or 7 septets, plus UDH length.
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7;
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Multi-part messages require a user data header of 5 octets, or 6 septets,
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * plus UDH length.
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @SmallTest
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void testCalcLengthAscii() throws Exception {
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder sb = new StringBuilder(320);
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int startPos = 0;
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int asciiCharsLen = sAsciiChars.length();
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < sTestLengthCount; i++) {
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int len = sSeptetTestLengths[i];
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertTrue(sb.length() <= len);
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            while (sb.length() < len) {
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int addCount = len - sb.length();
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int endPos = (asciiCharsLen - startPos > addCount) ?
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (startPos + addCount) : asciiCharsLen;
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sb.append(sAsciiChars, startPos, endPos);
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                startPos = (endPos == asciiCharsLen) ? 0 : endPos;
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals(len, sb.length());
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String testStr = sb.toString();
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[0] = sTestMsgCounts[i];
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[1] = len;
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[2] = sSeptetUnitsRemaining[i];
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callGsmLengthMethods(testStr, false, values);
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callGsmLengthMethods(testStr, true, values);
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callCdmaLengthMethods(testStr, false, values);
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callCdmaLengthMethods(testStr, true, values);
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @SmallTest
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void testCalcLengthUnicode() throws Exception {
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder sb = new StringBuilder(160);
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0};
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] values7bit = {1, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int startPos = 0;
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int unicodeCharsLen = sUnicodeChars.length();
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // start with length 1: empty string uses ENCODING_7BIT
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 1; i < sTestLengthCount; i++) {
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int len = sUnicodeTestLengths[i];
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertTrue(sb.length() <= len);
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            while (sb.length() < len) {
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int addCount = len - sb.length();
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int endPos = (unicodeCharsLen - startPos > addCount) ?
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (startPos + addCount) : unicodeCharsLen;
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sb.append(sUnicodeChars, startPos, endPos);
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                startPos = (endPos == unicodeCharsLen) ? 0 : endPos;
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals(len, sb.length());
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String testStr = sb.toString();
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[0] = sTestMsgCounts[i];
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[1] = len;
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values[2] = sUnicodeUnitsRemaining[i];
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values7bit[1] = len;
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values7bit[2] = SmsConstants.MAX_USER_DATA_SEPTETS - len;
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callGsmLengthMethods(testStr, false, values);
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callCdmaLengthMethods(testStr, false, values);
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callGsmLengthMethods(testStr, true, values7bit);
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            callCdmaLengthMethods(testStr, true, values7bit);
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static class LanguagePair {
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // index is 2 for Portuguese locking shift because there is no Spanish locking shift table
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        private final int langTableIndex;
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        private final int langShiftTableIndex;
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int length;
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int missingChars7bit;
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        LanguagePair(int langTable, int langShiftTable) {
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            langTableIndex = langTable;
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            langShiftTableIndex = langShiftTable;
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void clear() {
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            length = 0;
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            missingChars7bit = 0;
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void addChar(boolean[] charClassTableRow) {
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (charClassTableRow[langTableIndex]) {
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                length++;
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (charClassTableRow[3 + langShiftTableIndex]) {
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                length += 2;
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                length++;    // use ' ' for unmapped char in 7 bit only mode
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                missingChars7bit++;
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static class CounterHelper {
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        LanguagePair[] mCounters;
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] mStatsCounters;
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int mUnicodeCounter;
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CounterHelper() {
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mCounters = new LanguagePair[12];
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mStatsCounters = new int[12];
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < 12; i++) {
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCounters[i] = new LanguagePair(i/4, i%4);
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void clear() {
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Note: don't clear stats counters
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < 12; i++) {
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCounters[i].clear();
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void addChar(int charClass) {
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            boolean[] charClassTableRow = sCharClassPresenceInTables[charClass];
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < 12; i++) {
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCounters[i].addChar(charClassTableRow);
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void fillData(int enabledLangsIndex, boolean use7bitOnly, int[] values, int length) {
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] languagePairs = sLanguagePairIndexesByEnabledIndex[enabledLangsIndex];
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int minNumSeptets = Integer.MAX_VALUE;
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int minNumSeptetsWithHeader = Integer.MAX_VALUE;
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int minNumMissingChars = Integer.MAX_VALUE;
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int langIndex = -1;
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int langShiftIndex = -1;
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i : languagePairs) {
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                LanguagePair pair = mCounters[i];
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int udhLength = 0;
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (i != 0) {
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    udhLength = UDH_SEPTET_COST_LENGTH;
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (i < 4 || i % 4 == 0) {
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE;
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES;
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int numSeptetsWithHeader;
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (pair.length > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) {
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (udhLength == 0) {
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength = UDH_SEPTET_COST_LENGTH;
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE;
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int msgCount = (pair.length + septetsPerPart - 1) / septetsPerPart;
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    numSeptetsWithHeader = udhLength * msgCount + pair.length;
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    numSeptetsWithHeader = udhLength + pair.length;
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (use7bitOnly) {
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (pair.missingChars7bit < minNumMissingChars || (pair.missingChars7bit ==
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            minNumMissingChars && numSeptetsWithHeader < minNumSeptetsWithHeader)) {
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumSeptets = pair.length;
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumSeptetsWithHeader = numSeptetsWithHeader;
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumMissingChars = pair.missingChars7bit;
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        langIndex = pair.langTableIndex;
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        langShiftIndex = pair.langShiftTableIndex;
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (pair.missingChars7bit == 0 && numSeptetsWithHeader < minNumSeptetsWithHeader) {
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumSeptets = pair.length;
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumSeptetsWithHeader = numSeptetsWithHeader;
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        langIndex = pair.langTableIndex;
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        langShiftIndex = pair.langShiftTableIndex;
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (langIndex == -1) {
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // nothing matches, use values for Unicode
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int byteCount = length * 2;
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (byteCount > SmsConstants.MAX_USER_DATA_BYTES) {
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    values[0] = (byteCount + SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER - 1) /
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    values[2] = ((values[0] * SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER) -
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            byteCount) / 2;
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    values[0] = 1;
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    values[2] = (SmsConstants.MAX_USER_DATA_BYTES - byteCount) / 2;
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[1] = length;
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[3] = SmsConstants.ENCODING_16BIT;
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[4] = 0;
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[5] = 0;
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mUnicodeCounter++;
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int udhLength = 0;
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (langIndex != 0 || langShiftIndex != 0) {
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    udhLength = UDH_SEPTET_COST_LENGTH;
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (langIndex == 0 || langShiftIndex == 0) {
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength += UDH_SEPTET_COST_ONE_SHIFT_TABLE;
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength += UDH_SEPTET_COST_TWO_SHIFT_TABLES;
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int msgCount;
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (minNumSeptets > (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) {
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (udhLength == 0) {
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength = UDH_SEPTET_COST_LENGTH;
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    udhLength += UDH_SEPTET_COST_CONCATENATED_MESSAGE;
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    int septetsPerPart = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    msgCount = (minNumSeptets + septetsPerPart - 1) / septetsPerPart;
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    msgCount = 1;
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[0] = msgCount;
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[1] = minNumSeptets;
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[2] = (values[0] * (SmsConstants.MAX_USER_DATA_SEPTETS - udhLength)) -
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        minNumSeptets;
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[3] = SmsConstants.ENCODING_7BIT;
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[4] = (langIndex == 2 ? 3 : langIndex); // Portuguese is code 3, index 2
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                values[5] = langShiftIndex;
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                assertEquals("minNumSeptetsWithHeader", minNumSeptetsWithHeader,
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        udhLength * msgCount + minNumSeptets);
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mStatsCounters[langIndex * 4 + langShiftIndex]++;
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void printStats() {
48399c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville            Rlog.d(TAG, "Unicode selection count: " + mUnicodeCounter);
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < 12; i++) {
48599c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                Rlog.d(TAG, "Language pair index " + i + " count: " + mStatsCounters[i]);
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @LargeTest
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void testCalcLengthMixed7bit() throws Exception {
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        StringBuilder sb = new StringBuilder(320);
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CounterHelper ch = new CounterHelper();
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Random r = new Random(0x4321);  // use the same seed for reproducibility
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] expectedValues = new int[6];
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] origLockingShiftTables = GsmAlphabet.getEnabledLockingShiftTables();
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] origSingleShiftTables = GsmAlphabet.getEnabledSingleShiftTables();
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int enabledLanguagesTestCases = sEnabledSingleShiftTables.length;
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        long startTime = System.currentTimeMillis();
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Repeat for 10 test runs
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int run = 0; run < 10; run++) {
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            sb.setLength(0);
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ch.clear();
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int unicodeOnlyCount = 0;
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Test incrementally from 1 to 320 character random messages
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 1; i < 320; i++) {
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // 1% chance to add from each special character class, else add an ASCII char
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int charClass = r.nextInt(100);
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (charClass >= sNumCharacterClasses) {
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    charClass = sNumCharacterClasses - 1;   // last class is ASCII
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int classLength = sCharacterClasses[charClass].length();
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                char nextChar = sCharacterClasses[charClass].charAt(r.nextInt(classLength));
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sb.append(nextChar);
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ch.addChar(charClass);
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville//                if (i % 20 == 0) {
52099c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville//                    Rlog.d(TAG, "test string: " + sb);
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville//                }
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Test string against all combinations of enabled languages
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                boolean unicodeOnly = true;
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                for (int j = 0; j < enabledLanguagesTestCases; j++) {
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    GsmAlphabet.setEnabledSingleShiftTables(sEnabledSingleShiftTables[j]);
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    GsmAlphabet.setEnabledLockingShiftTables(sEnabledLockingShiftTables[j]);
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ch.fillData(j, false, expectedValues, i);
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (expectedValues[3] == SmsConstants.ENCODING_7BIT) {
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        unicodeOnly = false;
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    callGsmLengthMethods(sb, false, expectedValues);
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // test 7 bit only mode
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ch.fillData(j, true, expectedValues, i);
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    callGsmLengthMethods(sb, true, expectedValues);
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // after 10 iterations with a Unicode-only string, skip to next test string
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // so we can spend more time testing strings that do encode into 7 bits.
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (unicodeOnly && ++unicodeOnlyCount == 10) {
54099c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville//                    Rlog.d(TAG, "Unicode only: skipping to next test string");
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ch.printStats();
54699c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville        Rlog.d(TAG, "Completed in " + (System.currentTimeMillis() - startTime) + " ms");
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        GsmAlphabet.setEnabledLockingShiftTables(origLockingShiftTables);
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        GsmAlphabet.setEnabledSingleShiftTables(origSingleShiftTables);
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void callGsmLengthMethods(CharSequence msgBody, boolean use7bitOnly,
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] expectedValues)
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // deprecated GSM-specific method
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int[] values = android.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("msgCount",           expectedValues[0], values[0]);
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitCount",      expectedValues[1], values[1]);
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitSize",       expectedValues[3], values[3]);
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int activePhone = TelephonyManager.getDefault().getPhoneType();
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (TelephonyManager.PHONE_TYPE_GSM == activePhone) {
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("msgCount",           expectedValues[0], values[0]);
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitCount",      expectedValues[1], values[1]);
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitSize",       expectedValues[3], values[3]);
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        GsmAlphabet.TextEncodingDetails ted =
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("languageTable",      expectedValues[4], ted.languageTable);
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("languageShiftTable", expectedValues[5], ted.languageShiftTable);
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void callCdmaLengthMethods(CharSequence msgBody, boolean use7bitOnly,
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] expectedValues)
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    {
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int activePhone = TelephonyManager.getDefault().getPhoneType();
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (TelephonyManager.PHONE_TYPE_CDMA == activePhone) {
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int[] values = android.telephony.SmsMessage.calculateLength(msgBody, use7bitOnly);
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("msgCount",           expectedValues[0], values[0]);
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitCount",      expectedValues[1], values[1]);
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitsRemaining", expectedValues[2], values[2]);
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assertEquals("codeUnitSize",       expectedValues[3], values[3]);
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        GsmAlphabet.TextEncodingDetails ted =
5933ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan                com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly, true);
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5993ce96a061c2c6e24f4ff3bd237e18c29fc0c0108Amit Mahajan        ted = com.android.internal.telephony.cdma.sms.BearerData.calcTextEncodingDetails(msgBody, use7bitOnly, true);
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("msgCount",           expectedValues[0], ted.msgCount);
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitCount",      expectedValues[1], ted.codeUnitCount);
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitsRemaining", expectedValues[2], ted.codeUnitsRemaining);
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assertEquals("codeUnitSize",       expectedValues[3], ted.codeUnitSize);
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
606