• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.inputmethod.keyboard.internal;
18 
19 import android.app.Instrumentation;
20 import android.test.InstrumentationTestCase;
21 import android.test.suitebuilder.annotation.MediumTest;
22 
23 import com.android.inputmethod.latin.CollectionUtils;
24 import com.android.inputmethod.latin.StringUtils;
25 
26 import java.lang.reflect.Field;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Locale;
30 
31 @MediumTest
32 public class KeySpecParserCsvTests extends InstrumentationTestCase {
33     private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
34 
35     @Override
setUp()36     protected void setUp() throws Exception {
37         super.setUp();
38 
39         final Instrumentation instrumentation = getInstrumentation();
40         mTextsSet.setLanguage(Locale.ENGLISH.getLanguage());
41         mTextsSet.loadStringResources(instrumentation.getTargetContext());
42         final String[] testResourceNames = getAllResourceIdNames(
43                 com.android.inputmethod.latin.tests.R.string.class);
44         mTextsSet.loadStringResourcesInternal(instrumentation.getContext(),
45                 testResourceNames,
46                 com.android.inputmethod.latin.tests.R.string.empty_string);
47     }
48 
getAllResourceIdNames(final Class<?> resourceIdClass)49     private static String[] getAllResourceIdNames(final Class<?> resourceIdClass) {
50         final ArrayList<String> names = CollectionUtils.newArrayList();
51         for (final Field field : resourceIdClass.getFields()) {
52             if (field.getType() == Integer.TYPE) {
53                 names.add(field.getName());
54             }
55         }
56         return names.toArray(new String[names.size()]);
57     }
58 
assertArrayEquals(final String message, final Object[] expected, final Object[] actual)59     private static void assertArrayEquals(final String message, final Object[] expected,
60             final Object[] actual) {
61         if (expected == actual) {
62             return;
63         }
64         if (expected == null || actual == null) {
65             assertEquals(message, Arrays.toString(expected), Arrays.toString(actual));
66             return;
67         }
68         if (expected.length != actual.length) {
69             assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual));
70             return;
71         }
72         for (int i = 0; i < expected.length; i++) {
73             assertEquals(message + " [" + i + "]",
74                     Arrays.toString(expected), Arrays.toString(actual));
75         }
76     }
77 
assertTextArray(final String message, final String value, final String ... expectedArray)78     private void assertTextArray(final String message, final String value,
79             final String ... expectedArray) {
80         final String resolvedActual = KeySpecParser.resolveTextReference(value, mTextsSet);
81         final String[] actual = StringUtils.parseCsvString(resolvedActual);
82         final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
83         assertArrayEquals(message, expected, actual);
84     }
85 
assertError(final String message, final String value, final String ... expected)86     private void assertError(final String message, final String value, final String ... expected) {
87         try {
88             assertTextArray(message, value, expected);
89             fail(message);
90         } catch (Exception pcpe) {
91             // success.
92         }
93     }
94 
95     // \U001d11e: MUSICAL SYMBOL G CLEF
96     private static final String PAIR1 = "\ud834\udd1e";
97     // \U001d122: MUSICAL SYMBOL F CLEF
98     private static final String PAIR2 = "\ud834\udd22";
99     // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148.
100     private static final String PAIR3 = "\ud87e\udca6";
101     private static final String SURROGATE1 = PAIR1 + PAIR2;
102     private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
103 
testParseCsvTextZero()104     public void testParseCsvTextZero() {
105         assertTextArray("Empty string", "");
106         assertTextArray("Empty entry", ",");
107         assertTextArray("Empty entry at beginning", ",a", "a");
108         assertTextArray("Empty entry at end", "a,", "a");
109         assertTextArray("Empty entry at middle", "a,,b", "a", "b");
110         assertTextArray("Empty entries with escape", ",a,b\\,c,,d,", "a", "b\\,c", "d");
111     }
112 
testParseCsvTextSingle()113     public void testParseCsvTextSingle() {
114         assertTextArray("Single char", "a", "a");
115         assertTextArray("Surrogate pair", PAIR1, PAIR1);
116         assertTextArray("Single escape", "\\", "\\");
117         assertTextArray("Space", " ", " ");
118         assertTextArray("Single label", "abc", "abc");
119         assertTextArray("Single surrogate pairs label", SURROGATE2, SURROGATE2);
120         assertTextArray("Spaces", "   ", "   ");
121         assertTextArray("Spaces in label", "a b c", "a b c");
122         assertTextArray("Spaces at beginning of label", " abc", " abc");
123         assertTextArray("Spaces at end of label", "abc ", "abc ");
124         assertTextArray("Label surrounded by spaces", " abc ", " abc ");
125         assertTextArray("Surrogate pair surrounded by space",
126                 " " + PAIR1 + " ",
127                 " " + PAIR1 + " ");
128         assertTextArray("Surrogate pair within characters",
129                 "ab" + PAIR2 + "cd",
130                 "ab" + PAIR2 + "cd");
131         assertTextArray("Surrogate pairs within characters",
132                 "ab" + SURROGATE1 + "cd",
133                 "ab" + SURROGATE1 + "cd");
134 
135         assertTextArray("Incomplete resource reference 1", "text", "text");
136         assertTextArray("Incomplete resource reference 2", "!text", "!text");
137         assertTextArray("Incomplete RESOURCE REFERENCE 2", "!TEXT", "!TEXT");
138         assertTextArray("Incomplete resource reference 3", "text/", "text/");
139         assertTextArray("Incomplete resource reference 4", "!" + SURROGATE2, "!" + SURROGATE2);
140     }
141 
testParseCsvTextSingleEscaped()142     public void testParseCsvTextSingleEscaped() {
143         assertTextArray("Escaped char", "\\a", "\\a");
144         assertTextArray("Escaped surrogate pair", "\\" + PAIR1, "\\" + PAIR1);
145         assertTextArray("Escaped comma", "\\,", "\\,");
146         assertTextArray("Escaped comma escape", "a\\,\\", "a\\,\\");
147         assertTextArray("Escaped escape", "\\\\", "\\\\");
148         assertTextArray("Escaped label", "a\\bc", "a\\bc");
149         assertTextArray("Escaped surrogate", "a\\" + PAIR1 + "c", "a\\" + PAIR1 + "c");
150         assertTextArray("Escaped label at beginning", "\\abc", "\\abc");
151         assertTextArray("Escaped surrogate at beginning", "\\" + SURROGATE2, "\\" + SURROGATE2);
152         assertTextArray("Escaped label at end", "abc\\", "abc\\");
153         assertTextArray("Escaped surrogate at end", SURROGATE2 + "\\", SURROGATE2 + "\\");
154         assertTextArray("Escaped label with comma", "a\\,c", "a\\,c");
155         assertTextArray("Escaped surrogate with comma",
156                 PAIR1 + "\\," + PAIR2, PAIR1 + "\\," + PAIR2);
157         assertTextArray("Escaped label with comma at beginning", "\\,bc", "\\,bc");
158         assertTextArray("Escaped surrogate with comma at beginning",
159                 "\\," + SURROGATE1, "\\," + SURROGATE1);
160         assertTextArray("Escaped label with comma at end", "ab\\,", "ab\\,");
161         assertTextArray("Escaped surrogate with comma at end",
162                 SURROGATE2 + "\\,", SURROGATE2 + "\\,");
163         assertTextArray("Escaped label with successive", "\\,\\\\bc", "\\,\\\\bc");
164         assertTextArray("Escaped surrogate with successive",
165                 "\\,\\\\" + SURROGATE1, "\\,\\\\" + SURROGATE1);
166         assertTextArray("Escaped label with escape", "a\\\\c", "a\\\\c");
167         assertTextArray("Escaped surrogate with escape",
168                 PAIR1 + "\\\\" + PAIR2, PAIR1 + "\\\\" + PAIR2);
169 
170         assertTextArray("Escaped !text", "\\!text", "\\!text");
171         assertTextArray("Escaped !text/", "\\!text/", "\\!text/");
172         assertTextArray("Escaped !TEXT/", "\\!TEXT/", "\\!TEXT/");
173         assertTextArray("Escaped !text/name", "\\!text/empty_string", "\\!text/empty_string");
174         assertTextArray("Escaped !TEXT/NAME", "\\!TEXT/EMPTY_STRING", "\\!TEXT/EMPTY_STRING");
175     }
176 
testParseCsvTextMulti()177     public void testParseCsvTextMulti() {
178         assertTextArray("Multiple chars", "a,b,c", "a", "b", "c");
179         assertTextArray("Multiple chars", "a,b,\\c", "a", "b", "\\c");
180         assertTextArray("Multiple chars and escape at beginning and end",
181                 "\\a,b,\\c\\", "\\a", "b", "\\c\\");
182         assertTextArray("Multiple surrogates", PAIR1 + "," + PAIR2 + "," + PAIR3,
183                 PAIR1, PAIR2, PAIR3);
184         assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c ");
185         assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi");
186         assertTextArray("Multiple surrogated", SURROGATE1 + "," + SURROGATE2,
187                 SURROGATE1, SURROGATE2);
188         assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ",
189                 " abc ", " def ", " ghi ");
190     }
191 
testParseCsvTextMultiEscaped()192     public void testParseCsvTextMultiEscaped() {
193         assertTextArray("Multiple chars with comma", "a,\\,,c", "a", "\\,", "c");
194         assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ",
195                 " a ", " \\, ", " c ");
196         assertTextArray("Multiple labels with escape",
197                 "\\abc,d\\ef,gh\\i", "\\abc", "d\\ef", "gh\\i");
198         assertTextArray("Multiple labels with escape surrounded by spaces",
199                 " \\abc , d\\ef , gh\\i ", " \\abc ", " d\\ef ", " gh\\i ");
200         assertTextArray("Multiple labels with comma and escape",
201                 "ab\\\\,d\\\\\\,,g\\,i", "ab\\\\", "d\\\\\\,", "g\\,i");
202         assertTextArray("Multiple labels with comma and escape surrounded by spaces",
203                 " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
204 
205         assertTextArray("Multiple escaped !text", "\\!,\\!text/empty_string",
206                 "\\!", "\\!text/empty_string");
207         assertTextArray("Multiple escaped !TEXT", "\\!,\\!TEXT/EMPTY_STRING",
208                 "\\!", "\\!TEXT/EMPTY_STRING");
209     }
210 
testParseCsvResourceError()211     public void testParseCsvResourceError() {
212         assertError("Incomplete resource name", "!text/", "!text/");
213         assertError("Non existing resource", "!text/non_existing");
214     }
215 
testParseCsvResourceZero()216     public void testParseCsvResourceZero() {
217         assertTextArray("Empty string",
218                 "!text/empty_string");
219     }
220 
testParseCsvResourceSingle()221     public void testParseCsvResourceSingle() {
222         assertTextArray("Single char",
223                 "!text/single_char", "a");
224         assertTextArray("Space",
225                 "!text/space", " ");
226         assertTextArray("Single label",
227                 "!text/single_label", "abc");
228         assertTextArray("Spaces",
229                 "!text/spaces", "   ");
230         assertTextArray("Spaces in label",
231                 "!text/spaces_in_label", "a b c");
232         assertTextArray("Spaces at beginning of label",
233                 "!text/spaces_at_beginning_of_label", " abc");
234         assertTextArray("Spaces at end of label",
235                 "!text/spaces_at_end_of_label", "abc ");
236         assertTextArray("label surrounded by spaces",
237                 "!text/label_surrounded_by_spaces", " abc ");
238 
239         assertTextArray("Escape and single char",
240                 "\\\\!text/single_char", "\\\\a");
241     }
242 
testParseCsvResourceSingleEscaped()243     public void testParseCsvResourceSingleEscaped() {
244         assertTextArray("Escaped char",
245                 "!text/escaped_char", "\\a");
246         assertTextArray("Escaped comma",
247                 "!text/escaped_comma", "\\,");
248         assertTextArray("Escaped comma escape",
249                 "!text/escaped_comma_escape", "a\\,\\");
250         assertTextArray("Escaped escape",
251                 "!text/escaped_escape", "\\\\");
252         assertTextArray("Escaped label",
253                 "!text/escaped_label", "a\\bc");
254         assertTextArray("Escaped label at beginning",
255                 "!text/escaped_label_at_beginning", "\\abc");
256         assertTextArray("Escaped label at end",
257                 "!text/escaped_label_at_end", "abc\\");
258         assertTextArray("Escaped label with comma",
259                 "!text/escaped_label_with_comma", "a\\,c");
260         assertTextArray("Escaped label with comma at beginning",
261                 "!text/escaped_label_with_comma_at_beginning", "\\,bc");
262         assertTextArray("Escaped label with comma at end",
263                 "!text/escaped_label_with_comma_at_end", "ab\\,");
264         assertTextArray("Escaped label with successive",
265                 "!text/escaped_label_with_successive", "\\,\\\\bc");
266         assertTextArray("Escaped label with escape",
267                 "!text/escaped_label_with_escape", "a\\\\c");
268     }
269 
testParseCsvResourceMulti()270     public void testParseCsvResourceMulti() {
271         assertTextArray("Multiple chars",
272                 "!text/multiple_chars", "a", "b", "c");
273         assertTextArray("Multiple chars surrounded by spaces",
274                 "!text/multiple_chars_surrounded_by_spaces",
275                 " a ", " b ", " c ");
276         assertTextArray("Multiple labels",
277                 "!text/multiple_labels", "abc", "def", "ghi");
278         assertTextArray("Multiple labels surrounded by spaces",
279                 "!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
280     }
281 
testParseCsvResourcetMultiEscaped()282     public void testParseCsvResourcetMultiEscaped() {
283         assertTextArray("Multiple chars with comma",
284                 "!text/multiple_chars_with_comma",
285                 "a", "\\,", "c");
286         assertTextArray("Multiple chars with comma surrounded by spaces",
287                 "!text/multiple_chars_with_comma_surrounded_by_spaces",
288                 " a ", " \\, ", " c ");
289         assertTextArray("Multiple labels with escape",
290                 "!text/multiple_labels_with_escape",
291                 "\\abc", "d\\ef", "gh\\i");
292         assertTextArray("Multiple labels with escape surrounded by spaces",
293                 "!text/multiple_labels_with_escape_surrounded_by_spaces",
294                 " \\abc ", " d\\ef ", " gh\\i ");
295         assertTextArray("Multiple labels with comma and escape",
296                 "!text/multiple_labels_with_comma_and_escape",
297                 "ab\\\\", "d\\\\\\,", "g\\,i");
298         assertTextArray("Multiple labels with comma and escape surrounded by spaces",
299                 "!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
300                 " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
301     }
302 
testParseMultipleResources()303     public void testParseMultipleResources() {
304         assertTextArray("Literals and resources",
305                 "1,!text/multiple_chars,z", "1", "a", "b", "c", "z");
306         assertTextArray("Literals and resources and escape at end",
307                 "\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\");
308         assertTextArray("Multiple single resource chars and labels",
309                 "!text/single_char,!text/single_label,!text/escaped_comma",
310                 "a", "abc", "\\,");
311         assertTextArray("Multiple single resource chars and labels 2",
312                 "!text/single_char,!text/single_label,!text/escaped_comma_escape",
313                 "a", "abc", "a\\,\\");
314         assertTextArray("Multiple multiple resource chars and labels",
315                 "!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma",
316                 "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
317         assertTextArray("Concatenated resources",
318                 "!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma",
319                 "a", "b", "cabc", "def", "ghia", "\\,", "c");
320         assertTextArray("Concatenated resource and literal",
321                 "abc!text/multiple_labels",
322                 "abcabc", "def", "ghi");
323     }
324 
testParseIndirectReference()325     public void testParseIndirectReference() {
326         assertTextArray("Indirect",
327                 "!text/indirect_string", "a", "b", "c");
328         assertTextArray("Indirect with literal",
329                 "1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
330         assertTextArray("Indirect2",
331                 "!text/indirect2_string", "a", "b", "c");
332     }
333 
testParseInfiniteIndirectReference()334     public void testParseInfiniteIndirectReference() {
335         assertError("Infinite indirection",
336                 "1,!text/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
337     }
338 
testLabelReferece()339     public void testLabelReferece() {
340         assertTextArray("Label time am", "!text/label_time_am", "AM");
341 
342         assertTextArray("More keys for am pm", "!text/more_keys_for_am_pm",
343                 "!fixedColumnOrder!2", "!hasLabels!", "AM", "PM");
344 
345         assertTextArray("Settings as more key", "!text/settings_as_more_key",
346                 "!icon/settings_key|!code/key_settings");
347 
348         assertTextArray("Indirect naviagte actions as more key",
349                 "!text/indirect_navigate_actions_as_more_key",
350                 "!fixedColumnOrder!2",
351                 "!hasLabels!", "Prev|!code/key_action_previous",
352                 "!hasLabels!", "Next|!code/key_action_next");
353     }
354 
testUselessUpperCaseSpecifier()355     public void testUselessUpperCaseSpecifier() {
356         assertTextArray("EMPTY STRING",
357                 "!TEXT/EMPTY_STRING", "!TEXT/EMPTY_STRING");
358 
359         assertTextArray("SINGLE CHAR",
360                 "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_CHAR");
361         assertTextArray("Escape and SINGLE CHAR",
362                 "\\\\!TEXT/SINGLE_CHAR", "\\\\!TEXT/SINGLE_CHAR");
363 
364         assertTextArray("MULTIPLE CHARS",
365                 "!TEXT/MULTIPLE_CHARS", "!TEXT/MULTIPLE_CHARS");
366 
367         assertTextArray("Literals and RESOURCES",
368                 "1,!TEXT/MULTIPLE_CHARS,z", "1", "!TEXT/MULTIPLE_CHARS", "z");
369         assertTextArray("Multiple single RESOURCE chars and LABELS 2",
370                 "!TEXT/SINGLE_CHAR,!TEXT/SINGLE_LABEL,!TEXT/ESCAPED_COMMA_ESCAPE",
371                 "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_LABEL", "!TEXT/ESCAPED_COMMA_ESCAPE");
372 
373         assertTextArray("INDIRECT",
374                 "!TEXT/INDIRECT_STRING", "!TEXT/INDIRECT_STRING");
375         assertTextArray("INDIRECT with literal",
376                 "1,!TEXT/INDIRECT_STRING_WITH_LITERAL,2",
377                 "1", "!TEXT/INDIRECT_STRING_WITH_LITERAL", "2");
378         assertTextArray("INDIRECT2",
379                 "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING");
380 
381         assertTextArray("Upper indirect",
382                 "!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS");
383         assertTextArray("Upper indirect with literal",
384                 "1,!text/upper_indirect_string_with_literal,2",
385                 "1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2");
386         assertTextArray("Upper indirect2",
387                 "!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING");
388 
389         assertTextArray("UPPER INDIRECT",
390                 "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING");
391         assertTextArray("Upper INDIRECT with literal",
392                 "1,!TEXT/upper_INDIRECT_STRING_WITH_LITERAL,2",
393                 "1", "!TEXT/upper_INDIRECT_STRING_WITH_LITERAL", "2");
394         assertTextArray("Upper INDIRECT2",
395                 "!TEXT/upper_INDIRECT2_STRING", "!TEXT/upper_INDIRECT2_STRING");
396 
397         assertTextArray("INFINITE INDIRECTION",
398                 "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2");
399 
400         assertTextArray("Upper infinite indirection",
401                 "1,!text/upper_infinite_indirection,2",
402                 "1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2");
403         assertTextArray("Upper INFINITE INDIRECTION",
404                 "1,!TEXT/UPPER_INFINITE_INDIRECTION,2",
405                 "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2");
406 
407         assertTextArray("LABEL TIME AM", "!TEXT/LABEL_TIME_AM", "!TEXT/LABEL_TIME_AM");
408         assertTextArray("MORE KEYS FOR AM OM", "!TEXT/MORE_KEYS_FOR_AM_PM",
409                 "!TEXT/MORE_KEYS_FOR_AM_PM");
410         assertTextArray("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY",
411                 "!TEXT/SETTINGS_AS_MORE_KEY");
412         assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY",
413                 "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY",
414                 "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY");
415      }
416 }
417