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