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");
      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
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    226     public void testSplitResourceError() {
    227         assertError("Incomplete resource name", "!text/", "!text/");
    228         assertError("Non existing resource", "!text/non_existing");
    229     }
    230 
    231     public void testSplitResourceZero() {
    232         assertTextArray("Empty string",
    233                 "!text/empty_string");
    234     }
    235 
    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 
    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 
    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 
    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 
    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 
    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 
    349     public void testSplitInfiniteIndirectReference() {
    350         assertError("Infinite indirection",
    351                 "1,!text/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
    352     }
    353 
    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 
    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