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