Home | History | Annotate | Download | only in internal
      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 
     17 package com.android.inputmethod.keyboard.internal;
     18 
     19 import android.test.AndroidTestCase;
     20 
     21 import java.lang.reflect.Field;
     22 import java.util.ArrayList;
     23 import java.util.Arrays;
     24 import java.util.Locale;
     25 
     26 public class KeySpecParserCsvTests extends AndroidTestCase {
     27     private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
     28 
     29     @Override
     30     protected void setUp() throws Exception {
     31         super.setUp();
     32 
     33         mTextsSet.setLanguage(Locale.ENGLISH.getLanguage());
     34         mTextsSet.loadStringResources(getContext());
     35         final String[] testResourceNames = getAllResourceIdNames(
     36                 com.android.inputmethod.latin.tests.R.string.class);
     37         mTextsSet.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, mTextsSet);
     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", "text", "text");
    126         assertTextArray("Incomplete resource reference 2", "!text", "!text");
    127         assertTextArray("Incomplete RESOURCE REFERENCE 2", "!TEXT", "!TEXT");
    128         assertTextArray("Incomplete resource reference 3", "text/", "text/");
    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 !text", "\\!text", "\\!text");
    161         assertTextArray("Escaped !text/", "\\!text/", "\\!text/");
    162         assertTextArray("Escaped !TEXT/", "\\!TEXT/", "\\!TEXT/");
    163         assertTextArray("Escaped !text/name", "\\!text/empty_string", "\\!text/empty_string");
    164         assertTextArray("Escaped !TEXT/NAME", "\\!TEXT/EMPTY_STRING", "\\!TEXT/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 !text", "\\!,\\!text/empty_string",
    196                 "\\!", "\\!text/empty_string");
    197         assertTextArray("Multiple escaped !TEXT", "\\!,\\!TEXT/EMPTY_STRING",
    198                 "\\!", "\\!TEXT/EMPTY_STRING");
    199     }
    200 
    201     public void testParseCsvResourceError() {
    202         assertError("Incomplete resource name", "!text/", "!text/");
    203         assertError("Non existing resource", "!text/non_existing");
    204     }
    205 
    206     public void testParseCsvResourceZero() {
    207         assertTextArray("Empty string",
    208                 "!text/empty_string");
    209     }
    210 
    211     public void testParseCsvResourceSingle() {
    212         assertTextArray("Single char",
    213                 "!text/single_char", "a");
    214         assertTextArray("Space",
    215                 "!text/space", " ");
    216         assertTextArray("Single label",
    217                 "!text/single_label", "abc");
    218         assertTextArray("Spaces",
    219                 "!text/spaces", "   ");
    220         assertTextArray("Spaces in label",
    221                 "!text/spaces_in_label", "a b c");
    222         assertTextArray("Spaces at beginning of label",
    223                 "!text/spaces_at_beginning_of_label", " abc");
    224         assertTextArray("Spaces at end of label",
    225                 "!text/spaces_at_end_of_label", "abc ");
    226         assertTextArray("label surrounded by spaces",
    227                 "!text/label_surrounded_by_spaces", " abc ");
    228 
    229         assertTextArray("Escape and single char",
    230                 "\\\\!text/single_char", "\\\\a");
    231     }
    232 
    233     public void testParseCsvResourceSingleEscaped() {
    234         assertTextArray("Escaped char",
    235                 "!text/escaped_char", "\\a");
    236         assertTextArray("Escaped comma",
    237                 "!text/escaped_comma", "\\,");
    238         assertTextArray("Escaped comma escape",
    239                 "!text/escaped_comma_escape", "a\\,\\");
    240         assertTextArray("Escaped escape",
    241                 "!text/escaped_escape", "\\\\");
    242         assertTextArray("Escaped label",
    243                 "!text/escaped_label", "a\\bc");
    244         assertTextArray("Escaped label at beginning",
    245                 "!text/escaped_label_at_beginning", "\\abc");
    246         assertTextArray("Escaped label at end",
    247                 "!text/escaped_label_at_end", "abc\\");
    248         assertTextArray("Escaped label with comma",
    249                 "!text/escaped_label_with_comma", "a\\,c");
    250         assertTextArray("Escaped label with comma at beginning",
    251                 "!text/escaped_label_with_comma_at_beginning", "\\,bc");
    252         assertTextArray("Escaped label with comma at end",
    253                 "!text/escaped_label_with_comma_at_end", "ab\\,");
    254         assertTextArray("Escaped label with successive",
    255                 "!text/escaped_label_with_successive", "\\,\\\\bc");
    256         assertTextArray("Escaped label with escape",
    257                 "!text/escaped_label_with_escape", "a\\\\c");
    258     }
    259 
    260     public void testParseCsvResourceMulti() {
    261         assertTextArray("Multiple chars",
    262                 "!text/multiple_chars", "a", "b", "c");
    263         assertTextArray("Multiple chars surrounded by spaces",
    264                 "!text/multiple_chars_surrounded_by_spaces",
    265                 " a ", " b ", " c ");
    266         assertTextArray("Multiple labels",
    267                 "!text/multiple_labels", "abc", "def", "ghi");
    268         assertTextArray("Multiple labels surrounded by spaces",
    269                 "!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
    270     }
    271 
    272     public void testParseCsvResourcetMultiEscaped() {
    273         assertTextArray("Multiple chars with comma",
    274                 "!text/multiple_chars_with_comma",
    275                 "a", "\\,", "c");
    276         assertTextArray("Multiple chars with comma surrounded by spaces",
    277                 "!text/multiple_chars_with_comma_surrounded_by_spaces",
    278                 " a ", " \\, ", " c ");
    279         assertTextArray("Multiple labels with escape",
    280                 "!text/multiple_labels_with_escape",
    281                 "\\abc", "d\\ef", "gh\\i");
    282         assertTextArray("Multiple labels with escape surrounded by spaces",
    283                 "!text/multiple_labels_with_escape_surrounded_by_spaces",
    284                 " \\abc ", " d\\ef ", " gh\\i ");
    285         assertTextArray("Multiple labels with comma and escape",
    286                 "!text/multiple_labels_with_comma_and_escape",
    287                 "ab\\\\", "d\\\\\\,", "g\\,i");
    288         assertTextArray("Multiple labels with comma and escape surrounded by spaces",
    289                 "!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
    290                 " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
    291     }
    292 
    293     public void testParseMultipleResources() {
    294         assertTextArray("Literals and resources",
    295                 "1,!text/multiple_chars,z", "1", "a", "b", "c", "z");
    296         assertTextArray("Literals and resources and escape at end",
    297                 "\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\");
    298         assertTextArray("Multiple single resource chars and labels",
    299                 "!text/single_char,!text/single_label,!text/escaped_comma",
    300                 "a", "abc", "\\,");
    301         assertTextArray("Multiple single resource chars and labels 2",
    302                 "!text/single_char,!text/single_label,!text/escaped_comma_escape",
    303                 "a", "abc", "a\\,\\");
    304         assertTextArray("Multiple multiple resource chars and labels",
    305                 "!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma",
    306                 "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
    307         assertTextArray("Concatenated resources",
    308                 "!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma",
    309                 "a", "b", "cabc", "def", "ghia", "\\,", "c");
    310         assertTextArray("Concatenated resource and literal",
    311                 "abc!text/multiple_labels",
    312                 "abcabc", "def", "ghi");
    313     }
    314 
    315     public void testParseIndirectReference() {
    316         assertTextArray("Indirect",
    317                 "!text/indirect_string", "a", "b", "c");
    318         assertTextArray("Indirect with literal",
    319                 "1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
    320         assertTextArray("Indirect2",
    321                 "!text/indirect2_string", "a", "b", "c");
    322     }
    323 
    324     public void testParseInfiniteIndirectReference() {
    325         assertError("Infinite indirection",
    326                 "1,!text/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
    327     }
    328 
    329     public void testLabelReferece() {
    330         assertTextArray("Label time am", "!text/label_time_am", "AM");
    331 
    332         assertTextArray("More keys for am pm", "!text/more_keys_for_am_pm",
    333                 "!fixedColumnOrder!2", "!hasLabels!", "AM", "PM");
    334 
    335         assertTextArray("Settings as more key", "!text/settings_as_more_key",
    336                 "!icon/settings_key|!code/key_settings");
    337 
    338         assertTextArray("Indirect naviagte actions as more key",
    339                 "!text/indirect_navigate_actions_as_more_key",
    340                 "!fixedColumnOrder!2",
    341                 "!hasLabels!", "Prev|!code/key_action_previous",
    342                 "!hasLabels!", "Next|!code/key_action_next");
    343     }
    344 
    345     public void testUselessUpperCaseSpecifier() {
    346         assertTextArray("EMPTY STRING",
    347                 "!TEXT/EMPTY_STRING", "!TEXT/EMPTY_STRING");
    348 
    349         assertTextArray("SINGLE CHAR",
    350                 "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_CHAR");
    351         assertTextArray("Escape and SINGLE CHAR",
    352                 "\\\\!TEXT/SINGLE_CHAR", "\\\\!TEXT/SINGLE_CHAR");
    353 
    354         assertTextArray("MULTIPLE CHARS",
    355                 "!TEXT/MULTIPLE_CHARS", "!TEXT/MULTIPLE_CHARS");
    356 
    357         assertTextArray("Literals and RESOURCES",
    358                 "1,!TEXT/MULTIPLE_CHARS,z", "1", "!TEXT/MULTIPLE_CHARS", "z");
    359         assertTextArray("Multiple single RESOURCE chars and LABELS 2",
    360                 "!TEXT/SINGLE_CHAR,!TEXT/SINGLE_LABEL,!TEXT/ESCAPED_COMMA_ESCAPE",
    361                 "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_LABEL", "!TEXT/ESCAPED_COMMA_ESCAPE");
    362 
    363         assertTextArray("INDIRECT",
    364                 "!TEXT/INDIRECT_STRING", "!TEXT/INDIRECT_STRING");
    365         assertTextArray("INDIRECT with literal",
    366                 "1,!TEXT/INDIRECT_STRING_WITH_LITERAL,2",
    367                 "1", "!TEXT/INDIRECT_STRING_WITH_LITERAL", "2");
    368         assertTextArray("INDIRECT2",
    369                 "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING");
    370 
    371         assertTextArray("Upper indirect",
    372                 "!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS");
    373         assertTextArray("Upper indirect with literal",
    374                 "1,!text/upper_indirect_string_with_literal,2",
    375                 "1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2");
    376         assertTextArray("Upper indirect2",
    377                 "!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING");
    378 
    379         assertTextArray("UPPER INDIRECT",
    380                 "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING");
    381         assertTextArray("Upper INDIRECT with literal",
    382                 "1,!TEXT/upper_INDIRECT_STRING_WITH_LITERAL,2",
    383                 "1", "!TEXT/upper_INDIRECT_STRING_WITH_LITERAL", "2");
    384         assertTextArray("Upper INDIRECT2",
    385                 "!TEXT/upper_INDIRECT2_STRING", "!TEXT/upper_INDIRECT2_STRING");
    386 
    387         assertTextArray("INFINITE INDIRECTION",
    388                 "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2");
    389 
    390         assertTextArray("Upper infinite indirection",
    391                 "1,!text/upper_infinite_indirection,2",
    392                 "1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2");
    393         assertTextArray("Upper INFINITE INDIRECTION",
    394                 "1,!TEXT/UPPER_INFINITE_INDIRECTION,2",
    395                 "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2");
    396 
    397         assertTextArray("LABEL TIME AM", "!TEXT/LABEL_TIME_AM", "!TEXT/LABEL_TIME_AM");
    398         assertTextArray("MORE KEYS FOR AM OM", "!TEXT/MORE_KEYS_FOR_AM_PM",
    399                 "!TEXT/MORE_KEYS_FOR_AM_PM");
    400         assertTextArray("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY",
    401                 "!TEXT/SETTINGS_AS_MORE_KEY");
    402         assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY",
    403                 "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY",
    404                 "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY");
    405      }
    406 }
    407