InputLogicTests.java revision 9184d8b2352e11a25026ea9eed7f404836a7d476
1/* 2 * Copyright (C) 2012 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 17package com.android.inputmethod.latin; 18 19import android.content.Context; 20import android.content.Intent; 21import android.content.SharedPreferences; 22import android.preference.PreferenceManager; 23import android.test.ServiceTestCase; 24import android.text.InputType; 25import android.util.Log; 26import android.view.LayoutInflater; 27import android.view.ViewGroup; 28import android.view.View; 29import android.view.inputmethod.BaseInputConnection; 30import android.view.inputmethod.EditorInfo; 31import android.view.inputmethod.InputConnection; 32import android.widget.FrameLayout; 33import android.widget.TextView; 34 35import com.android.inputmethod.keyboard.Keyboard; 36import com.android.inputmethod.keyboard.KeyboardActionListener; 37import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; // for proximity info 38import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; 39 40import java.util.Arrays; 41import java.util.HashMap; 42 43public class InputLogicTests extends ServiceTestCase<LatinIME> { 44 45 private static final String PREF_DEBUG_MODE = "debug_mode"; 46 47 private LatinIME mLatinIME; 48 private TextView mTextView; 49 private InputConnection mInputConnection; 50 private HashMap<Integer, int[]> mProximity; 51 52 public InputLogicTests() { 53 super(LatinIME.class); 54 mProximity = createProximity(); 55 } 56 57 private static HashMap<Integer, int[]> createProximity() { 58 final HashMap<Integer, int[]> proximity = new HashMap<Integer, int[]>(); 59 final int[] testProximity = SpellCheckerProximityInfo.getProximityForScript( 60 AndroidSpellCheckerService.SCRIPT_LATIN); 61 final int ROW_SIZE = SpellCheckerProximityInfo.ROW_SIZE; 62 final int NUL = SpellCheckerProximityInfo.NUL; 63 for (int row = 0; row * ROW_SIZE < testProximity.length; ++row) { 64 final int rowBase = row * ROW_SIZE; 65 int column; 66 for (column = 1; NUL != testProximity[rowBase + column]; ++column) { 67 // Do nothing, just search for a NUL element 68 } 69 proximity.put(testProximity[row * ROW_SIZE], 70 Arrays.copyOfRange(testProximity, rowBase, rowBase + column)); 71 } 72 return proximity; 73 } 74 75 // returns the previous setting value 76 private boolean setDebugMode(final boolean mode) { 77 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME); 78 final boolean previousDebugSetting = prefs.getBoolean(PREF_DEBUG_MODE, false); 79 final SharedPreferences.Editor editor = prefs.edit(); 80 editor.putBoolean(PREF_DEBUG_MODE, true); 81 editor.commit(); 82 return previousDebugSetting; 83 } 84 85 @Override 86 protected void setUp() { 87 try { 88 super.setUp(); 89 } catch (Exception e) { 90 e.printStackTrace(); 91 } 92 mTextView = new TextView(getContext()); 93 mTextView.setInputType(InputType.TYPE_CLASS_TEXT); 94 mTextView.setEnabled(true); 95 setupService(); 96 mLatinIME = getService(); 97 final boolean previousDebugSetting = setDebugMode(true); 98 mLatinIME.onCreate(); 99 setDebugMode(previousDebugSetting); 100 final EditorInfo ei = new EditorInfo(); 101 ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; 102 final InputConnection ic = mTextView.onCreateInputConnection(ei); 103 ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; 104 final LayoutInflater inflater = 105 (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 106 final ViewGroup vg = new FrameLayout(getContext()); 107 final View inputView = inflater.inflate(R.layout.input_view, vg); 108 mLatinIME.setInputView(inputView); 109 mLatinIME.onBindInput(); 110 mLatinIME.onCreateInputView(); 111 mLatinIME.onStartInputView(ei, false); 112 mLatinIME.onCreateInputMethodInterface().startInput(ic, ei); 113 mInputConnection = ic; 114 } 115 116 // type(int) and type(String): helper methods to send a code point resp. a string to LatinIME. 117 private void type(final int codePoint) { 118 // onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the 119 // code (although multitouch/slide input and other factors make the sequencing complicated). 120 // They are supposed to be entirely deconnected from the input logic from LatinIME point of 121 // view and only delegates to the parts of the code that care. So we don't include them here 122 // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies, 123 // but keep them in mind if something breaks. Commenting them out as is should work. 124 //mLatinIME.onPressKey(codePoint); 125 int[] proximityKeys = mProximity.get(codePoint); 126 if (null == proximityKeys) { 127 proximityKeys = new int[] { codePoint }; 128 } 129 mLatinIME.onCodeInput(codePoint, proximityKeys, 130 KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 131 KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 132 //mLatinIME.onReleaseKey(codePoint, false); 133 } 134 135 private void type(final String stringToType) { 136 for (int i = 0; i < stringToType.length(); ++i) { 137 type(stringToType.codePointAt(i)); 138 } 139 } 140 141 public void testTypeWord() { 142 final String WORD_TO_TYPE = "abcd"; 143 type(WORD_TO_TYPE); 144 assertEquals("type word", WORD_TO_TYPE, mTextView.getText().toString()); 145 } 146 147 public void testPickSuggestionThenBackspace() { 148 final String WORD_TO_TYPE = "tgis"; 149 type(WORD_TO_TYPE); 150 mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); 151 type(Keyboard.CODE_DELETE); 152 assertEquals("press suggestion then backspace", WORD_TO_TYPE, 153 mTextView.getText().toString()); 154 } 155 156 public void testDeleteSelection() { 157 final String STRING_TO_TYPE = "some text delete me some text"; 158 final int SELECTION_START = 10; 159 final int SELECTION_END = 19; 160 final String EXPECTED_RESULT = "some text some text"; 161 type(STRING_TO_TYPE); 162 // There is no IMF to call onUpdateSelection for us so we must do it by hand. 163 // Send once to simulate the cursor actually responding to the move caused by typing. 164 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 165 // move with a move triggered by LatinIME inputting stuff. 166 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 167 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 168 // And now we simulate the user actually selecting some text. 169 mLatinIME.onUpdateSelection(0, 0, SELECTION_START, SELECTION_END, -1, -1); 170 type(Keyboard.CODE_DELETE); 171 assertEquals("delete selection", EXPECTED_RESULT, mTextView.getText().toString()); 172 } 173 174 public void testAutoCorrect() { 175 final String STRING_TO_TYPE = "tgis "; 176 final String EXPECTED_RESULT = "this "; 177 type(STRING_TO_TYPE); 178 assertEquals("simple auto-correct", EXPECTED_RESULT, mTextView.getText().toString()); 179 } 180 181 public void testDoubleSpace() { 182 final String STRING_TO_TYPE = "this "; 183 final String EXPECTED_RESULT = "this. "; 184 type(STRING_TO_TYPE); 185 assertEquals("double space make a period", EXPECTED_RESULT, mTextView.getText().toString()); 186 } 187 188 public void testCancelDoubleSpace() { 189 final String STRING_TO_TYPE = "tgis "; 190 final String EXPECTED_RESULT = "this "; 191 type(STRING_TO_TYPE); 192 type(Keyboard.CODE_DELETE); 193 assertEquals("double space make a period", EXPECTED_RESULT, mTextView.getText().toString()); 194 195 public void testBackspaceAtStartAfterAutocorrect() { 196 final String STRING_TO_TYPE = "tgis "; 197 final String EXPECTED_RESULT = "this "; 198 final int NEW_CURSOR_POSITION = 0; 199 type(STRING_TO_TYPE); 200 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 201 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 202 mLatinIME.onUpdateSelection(0, 0, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 203 type(Keyboard.CODE_DELETE); 204 assertEquals("auto correct then move curor to start of line then backspace", 205 EXPECTED_RESULT, mTextView.getText().toString()); 206 } 207 208 public void testAutoCorrectThenMoveCursorThenBackspace() { 209 final String STRING_TO_TYPE = "and tgis "; 210 final String EXPECTED_RESULT = "andthis "; 211 final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t'); 212 type(STRING_TO_TYPE); 213 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 214 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 215 mLatinIME.onUpdateSelection(0, 0, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 216 type(Keyboard.CODE_DELETE); 217 assertEquals("auto correct then move curor then backspace", 218 EXPECTED_RESULT, mTextView.getText().toString()); 219 } 220} 221