1/*
2 * Copyright (C) 2010 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.inputmethod.keyboard.internal;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.test.AndroidTestCase;
22import android.test.suitebuilder.annotation.SmallTest;
23
24import com.android.inputmethod.latin.R;
25
26import java.util.Arrays;
27import java.util.Locale;
28
29@SmallTest
30public class MoreKeySpecSplitTests extends AndroidTestCase {
31    private static final Locale TEST_LOCALE = Locale.ENGLISH;
32    private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
33
34    @Override
35    protected void setUp() throws Exception {
36        super.setUp();
37
38        final Context targetContext = getContext();
39        final Resources targetRes = targetContext.getResources();
40        final String targetPackageName = targetRes.getResourcePackageName(
41                R.string.english_ime_name);
42        mTextsSet.setLocale(TEST_LOCALE, targetRes, targetPackageName);
43    }
44
45    static <T> void assertArrayEquals(final String message, final T[] expected, final T[] actual) {
46        if (expected == actual) {
47            return;
48        }
49        if (expected == null || actual == null) {
50            assertEquals(message, Arrays.toString(expected), Arrays.toString(actual));
51            return;
52        }
53        if (expected.length != actual.length) {
54            assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual));
55            return;
56        }
57        for (int i = 0; i < expected.length; i++) {
58            final T e = expected[i];
59            final T a = actual[i];
60            if (e == a) {
61                continue;
62            }
63            assertEquals(message + " [" + i + "]", e, a);
64        }
65    }
66
67    private void assertTextArray(final String message, final String value,
68            final String ... expectedArray) {
69        final String resolvedActual = mTextsSet.resolveTextReference(value);
70        final String[] actual = MoreKeySpec.splitKeySpecs(resolvedActual);
71        final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
72        assertArrayEquals(message, expected, actual);
73    }
74
75    private void assertError(final String message, final String value, final String ... expected) {
76        try {
77            assertTextArray(message, value, expected);
78            fail(message);
79        } catch (Exception pcpe) {
80            // success.
81        }
82    }
83
84    // \U001d11e: MUSICAL SYMBOL G CLEF
85    private static final String PAIR1 = "\ud834\udd1e";
86    // \U001d122: MUSICAL SYMBOL F CLEF
87    private static final String PAIR2 = "\ud834\udd22";
88    // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148.
89    private static final String PAIR3 = "\ud87e\udca6";
90    private static final String SURROGATE1 = PAIR1 + PAIR2;
91    private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
92
93    public void testSplitZero() {
94        assertTextArray("Empty string", "");
95        assertTextArray("Empty entry", ",");
96        assertTextArray("Empty entry at beginning", ",a", "a");
97        assertTextArray("Empty entry at end", "a,", "a");
98        assertTextArray("Empty entry at middle", "a,,b", "a", "b");
99        assertTextArray("Empty entries with escape", ",a,b\\,c,,d,", "a", "b\\,c", "d");
100    }
101
102    public void testSplitSingle() {
103        assertTextArray("Single char", "a", "a");
104        assertTextArray("Surrogate pair", PAIR1, PAIR1);
105        assertTextArray("Single escape", "\\", "\\");
106        assertTextArray("Space", " ", " ");
107        assertTextArray("Single label", "abc", "abc");
108        assertTextArray("Single surrogate pairs label", SURROGATE2, SURROGATE2);
109        assertTextArray("Spaces", "   ", "   ");
110        assertTextArray("Spaces in label", "a b c", "a b c");
111        assertTextArray("Spaces at beginning of label", " abc", " abc");
112        assertTextArray("Spaces at end of label", "abc ", "abc ");
113        assertTextArray("Label surrounded by spaces", " abc ", " abc ");
114        assertTextArray("Surrogate pair surrounded by space",
115                " " + PAIR1 + " ",
116                " " + PAIR1 + " ");
117        assertTextArray("Surrogate pair within characters",
118                "ab" + PAIR2 + "cd",
119                "ab" + PAIR2 + "cd");
120        assertTextArray("Surrogate pairs within characters",
121                "ab" + SURROGATE1 + "cd",
122                "ab" + SURROGATE1 + "cd");
123
124        assertTextArray("Incomplete resource reference 1", "text", "text");
125        assertTextArray("Incomplete resource reference 2", "!text", "!text");
126        assertTextArray("Incomplete RESOURCE REFERENCE 2", "!TEXT", "!TEXT");
127        assertTextArray("Incomplete resource reference 3", "text/", "text/");
128        assertTextArray("Incomplete resource reference 4", "!" + SURROGATE2, "!" + SURROGATE2);
129    }
130
131    public void testSplitSingleEscaped() {
132        assertTextArray("Escaped char", "\\a", "\\a");
133        assertTextArray("Escaped surrogate pair", "\\" + PAIR1, "\\" + PAIR1);
134        assertTextArray("Escaped comma", "\\,", "\\,");
135        assertTextArray("Escaped comma escape", "a\\,\\", "a\\,\\");
136        assertTextArray("Escaped escape", "\\\\", "\\\\");
137        assertTextArray("Escaped label", "a\\bc", "a\\bc");
138        assertTextArray("Escaped surrogate", "a\\" + PAIR1 + "c", "a\\" + PAIR1 + "c");
139        assertTextArray("Escaped label at beginning", "\\abc", "\\abc");
140        assertTextArray("Escaped surrogate at beginning", "\\" + SURROGATE2, "\\" + SURROGATE2);
141        assertTextArray("Escaped label at end", "abc\\", "abc\\");
142        assertTextArray("Escaped surrogate at end", SURROGATE2 + "\\", SURROGATE2 + "\\");
143        assertTextArray("Escaped label with comma", "a\\,c", "a\\,c");
144        assertTextArray("Escaped surrogate with comma",
145                PAIR1 + "\\," + PAIR2, PAIR1 + "\\," + PAIR2);
146        assertTextArray("Escaped label with comma at beginning", "\\,bc", "\\,bc");
147        assertTextArray("Escaped surrogate with comma at beginning",
148                "\\," + SURROGATE1, "\\," + SURROGATE1);
149        assertTextArray("Escaped label with comma at end", "ab\\,", "ab\\,");
150        assertTextArray("Escaped surrogate with comma at end",
151                SURROGATE2 + "\\,", SURROGATE2 + "\\,");
152        assertTextArray("Escaped label with successive", "\\,\\\\bc", "\\,\\\\bc");
153        assertTextArray("Escaped surrogate with successive",
154                "\\,\\\\" + SURROGATE1, "\\,\\\\" + SURROGATE1);
155        assertTextArray("Escaped label with escape", "a\\\\c", "a\\\\c");
156        assertTextArray("Escaped surrogate with escape",
157                PAIR1 + "\\\\" + PAIR2, PAIR1 + "\\\\" + PAIR2);
158
159        assertTextArray("Escaped !text", "\\!text", "\\!text");
160        assertTextArray("Escaped !text/", "\\!text/", "\\!text/");
161        assertTextArray("Escaped !TEXT/", "\\!TEXT/", "\\!TEXT/");
162        assertTextArray("Escaped !text/name", "\\!text/empty_string", "\\!text/empty_string");
163        assertTextArray("Escaped !TEXT/NAME", "\\!TEXT/EMPTY_STRING", "\\!TEXT/EMPTY_STRING");
164    }
165
166    public void testSplitMulti() {
167        assertTextArray("Multiple chars", "a,b,c", "a", "b", "c");
168        assertTextArray("Multiple chars", "a,b,\\c", "a", "b", "\\c");
169        assertTextArray("Multiple chars and escape at beginning and end",
170                "\\a,b,\\c\\", "\\a", "b", "\\c\\");
171        assertTextArray("Multiple surrogates", PAIR1 + "," + PAIR2 + "," + PAIR3,
172                PAIR1, PAIR2, PAIR3);
173        assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c ");
174        assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi");
175        assertTextArray("Multiple surrogated", SURROGATE1 + "," + SURROGATE2,
176                SURROGATE1, SURROGATE2);
177        assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ",
178                " abc ", " def ", " ghi ");
179    }
180
181    public void testSplitMultiEscaped() {
182        assertTextArray("Multiple chars with comma", "a,\\,,c", "a", "\\,", "c");
183        assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ",
184                " a ", " \\, ", " c ");
185        assertTextArray("Multiple labels with escape",
186                "\\abc,d\\ef,gh\\i", "\\abc", "d\\ef", "gh\\i");
187        assertTextArray("Multiple labels with escape surrounded by spaces",
188                " \\abc , d\\ef , gh\\i ", " \\abc ", " d\\ef ", " gh\\i ");
189        assertTextArray("Multiple labels with comma and escape",
190                "ab\\\\,d\\\\\\,,g\\,i", "ab\\\\", "d\\\\\\,", "g\\,i");
191        assertTextArray("Multiple labels with comma and escape surrounded by spaces",
192                " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
193
194        assertTextArray("Multiple escaped !text", "\\!,\\!text/empty_string",
195                "\\!", "\\!text/empty_string");
196        assertTextArray("Multiple escaped !TEXT", "\\!,\\!TEXT/EMPTY_STRING",
197                "\\!", "\\!TEXT/EMPTY_STRING");
198    }
199
200    public void testSplitTextReferenceError() {
201        assertError("Incomplete text name", "!text/", "!text/");
202        assertError("Non existing text", "!text/non_existing");
203    }
204
205    public void testSplitEmptyTextReference() {
206        // Note that morekeys_q of English locale is empty.
207        assertTextArray("Empty string", "!text/morekeys_q");
208    }
209
210    public void testLabelReferece() {
211        assertTextArray("Label time am", "!text/keylabel_time_am", "AM");
212
213        assertTextArray("More keys for am pm", "!text/morekeys_am_pm",
214                "!fixedColumnOrder!2", "!hasLabels!", "AM", "PM");
215
216        assertTextArray("Settings as more key", "!text/keyspec_settings",
217                "!icon/settings_key|!code/key_settings");
218    }
219
220    public void testUselessUpperCaseSpecifier() {
221        assertTextArray("EMPTY STRING",
222                "!TEXT/EMPTY_STRING", "!TEXT/EMPTY_STRING");
223
224        assertTextArray("SINGLE CHAR",
225                "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_CHAR");
226        assertTextArray("Escape and SINGLE CHAR",
227                "\\\\!TEXT/SINGLE_CHAR", "\\\\!TEXT/SINGLE_CHAR");
228
229        assertTextArray("MULTIPLE CHARS",
230                "!TEXT/MULTIPLE_CHARS", "!TEXT/MULTIPLE_CHARS");
231
232        assertTextArray("Literals and RESOURCES",
233                "1,!TEXT/MULTIPLE_CHARS,z", "1", "!TEXT/MULTIPLE_CHARS", "z");
234        assertTextArray("Multiple single RESOURCE chars and LABELS 2",
235                "!TEXT/SINGLE_CHAR,!TEXT/SINGLE_LABEL,!TEXT/ESCAPED_COMMA_ESCAPE",
236                "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_LABEL", "!TEXT/ESCAPED_COMMA_ESCAPE");
237
238        assertTextArray("INDIRECT",
239                "!TEXT/INDIRECT_STRING", "!TEXT/INDIRECT_STRING");
240        assertTextArray("INDIRECT with literal",
241                "1,!TEXT/INDIRECT_STRING_WITH_LITERAL,2",
242                "1", "!TEXT/INDIRECT_STRING_WITH_LITERAL", "2");
243        assertTextArray("INDIRECT2",
244                "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING");
245
246        assertTextArray("UPPER INDIRECT",
247                "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING");
248        assertTextArray("Upper INDIRECT with literal",
249                "1,!TEXT/upper_INDIRECT_STRING_WITH_LITERAL,2",
250                "1", "!TEXT/upper_INDIRECT_STRING_WITH_LITERAL", "2");
251        assertTextArray("Upper INDIRECT2",
252                "!TEXT/upper_INDIRECT2_STRING", "!TEXT/upper_INDIRECT2_STRING");
253
254        assertTextArray("INFINITE INDIRECTION",
255                "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2");
256
257        assertTextArray("Upper INFINITE INDIRECTION",
258                "1,!TEXT/UPPER_INFINITE_INDIRECTION,2",
259                "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2");
260
261        assertTextArray("LABEL TIME AM", "!TEXT/LABEL_TIME_AM", "!TEXT/LABEL_TIME_AM");
262        assertTextArray("MORE KEYS FOR AM OM", "!TEXT/MORE_KEYS_FOR_AM_PM",
263                "!TEXT/MORE_KEYS_FOR_AM_PM");
264        assertTextArray("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY",
265                "!TEXT/SETTINGS_AS_MORE_KEY");
266        assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY",
267                "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY",
268                "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY");
269     }
270}
271