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