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