InputLogicTests.java revision 73a2426d455e6e83dd9402913889f80a0071f0ac
1/* 2 * Copyright (C) 2012 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 17package com.android.inputmethod.latin; 18 19import android.test.suitebuilder.annotation.LargeTest; 20import android.view.inputmethod.BaseInputConnection; 21 22@LargeTest 23public class InputLogicTests extends InputTestsBase { 24 25 public void testTypeWord() { 26 final String WORD_TO_TYPE = "abcd"; 27 type(WORD_TO_TYPE); 28 assertEquals("type word", WORD_TO_TYPE, mEditText.getText().toString()); 29 } 30 31 public void testPickSuggestionThenBackspace() { 32 final String WORD_TO_TYPE = "this"; 33 final String EXPECTED_RESULT = "thi"; 34 type(WORD_TO_TYPE); 35 pickSuggestionManually(0, WORD_TO_TYPE); 36 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 37 type(Constants.CODE_DELETE); 38 assertEquals("press suggestion then backspace", EXPECTED_RESULT, 39 mEditText.getText().toString()); 40 } 41 42 public void testPickAutoCorrectionThenBackspace() { 43 final String WORD_TO_TYPE = "tgis"; 44 final String WORD_TO_PICK = "this"; 45 final String EXPECTED_RESULT = "thi"; 46 type(WORD_TO_TYPE); 47 // Choose the auto-correction, which is always in position 0. For "tgis", the 48 // auto-correction should be "this". 49 pickSuggestionManually(0, WORD_TO_PICK); 50 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 51 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, 52 mEditText.getText().toString()); 53 type(Constants.CODE_DELETE); 54 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 55 mEditText.getText().toString()); 56 } 57 58 public void testPickTypedWordOverAutoCorrectionThenBackspace() { 59 final String WORD_TO_TYPE = "tgis"; 60 final String EXPECTED_RESULT = "tgi"; 61 type(WORD_TO_TYPE); 62 // Choose the typed word, which should be in position 1 (because position 0 should 63 // be occupied by the "this" auto-correction, as checked by testAutoCorrect()) 64 pickSuggestionManually(1, WORD_TO_TYPE); 65 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 66 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, 67 mEditText.getText().toString()); 68 type(Constants.CODE_DELETE); 69 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 70 mEditText.getText().toString()); 71 } 72 73 public void testPickDifferentSuggestionThenBackspace() { 74 final String WORD_TO_TYPE = "tgis"; 75 final String WORD_TO_PICK = "thus"; 76 final String EXPECTED_RESULT = "thu"; 77 type(WORD_TO_TYPE); 78 // Choose the second suggestion, which should be in position 2 and should be "thus" 79 // when "tgis is typed. 80 pickSuggestionManually(2, WORD_TO_PICK); 81 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 82 assertEquals("pick different suggestion then backspace", WORD_TO_PICK, 83 mEditText.getText().toString()); 84 type(Constants.CODE_DELETE); 85 assertEquals("pick different suggestion then backspace", EXPECTED_RESULT, 86 mEditText.getText().toString()); 87 } 88 89 public void testDeleteSelection() { 90 final String STRING_TO_TYPE = "some text delete me some text"; 91 final int typedLength = STRING_TO_TYPE.length(); 92 final int SELECTION_START = 10; 93 final int SELECTION_END = 19; 94 final String EXPECTED_RESULT = "some text some text"; 95 type(STRING_TO_TYPE); 96 // There is no IMF to call onUpdateSelection for us so we must do it by hand. 97 // Send once to simulate the cursor actually responding to the move caused by typing. 98 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 99 // move with a move triggered by LatinIME inputting stuff. 100 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 101 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 102 // And now we simulate the user actually selecting some text. 103 mLatinIME.onUpdateSelection(typedLength, typedLength, 104 SELECTION_START, SELECTION_END, -1, -1); 105 type(Constants.CODE_DELETE); 106 assertEquals("delete selection", EXPECTED_RESULT, mEditText.getText().toString()); 107 } 108 109 public void testDeleteSelectionTwice() { 110 final String STRING_TO_TYPE = "some text delete me some text"; 111 final int typedLength = STRING_TO_TYPE.length(); 112 final int SELECTION_START = 10; 113 final int SELECTION_END = 19; 114 final String EXPECTED_RESULT = "some text some text"; 115 type(STRING_TO_TYPE); 116 // There is no IMF to call onUpdateSelection for us so we must do it by hand. 117 // Send once to simulate the cursor actually responding to the move caused by typing. 118 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 119 // move with a move triggered by LatinIME inputting stuff. 120 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 121 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 122 // And now we simulate the user actually selecting some text. 123 mLatinIME.onUpdateSelection(typedLength, typedLength, 124 SELECTION_START, SELECTION_END, -1, -1); 125 type(Constants.CODE_DELETE); 126 type(Constants.CODE_DELETE); 127 assertEquals("delete selection twice", EXPECTED_RESULT, mEditText.getText().toString()); 128 } 129 130 public void testAutoCorrect() { 131 final String STRING_TO_TYPE = "tgis "; 132 final String EXPECTED_RESULT = "this "; 133 type(STRING_TO_TYPE); 134 assertEquals("simple auto-correct", EXPECTED_RESULT, mEditText.getText().toString()); 135 } 136 137 public void testAutoCorrectWithQuote() { 138 final String STRING_TO_TYPE = "didn' "; 139 final String EXPECTED_RESULT = "didn't "; 140 type(STRING_TO_TYPE); 141 assertEquals("auto-correct with quote", EXPECTED_RESULT, mEditText.getText().toString()); 142 } 143 144 public void testAutoCorrectWithPeriod() { 145 final String STRING_TO_TYPE = "tgis."; 146 final String EXPECTED_RESULT = "this."; 147 type(STRING_TO_TYPE); 148 assertEquals("auto-correct with period", EXPECTED_RESULT, mEditText.getText().toString()); 149 } 150 151 public void testAutoCorrectWithPeriodThenRevert() { 152 final String STRING_TO_TYPE = "tgis."; 153 final String EXPECTED_RESULT = "tgis."; 154 type(STRING_TO_TYPE); 155 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 156 type(Constants.CODE_DELETE); 157 assertEquals("auto-correct with period then revert", EXPECTED_RESULT, 158 mEditText.getText().toString()); 159 } 160 161 public void testAutoCorrectWithSpaceThenRevert() { 162 final String STRING_TO_TYPE = "tgis "; 163 final String EXPECTED_RESULT = "tgis "; 164 type(STRING_TO_TYPE); 165 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 166 type(Constants.CODE_DELETE); 167 assertEquals("auto-correct with space then revert", EXPECTED_RESULT, 168 mEditText.getText().toString()); 169 } 170 171 public void testAutoCorrectToSelfDoesNotRevert() { 172 final String STRING_TO_TYPE = "this "; 173 final String EXPECTED_RESULT = "this"; 174 type(STRING_TO_TYPE); 175 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 176 type(Constants.CODE_DELETE); 177 assertEquals("auto-correct with space does not revert", EXPECTED_RESULT, 178 mEditText.getText().toString()); 179 } 180 181 public void testDoubleSpace() { 182 // U+1F607 is an emoji 183 final String[] STRINGS_TO_TYPE = 184 new String[] { "this ", "a+ ", "\u1F607 ", ".. ", ") ", "( ", "% " }; 185 final String[] EXPECTED_RESULTS = 186 new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "%. " }; 187 for (int i = 0; i < STRINGS_TO_TYPE.length; ++i) { 188 mEditText.setText(""); 189 type(STRINGS_TO_TYPE[i]); 190 assertEquals("double space processing", EXPECTED_RESULTS[i], 191 mEditText.getText().toString()); 192 } 193 } 194 195 public void testCancelDoubleSpace() { 196 final String STRING_TO_TYPE = "this "; 197 final String EXPECTED_RESULT = "this "; 198 type(STRING_TO_TYPE); 199 type(Constants.CODE_DELETE); 200 assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString()); 201 } 202 203 public void testBackspaceAtStartAfterAutocorrect() { 204 final String STRING_TO_TYPE = "tgis "; 205 final int typedLength = STRING_TO_TYPE.length(); 206 final String EXPECTED_RESULT = "this "; 207 final int NEW_CURSOR_POSITION = 0; 208 type(STRING_TO_TYPE); 209 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 210 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 211 mLatinIME.onUpdateSelection(typedLength, typedLength, 212 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 213 type(Constants.CODE_DELETE); 214 assertEquals("auto correct then move cursor to start of line then backspace", 215 EXPECTED_RESULT, mEditText.getText().toString()); 216 } 217 218 public void testAutoCorrectThenMoveCursorThenBackspace() { 219 final String STRING_TO_TYPE = "and tgis "; 220 final int typedLength = STRING_TO_TYPE.length(); 221 final String EXPECTED_RESULT = "andthis "; 222 final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t'); 223 type(STRING_TO_TYPE); 224 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 225 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 226 mLatinIME.onUpdateSelection(typedLength, typedLength, 227 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 228 type(Constants.CODE_DELETE); 229 assertEquals("auto correct then move cursor then backspace", 230 EXPECTED_RESULT, mEditText.getText().toString()); 231 } 232 233 public void testNoSpaceAfterManualPick() { 234 final String WORD_TO_TYPE = "this"; 235 final String EXPECTED_RESULT = WORD_TO_TYPE; 236 type(WORD_TO_TYPE); 237 pickSuggestionManually(0, WORD_TO_TYPE); 238 assertEquals("no space after manual pick", EXPECTED_RESULT, 239 mEditText.getText().toString()); 240 } 241 242 public void testManualPickThenType() { 243 final String WORD1_TO_TYPE = "this"; 244 final String WORD2_TO_TYPE = "is"; 245 final String EXPECTED_RESULT = "this is"; 246 type(WORD1_TO_TYPE); 247 pickSuggestionManually(0, WORD1_TO_TYPE); 248 type(WORD2_TO_TYPE); 249 assertEquals("manual pick then type", EXPECTED_RESULT, mEditText.getText().toString()); 250 } 251 252 public void testManualPickThenSeparator() { 253 final String WORD1_TO_TYPE = "this"; 254 final String WORD2_TO_TYPE = "!"; 255 final String EXPECTED_RESULT = "this!"; 256 type(WORD1_TO_TYPE); 257 pickSuggestionManually(0, WORD1_TO_TYPE); 258 type(WORD2_TO_TYPE); 259 assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString()); 260 } 261 262 public void testManualPickThenStripperThenPick() { 263 final String WORD_TO_TYPE = "this"; 264 final String STRIPPER = "\n"; 265 final String EXPECTED_RESULT = "this\nthis"; 266 type(WORD_TO_TYPE); 267 pickSuggestionManually(0, WORD_TO_TYPE); 268 type(STRIPPER); 269 type(WORD_TO_TYPE); 270 pickSuggestionManually(0, WORD_TO_TYPE); 271 assertEquals("manual pick then \\n then manual pick", EXPECTED_RESULT, 272 mEditText.getText().toString()); 273 } 274 275 public void testManualPickThenSpaceThenType() { 276 final String WORD1_TO_TYPE = "this"; 277 final String WORD2_TO_TYPE = " is"; 278 final String EXPECTED_RESULT = "this is"; 279 type(WORD1_TO_TYPE); 280 pickSuggestionManually(0, WORD1_TO_TYPE); 281 type(WORD2_TO_TYPE); 282 assertEquals("manual pick then space then type", EXPECTED_RESULT, 283 mEditText.getText().toString()); 284 } 285 286 public void testManualPickThenManualPick() { 287 final String WORD1_TO_TYPE = "this"; 288 final String WORD2_TO_PICK = "is"; 289 final String EXPECTED_RESULT = "this is"; 290 type(WORD1_TO_TYPE); 291 pickSuggestionManually(0, WORD1_TO_TYPE); 292 // Here we fake picking a word through bigram prediction. This test is taking 293 // advantage of the fact that Latin IME blindly trusts the caller of #pickSuggestionManually 294 // to actually pass the right string. 295 pickSuggestionManually(1, WORD2_TO_PICK); 296 assertEquals("manual pick then manual pick", EXPECTED_RESULT, 297 mEditText.getText().toString()); 298 } 299 300 public void testDeleteWholeComposingWord() { 301 final String WORD_TO_TYPE = "this"; 302 type(WORD_TO_TYPE); 303 for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { 304 type(Constants.CODE_DELETE); 305 } 306 assertEquals("delete whole composing word", "", mEditText.getText().toString()); 307 } 308 309 public void testResumeSuggestionOnBackspace() { 310 final String STRING_TO_TYPE = "and this "; 311 final int typedLength = STRING_TO_TYPE.length(); 312 type(STRING_TO_TYPE); 313 assertEquals("resume suggestion on backspace", -1, 314 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 315 assertEquals("resume suggestion on backspace", -1, 316 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 317 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 318 type(Constants.CODE_DELETE); 319 assertEquals("resume suggestion on backspace", 4, 320 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 321 assertEquals("resume suggestion on backspace", 8, 322 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 323 } 324 325 private void helperTestComposing(final String wordToType, final boolean shouldBeComposing) { 326 mEditText.setText(""); 327 type(wordToType); 328 assertEquals("start composing inside text", shouldBeComposing ? 0 : -1, 329 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 330 assertEquals("start composing inside text", shouldBeComposing ? wordToType.length() : -1, 331 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 332 } 333 334 public void testStartComposing() { 335 // Should start composing on a letter 336 helperTestComposing("a", true); 337 type(" "); // To reset the composing state 338 // Should not start composing on quote 339 helperTestComposing("'", false); 340 type(" "); 341 helperTestComposing("'-", false); 342 type(" "); 343 // Should not start composing on dash 344 helperTestComposing("-", false); 345 type(" "); 346 helperTestComposing("-'", false); 347 type(" "); 348 helperTestComposing("a-", true); 349 type(" "); 350 helperTestComposing("a'", true); 351 } 352 // TODO: Add some tests for non-BMP characters 353 354 public void testAutoCorrectByUserHistory() { 355 final String WORD_TO_BE_CORRECTED = "qpmx"; 356 final String NOT_CORRECTED_RESULT = "qpmx "; 357 final String DESIRED_WORD = "qpmz"; 358 final String CORRECTED_RESULT = "qpmz "; 359 final int typeCountNotToAutocorrect = 1; 360 final int typeCountToAutoCorrect = 16; 361 int startIndex = 0; 362 int endIndex = 0; 363 364 for (int i = 0; i < typeCountNotToAutocorrect; i++) { 365 type(DESIRED_WORD); 366 type(Constants.CODE_SPACE); 367 } 368 startIndex = mEditText.getText().length(); 369 type(WORD_TO_BE_CORRECTED); 370 type(Constants.CODE_SPACE); 371 endIndex = mEditText.getText().length(); 372 assertEquals("not auto-corrected by user history", NOT_CORRECTED_RESULT, 373 mEditText.getText().subSequence(startIndex, endIndex).toString()); 374 for (int i = typeCountNotToAutocorrect; i < typeCountToAutoCorrect; i++) { 375 type(DESIRED_WORD); 376 type(Constants.CODE_SPACE); 377 } 378 startIndex = mEditText.getText().length(); 379 type(WORD_TO_BE_CORRECTED); 380 type(Constants.CODE_SPACE); 381 endIndex = mEditText.getText().length(); 382 assertEquals("auto-corrected by user history", 383 CORRECTED_RESULT, mEditText.getText().subSequence(startIndex, endIndex).toString()); 384 } 385 386 public void testPredictionsAfterSpace() { 387 final String WORD_TO_TYPE = "Barack "; 388 type(WORD_TO_TYPE); 389 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 390 runMessages(); 391 // Test the first prediction is displayed 392 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 393 assertEquals("predictions after space", "Obama", 394 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 395 } 396 397 public void testPredictionsAfterManualPick() { 398 final String WORD_TO_TYPE = "Barack"; 399 type(WORD_TO_TYPE); 400 // Choose the auto-correction, which is always in position 0. For "Barack", the 401 // auto-correction should be "Barack". 402 pickSuggestionManually(0, WORD_TO_TYPE); 403 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 404 runMessages(); 405 // Test the first prediction is displayed 406 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 407 assertEquals("predictions after manual pick", "Obama", 408 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 409 } 410 411 public void testNoPredictionsAfterPeriod() { 412 final String WORD_TO_TYPE = "Barack. "; 413 type(WORD_TO_TYPE); 414 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 415 runMessages(); 416 // Test the first prediction is not displayed 417 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 418 assertEquals("no prediction after period", 0, suggestedWords.size()); 419 } 420 421 public void testPredictionsAfterRecorrection() { 422 final String PREFIX = "A "; 423 final String WORD_TO_TYPE = "Barack"; 424 final String FIRST_NON_TYPED_SUGGESTION = "Barrack"; 425 final int endOfPrefix = PREFIX.length(); 426 final int endOfWord = endOfPrefix + WORD_TO_TYPE.length(); 427 final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length(); 428 final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack" 429 type(PREFIX); 430 mLatinIME.onUpdateSelection(0, 0, endOfPrefix, endOfPrefix, -1, -1); 431 type(WORD_TO_TYPE); 432 pickSuggestionManually(1, FIRST_NON_TYPED_SUGGESTION); 433 mLatinIME.onUpdateSelection(endOfPrefix, endOfPrefix, endOfSuggestion, endOfSuggestion, 434 -1, -1); 435 runMessages(); 436 type(" "); 437 mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion, 438 endOfSuggestion + 1, endOfSuggestion + 1, -1, -1); 439 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 440 runMessages(); 441 // Simulate a manual cursor move 442 mInputConnection.setSelection(indexForManualCursor, indexForManualCursor); 443 mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1, 444 indexForManualCursor, indexForManualCursor, -1, -1); 445 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 446 runMessages(); 447 pickSuggestionManually(0, WORD_TO_TYPE); 448 mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor, 449 endOfWord, endOfWord, -1, -1); 450 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); 451 runMessages(); 452 // Test the first prediction is displayed 453 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 454 assertEquals("predictions after recorrection", "Obama", 455 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 456 } 457} 458