Merge commit 'goog/master'
This commit is contained in:
commit
912fb384da
11 changed files with 588 additions and 15 deletions
|
@ -1,3 +1,8 @@
|
||||||
-keep class com.android.inputmethod.latin.BinaryDictionary {
|
-keep class com.android.inputmethod.latin.BinaryDictionary {
|
||||||
int mDictLength;
|
int mDictLength;
|
||||||
|
<init>(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class com.android.inputmethod.latin.Suggest {
|
||||||
|
<init>(...);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,11 @@
|
||||||
<Key android:keyLabel="/" android:keyWidth="10%p"/>
|
<Key android:keyLabel="/" android:keyWidth="10%p"/>
|
||||||
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
|
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
|
||||||
android:iconPreview="@drawable/sym_keyboard_feedback_space"
|
android:iconPreview="@drawable/sym_keyboard_feedback_space"
|
||||||
android:keyWidth="20%p" android:isRepeatable="true"/>
|
android:keyWidth="40%p" android:isRepeatable="true"/>
|
||||||
<Key android:keyLabel="@string/popular_domain_0"
|
<!--Key android:keyLabel="@string/popular_domain_0"
|
||||||
android:keyOutputText="@string/popular_domain_0"
|
android:keyOutputText="@string/popular_domain_0"
|
||||||
android:popupKeyboard="@xml/popup_domains"
|
android:popupKeyboard="@xml/popup_domains"
|
||||||
android:keyWidth="20%p"/>
|
android:keyWidth="20%p"/-->
|
||||||
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
|
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
|
||||||
android:keyWidth="10%p"/>
|
android:keyWidth="10%p"/>
|
||||||
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
||||||
|
@ -114,11 +114,11 @@
|
||||||
<Key android:keyLabel="\@" android:keyWidth="10%p"/>
|
<Key android:keyLabel="\@" android:keyWidth="10%p"/>
|
||||||
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
|
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
|
||||||
android:iconPreview="@drawable/sym_keyboard_feedback_space"
|
android:iconPreview="@drawable/sym_keyboard_feedback_space"
|
||||||
android:keyWidth="20%p" android:isRepeatable="true"/>
|
android:keyWidth="40%p" android:isRepeatable="true"/>
|
||||||
<Key android:keyLabel="@string/popular_domain_0"
|
<!--Key android:keyLabel="@string/popular_domain_0"
|
||||||
android:keyOutputText="@string/popular_domain_0"
|
android:keyOutputText="@string/popular_domain_0"
|
||||||
android:popupKeyboard="@xml/popup_domains"
|
android:popupKeyboard="@xml/popup_domains"
|
||||||
android:keyWidth="20%p"/>
|
android:keyWidth="20%p"/-->
|
||||||
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"/>
|
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"/>
|
||||||
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
||||||
android:iconPreview="@drawable/sym_keyboard_feedback_return"
|
android:iconPreview="@drawable/sym_keyboard_feedback_return"
|
||||||
|
|
|
@ -22,5 +22,5 @@
|
||||||
|
|
||||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:settingsActivity="com.android.inputmethod.latin.LatinIMESettings"
|
android:settingsActivity="com.android.inputmethod.latin.LatinIMESettings"
|
||||||
android:isDefault="true"
|
android:isDefault="@bool/im_is_default"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -68,6 +68,26 @@ public class BinaryDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a dictionary from a byte buffer. This is used for testing.
|
||||||
|
* @param context application context for reading resources
|
||||||
|
* @param resId the resource containing the raw binary dictionary
|
||||||
|
*/
|
||||||
|
public BinaryDictionary(Context context, ByteBuffer byteBuffer) {
|
||||||
|
if (byteBuffer != null) {
|
||||||
|
if (byteBuffer.isDirect()) {
|
||||||
|
mNativeDictDirectBuffer = byteBuffer;
|
||||||
|
} else {
|
||||||
|
mNativeDictDirectBuffer = ByteBuffer.allocateDirect(byteBuffer.capacity());
|
||||||
|
byteBuffer.rewind();
|
||||||
|
mNativeDictDirectBuffer.put(byteBuffer);
|
||||||
|
}
|
||||||
|
mDictLength = byteBuffer.capacity();
|
||||||
|
mNativeDict = openNative(mNativeDictDirectBuffer,
|
||||||
|
TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private native int openNative(ByteBuffer bb, int typedLetterMultiplier, int fullWordMultiplier);
|
private native int openNative(ByteBuffer bb, int typedLetterMultiplier, int fullWordMultiplier);
|
||||||
private native void closeNative(int dict);
|
private native void closeNative(int dict);
|
||||||
private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
|
private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
|
||||||
|
|
|
@ -16,18 +16,17 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.AutoText;
|
import android.text.AutoText;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.WordComposer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class loads a dictionary and provides a list of suggestions for a given sequence of
|
* This class loads a dictionary and provides a list of suggestions for a given sequence of
|
||||||
* characters. This includes corrections and completions.
|
* characters. This includes corrections and completions.
|
||||||
|
@ -69,9 +68,17 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
|
|
||||||
private int mCorrectionMode = CORRECTION_BASIC;
|
private int mCorrectionMode = CORRECTION_BASIC;
|
||||||
|
|
||||||
|
|
||||||
public Suggest(Context context, int dictionaryResId) {
|
public Suggest(Context context, int dictionaryResId) {
|
||||||
mMainDict = new BinaryDictionary(context, dictionaryResId);
|
mMainDict = new BinaryDictionary(context, dictionaryResId);
|
||||||
|
initPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Suggest(Context context, ByteBuffer byteBuffer) {
|
||||||
|
mMainDict = new BinaryDictionary(context, byteBuffer);
|
||||||
|
initPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPool() {
|
||||||
for (int i = 0; i < mPrefMaxSuggestions; i++) {
|
for (int i = 0; i < mPrefMaxSuggestions; i++) {
|
||||||
StringBuilder sb = new StringBuilder(32);
|
StringBuilder sb = new StringBuilder(32);
|
||||||
mStringPool.add(sb);
|
mStringPool.add(sb);
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class WordComposer {
|
||||||
*/
|
*/
|
||||||
private boolean mIsCapitalized;
|
private boolean mIsCapitalized;
|
||||||
|
|
||||||
WordComposer() {
|
public WordComposer() {
|
||||||
mCodes = new ArrayList<int[]>(12);
|
mCodes = new ArrayList<int[]>(12);
|
||||||
mTypedWord = new StringBuilder(20);
|
mTypedWord = new StringBuilder(20);
|
||||||
}
|
}
|
||||||
|
|
17
tests/Android.mk
Normal file
17
tests/Android.mk
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
# We only want this apk build for tests.
|
||||||
|
LOCAL_MODULE_TAGS := tests
|
||||||
|
LOCAL_CERTIFICATE := shared
|
||||||
|
|
||||||
|
LOCAL_JAVA_LIBRARIES := android.test.runner
|
||||||
|
|
||||||
|
# Include all test java files.
|
||||||
|
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||||
|
|
||||||
|
LOCAL_PACKAGE_NAME := LatinIMETests
|
||||||
|
|
||||||
|
LOCAL_INSTRUMENTATION_FOR := LatinIME
|
||||||
|
|
||||||
|
include $(BUILD_PACKAGE)
|
33
tests/AndroidManifest.xml
Normal file
33
tests/AndroidManifest.xml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.android.inputmethod.latin.tests">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
<!-- meta-data android:name="com.android.contacts.iconset" android:resource="@xml/iconset" /-->
|
||||||
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
||||||
|
android:targetPackage="com.android.inputmethod.latin"
|
||||||
|
android:label="LatinIME tests">
|
||||||
|
</instrumentation>
|
||||||
|
</manifest>
|
243
tests/data/wordlist.xml
Normal file
243
tests/data/wordlist.xml
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
<wordlist>
|
||||||
|
<w f="255">the</w>
|
||||||
|
<w f="246">and</w>
|
||||||
|
<w f="245">of</w>
|
||||||
|
<w f="242">to</w>
|
||||||
|
<w f="231">in</w>
|
||||||
|
<w f="230">that</w>
|
||||||
|
<w f="229">for</w>
|
||||||
|
<w f="224">with</w>
|
||||||
|
<w f="224">on</w>
|
||||||
|
<w f="224">it</w>
|
||||||
|
<w f="223">this</w>
|
||||||
|
<w f="222">you</w>
|
||||||
|
<w f="219">is</w>
|
||||||
|
<w f="219">was</w>
|
||||||
|
<w f="219">by</w>
|
||||||
|
<w f="219">or</w>
|
||||||
|
<w f="218">from</w>
|
||||||
|
<w f="217">but</w>
|
||||||
|
<w f="216">be</w>
|
||||||
|
<w f="216">Sunday</w>
|
||||||
|
<w f="215">are</w>
|
||||||
|
<w f="215">he</w>
|
||||||
|
<w f="214">so</w>
|
||||||
|
<w f="214">not</w>
|
||||||
|
<w f="213">have</w>
|
||||||
|
<w f="213">as</w>
|
||||||
|
<w f="211">all</w>
|
||||||
|
<w f="211">his</w>
|
||||||
|
<w f="210">my</w>
|
||||||
|
<w f="210">if</w>
|
||||||
|
<w f="210">which</w>
|
||||||
|
<w f="210">they</w>
|
||||||
|
<w f="209">at</w>
|
||||||
|
<w f="207">it's</w>
|
||||||
|
<w f="207">an</w>
|
||||||
|
<w f="207">your</w>
|
||||||
|
<w f="206">will</w>
|
||||||
|
<w f="206">about</w>
|
||||||
|
<w f="206">I'm</w>
|
||||||
|
<w f="205">there</w>
|
||||||
|
<w f="205">had</w>
|
||||||
|
<w f="205">has</w>
|
||||||
|
<w f="204">when</w>
|
||||||
|
<w f="203">no</w>
|
||||||
|
<w f="203">were</w>
|
||||||
|
<w f="203">what</w>
|
||||||
|
<w f="203">more</w>
|
||||||
|
<w f="203">out</w>
|
||||||
|
<w f="203">just</w>
|
||||||
|
<w f="202">their</w>
|
||||||
|
<w f="202">up</w>
|
||||||
|
<w f="202">would</w>
|
||||||
|
<w f="202">here</w>
|
||||||
|
<w f="202">can</w>
|
||||||
|
<w f="201">who</w>
|
||||||
|
<w f="200">her</w>
|
||||||
|
<w f="200">me</w>
|
||||||
|
<w f="200">now</w>
|
||||||
|
<w f="200">our</w>
|
||||||
|
<w f="200">do</w>
|
||||||
|
<w f="200">some</w>
|
||||||
|
<w f="199">been</w>
|
||||||
|
<w f="199">two</w>
|
||||||
|
<w f="199">like</w>
|
||||||
|
<w f="199">them</w>
|
||||||
|
<w f="199">new</w>
|
||||||
|
<w f="198">time</w>
|
||||||
|
<w f="198">we</w>
|
||||||
|
<w f="198">she</w>
|
||||||
|
<w f="197">one</w>
|
||||||
|
<w f="197">over</w>
|
||||||
|
<w f="197">may</w>
|
||||||
|
<w f="197">any</w>
|
||||||
|
<w f="197">him</w>
|
||||||
|
<w f="197">calling</w>
|
||||||
|
<w f="196">other</w>
|
||||||
|
<w f="196">how</w>
|
||||||
|
<w f="196">see</w>
|
||||||
|
<w f="195">because</w>
|
||||||
|
<w f="195">then</w>
|
||||||
|
<w f="195">right</w>
|
||||||
|
<w f="195">into</w>
|
||||||
|
<w f="195">well</w>
|
||||||
|
<w f="195">very</w>
|
||||||
|
<w f="195">said</w>
|
||||||
|
<w f="195">people</w>
|
||||||
|
<w f="194">these</w>
|
||||||
|
<w f="194">than</w>
|
||||||
|
<w f="193">only</w>
|
||||||
|
<w f="193">back</w>
|
||||||
|
<w f="193">first</w>
|
||||||
|
<w f="193">dot</w>
|
||||||
|
<w f="193">after</w>
|
||||||
|
<w f="193">where</w>
|
||||||
|
<w f="192">please</w>
|
||||||
|
<w f="192">could</w>
|
||||||
|
<w f="192">its</w>
|
||||||
|
<w f="192">before</w>
|
||||||
|
<w f="192">us</w>
|
||||||
|
<w f="192">again</w>
|
||||||
|
<w f="192">home</w>
|
||||||
|
<w f="191">also</w>
|
||||||
|
<w f="191">that's</w>
|
||||||
|
<w f="191">think</w>
|
||||||
|
<w f="191">three</w>
|
||||||
|
<w f="191">good</w>
|
||||||
|
<w f="191">get</w>
|
||||||
|
<w f="190">know</w>
|
||||||
|
<w f="190">thank</w>
|
||||||
|
<w f="190">should</w>
|
||||||
|
<w f="190">going</w>
|
||||||
|
<w f="190">down</w>
|
||||||
|
<w f="189">last</w>
|
||||||
|
<w f="189">today</w>
|
||||||
|
<w f="189">those</w>
|
||||||
|
<w f="189">go</w>
|
||||||
|
<w f="189">through</w>
|
||||||
|
<w f="189">such</w>
|
||||||
|
<w f="189">don't</w>
|
||||||
|
<w f="189">did</w>
|
||||||
|
<w f="188">most</w>
|
||||||
|
<w f="188">day</w>
|
||||||
|
<w f="188">man</w>
|
||||||
|
<w f="188">number</w>
|
||||||
|
<w f="188">work</w>
|
||||||
|
<w f="187">too</w>
|
||||||
|
<w f="187">show</w>
|
||||||
|
<w f="187">made</w>
|
||||||
|
<w f="187">even</w>
|
||||||
|
<w f="187">being</w>
|
||||||
|
<w f="187">make</w>
|
||||||
|
<w f="187">give</w>
|
||||||
|
<w f="186">off</w>
|
||||||
|
<w f="186">com</w>
|
||||||
|
<w f="186">much</w>
|
||||||
|
<w f="186">great</w>
|
||||||
|
<w f="186">take</w>
|
||||||
|
<w f="186">call</w>
|
||||||
|
<w f="186">way</w>
|
||||||
|
<w f="186">four</w>
|
||||||
|
<w f="186">say</w>
|
||||||
|
<w f="185">information</w>
|
||||||
|
<w f="185">under</w>
|
||||||
|
<w f="185">page</w>
|
||||||
|
<w f="185">many</w>
|
||||||
|
<w f="185">little</w>
|
||||||
|
<w f="185">thanks</w>
|
||||||
|
<w f="185">okay</w>
|
||||||
|
<w f="185">five</w>
|
||||||
|
<w f="185">we're</w>
|
||||||
|
<w f="185">between</w>
|
||||||
|
<w f="184">use</w>
|
||||||
|
<w f="184">come</w>
|
||||||
|
<w f="184">years</w>
|
||||||
|
<w f="184">office</w>
|
||||||
|
<w f="184">house</w>
|
||||||
|
<w f="184">search</w>
|
||||||
|
<w f="184">free</w>
|
||||||
|
<w f="183">next</w>
|
||||||
|
<w f="183">without</w>
|
||||||
|
<w f="183">still</w>
|
||||||
|
<w f="183">around</w>
|
||||||
|
<w f="183">I've</w>
|
||||||
|
<w f="183">business</w>
|
||||||
|
<w f="183">part</w>
|
||||||
|
<w f="183">every</w>
|
||||||
|
<w f="183">bye</w>
|
||||||
|
<w f="183">upon</w>
|
||||||
|
<w f="183">you're</w>
|
||||||
|
<w f="183">state</w>
|
||||||
|
<w f="183">life</w>
|
||||||
|
<w f="183">year</w>
|
||||||
|
<w f="182">thing</w>
|
||||||
|
<w f="182">since</w>
|
||||||
|
<w f="182">things</w>
|
||||||
|
<w f="182">something</w>
|
||||||
|
<w f="182">long</w>
|
||||||
|
<w f="182">got</w>
|
||||||
|
<w f="182">while</w>
|
||||||
|
<w f="182">I'll</w>
|
||||||
|
<w f="182">help</w>
|
||||||
|
<w f="182">service</w>
|
||||||
|
<w f="182">really</w>
|
||||||
|
<w f="182">must</w>
|
||||||
|
<w f="182">does</w>
|
||||||
|
<w f="182">name</w>
|
||||||
|
<w f="181">both</w>
|
||||||
|
<w f="181">six</w>
|
||||||
|
<w f="181">want</w>
|
||||||
|
<w f="181">same</w>
|
||||||
|
<w f="181">each</w>
|
||||||
|
<w f="181">yet</w>
|
||||||
|
<w f="181">let</w>
|
||||||
|
<w f="181">view</w>
|
||||||
|
<w f="181">place</w>
|
||||||
|
<w f="181">another</w>
|
||||||
|
<w f="181">company</w>
|
||||||
|
<w f="181">talk</w>
|
||||||
|
<w f="181">might</w>
|
||||||
|
<w f="181">am</w>
|
||||||
|
<w f="181">though</w>
|
||||||
|
<w f="181">find</w>
|
||||||
|
<w f="180">details</w>
|
||||||
|
<w f="180">look</w>
|
||||||
|
<w f="180">world</w>
|
||||||
|
<w f="180">old</w>
|
||||||
|
<w f="180">called</w>
|
||||||
|
<w f="180">case</w>
|
||||||
|
<w f="180">system</w>
|
||||||
|
<w f="180">news</w>
|
||||||
|
<w f="179">used</w>
|
||||||
|
<w f="179">contact</w>
|
||||||
|
<w f="179">never</w>
|
||||||
|
<w f="179">seven</w>
|
||||||
|
<w f="179">city</w>
|
||||||
|
<w f="179">until</w>
|
||||||
|
<w f="179">during</w>
|
||||||
|
<w f="179">set</w>
|
||||||
|
<w f="179">why</w>
|
||||||
|
<w f="179">point</w>
|
||||||
|
<w f="179">twenty</w>
|
||||||
|
<w f="179">high</w>
|
||||||
|
<w f="179">love</w>
|
||||||
|
<w f="179">services</w>
|
||||||
|
<w f="170">niño</w>
|
||||||
|
<w f="170">María</w>
|
||||||
|
<w f="0">hmmm</w>
|
||||||
|
<w f="0">hon</w>
|
||||||
|
<w f="0">tty</w>
|
||||||
|
<w f="0">ttyl</w>
|
||||||
|
<w f="0">txt</w>
|
||||||
|
<w f="0">ur</w>
|
||||||
|
<w f="0">wah</w>
|
||||||
|
<w f="0">whatcha</w>
|
||||||
|
<w f="0">woah</w>
|
||||||
|
<w f="0">ya</w>
|
||||||
|
<w f="0">yea</w>
|
||||||
|
<w f="0">yeh</w>
|
||||||
|
<w f="0">yessir</w>
|
||||||
|
<w f="0">yikes</w>
|
||||||
|
<w f="0">yrs</w>
|
||||||
|
</wordlist>
|
BIN
tests/res/raw/test.dict
Normal file
BIN
tests/res/raw/test.dict
Normal file
Binary file not shown.
248
tests/src/com/android/inputmethod/latin/tests/SuggestTests.java
Normal file
248
tests/src/com/android/inputmethod/latin/tests/SuggestTests.java
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
package com.android.inputmethod.latin.tests;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.Suggest;
|
||||||
|
import com.android.inputmethod.latin.WordComposer;
|
||||||
|
|
||||||
|
public class SuggestTests extends AndroidTestCase {
|
||||||
|
private static final String TAG = "SuggestTests";
|
||||||
|
|
||||||
|
private Suggest mSuggest;
|
||||||
|
|
||||||
|
int[][] adjacents = {
|
||||||
|
{'a','s','w','q',-1},
|
||||||
|
{'b','h','v','n','g','j',-1},
|
||||||
|
{'c','v','f','x','g',},
|
||||||
|
{'d','f','r','e','s','x',-1},
|
||||||
|
{'e','w','r','s','d',-1},
|
||||||
|
{'f','g','d','c','t','r',-1},
|
||||||
|
{'g','h','f','y','t','v',-1},
|
||||||
|
{'h','j','u','g','b','y',-1},
|
||||||
|
{'i','o','u','k',-1},
|
||||||
|
{'j','k','i','h','u','n',-1},
|
||||||
|
{'k','l','o','j','i','m',-1},
|
||||||
|
{'l','k','o','p',-1},
|
||||||
|
{'m','k','n','l',-1},
|
||||||
|
{'n','m','j','k','b',-1},
|
||||||
|
{'o','p','i','l',-1},
|
||||||
|
{'p','o',-1},
|
||||||
|
{'q','w',-1},
|
||||||
|
{'r','t','e','f',-1},
|
||||||
|
{'s','d','e','w','a','z',-1},
|
||||||
|
{'t','y','r',-1},
|
||||||
|
{'u','y','i','h','j',-1},
|
||||||
|
{'v','b','g','c','h',-1},
|
||||||
|
{'w','e','q',-1},
|
||||||
|
{'x','c','d','z','f',-1},
|
||||||
|
{'y','u','t','h','g',-1},
|
||||||
|
{'z','s','x','a','d',-1},
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
final Context context = getTestContext();
|
||||||
|
InputStream is = context.getResources().openRawResource(R.raw.test);
|
||||||
|
Log.i(TAG, "Stream type is " + is);
|
||||||
|
try {
|
||||||
|
int avail = is.available();
|
||||||
|
if (avail > 0) {
|
||||||
|
ByteBuffer byteBuffer =
|
||||||
|
ByteBuffer.allocateDirect(avail).order(ByteOrder.nativeOrder());
|
||||||
|
int got = Channels.newChannel(is).read(byteBuffer);
|
||||||
|
if (got != avail) {
|
||||||
|
Log.e(TAG, "Read " + got + " bytes, expected " + avail);
|
||||||
|
} else {
|
||||||
|
mSuggest = new Suggest(context, byteBuffer);
|
||||||
|
Log.i(TAG, "Created mSuggest " + avail + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.w(TAG, "No available size for binary dictionary");
|
||||||
|
}
|
||||||
|
mSuggest.setAutoTextEnabled(false);
|
||||||
|
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************** Helper functions ************************/
|
||||||
|
|
||||||
|
private WordComposer createWordComposer(CharSequence s) {
|
||||||
|
WordComposer word = new WordComposer();
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
final char c = s.charAt(i);
|
||||||
|
int[] codes;
|
||||||
|
// If it's not a lowercase letter, don't find adjacent letters
|
||||||
|
if (c < 'a' || c > 'z') {
|
||||||
|
codes = new int[] { c };
|
||||||
|
} else {
|
||||||
|
codes = adjacents[c - 'a'];
|
||||||
|
}
|
||||||
|
word.add(c, codes);
|
||||||
|
}
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showList(String title, List<CharSequence> suggestions) {
|
||||||
|
Log.i(TAG, title);
|
||||||
|
for (int i = 0; i < suggestions.size(); i++) {
|
||||||
|
Log.i(title, suggestions.get(i) + ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDefaultSuggestion(List<CharSequence> suggestions, CharSequence word) {
|
||||||
|
// Check if either the word is what you typed or the first alternative
|
||||||
|
return suggestions.size() > 0 &&
|
||||||
|
(/*TextUtils.equals(suggestions.get(0), word) || */
|
||||||
|
(suggestions.size() > 1 && TextUtils.equals(suggestions.get(1), word)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) {
|
||||||
|
WordComposer word = createWordComposer(typed);
|
||||||
|
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false);
|
||||||
|
return isDefaultSuggestion(suggestions, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDefaultCorrection(CharSequence typed, CharSequence expected) {
|
||||||
|
WordComposer word = createWordComposer(typed);
|
||||||
|
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false);
|
||||||
|
return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isASuggestion(CharSequence typed, CharSequence expected) {
|
||||||
|
WordComposer word = createWordComposer(typed);
|
||||||
|
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false);
|
||||||
|
for (int i = 1; i < suggestions.size(); i++) {
|
||||||
|
if (TextUtils.equals(suggestions.get(i), expected)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValid(CharSequence typed) {
|
||||||
|
return mSuggest.isValidWord(typed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************** Tests ************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for simple completions of one character.
|
||||||
|
*/
|
||||||
|
public void testCompletion1char() {
|
||||||
|
assertTrue(isDefaultSuggestion("peopl", "people"));
|
||||||
|
assertTrue(isDefaultSuggestion("abou", "about"));
|
||||||
|
assertTrue(isDefaultSuggestion("thei", "their"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for simple completions of two characters.
|
||||||
|
*/
|
||||||
|
public void testCompletion2char() {
|
||||||
|
assertTrue(isDefaultSuggestion("peop", "people"));
|
||||||
|
assertTrue(isDefaultSuggestion("calli", "calling"));
|
||||||
|
assertTrue(isDefaultSuggestion("busine", "business"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for proximity errors.
|
||||||
|
*/
|
||||||
|
public void testProximityPositive() {
|
||||||
|
assertTrue(isDefaultSuggestion("peiple", "people"));
|
||||||
|
assertTrue(isDefaultSuggestion("peoole", "people"));
|
||||||
|
assertTrue(isDefaultSuggestion("pwpple", "people"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for proximity errors - negative, when the error key is not near.
|
||||||
|
*/
|
||||||
|
public void testProximityNegative() {
|
||||||
|
assertFalse(isDefaultSuggestion("arout", "about"));
|
||||||
|
assertFalse(isDefaultSuggestion("ire", "are"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for checking if apostrophes are added automatically.
|
||||||
|
*/
|
||||||
|
public void testApostropheInsertion() {
|
||||||
|
assertTrue(isDefaultSuggestion("im", "I'm"));
|
||||||
|
assertTrue(isDefaultSuggestion("dont", "don't"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test to make sure apostrophed word is not suggested for an apostrophed word.
|
||||||
|
*/
|
||||||
|
public void testApostrophe() {
|
||||||
|
assertFalse(isDefaultSuggestion("don't", "don't"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for suggestion of capitalized version of a word.
|
||||||
|
*/
|
||||||
|
public void testCapitalization() {
|
||||||
|
assertTrue(isDefaultSuggestion("i'm", "I'm"));
|
||||||
|
assertTrue(isDefaultSuggestion("sunday", "Sunday"));
|
||||||
|
assertTrue(isDefaultSuggestion("sundat", "Sunday"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to see if more than one completion is provided for certain prefixes.
|
||||||
|
*/
|
||||||
|
public void testMultipleCompletions() {
|
||||||
|
assertTrue(isASuggestion("com", "come"));
|
||||||
|
assertTrue(isASuggestion("com", "company"));
|
||||||
|
assertTrue(isASuggestion("th", "the"));
|
||||||
|
assertTrue(isASuggestion("th", "that"));
|
||||||
|
assertTrue(isASuggestion("th", "this"));
|
||||||
|
assertTrue(isASuggestion("th", "they"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the suggestion engine recognize zero frequency words as valid words.
|
||||||
|
*/
|
||||||
|
public void testZeroFrequencyAccepted() {
|
||||||
|
assertTrue(isValid("yikes"));
|
||||||
|
assertFalse(isValid("yike"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to make sure that zero frequency words are not suggested as completions.
|
||||||
|
*/
|
||||||
|
public void testZeroFrequencySuggestionsNegative() {
|
||||||
|
assertFalse(isASuggestion("yike", "yikes"));
|
||||||
|
assertFalse(isASuggestion("what", "whatcha"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to ensure that words with large edit distances are not suggested, in some cases
|
||||||
|
* and not considered corrections, in some cases.
|
||||||
|
*/
|
||||||
|
public void testTooLargeEditDistance() {
|
||||||
|
assertFalse(isASuggestion("sniyr", "about"));
|
||||||
|
assertFalse(isDefaultCorrection("rjw", "the"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure isValid is case-sensitive.
|
||||||
|
*/
|
||||||
|
public void testValidityCaseSensitivity() {
|
||||||
|
assertTrue(isValid("Sunday"));
|
||||||
|
assertFalse(isValid("sunday"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are accented forms of words suggested as corrections?
|
||||||
|
*/
|
||||||
|
public void testAccents() {
|
||||||
|
assertTrue(isDefaultCorrection("nino", "ni\u00F1o")); // ni–o
|
||||||
|
assertTrue(isDefaultCorrection("nimo", "ni\u00F1o")); // ni–o
|
||||||
|
assertTrue(isDefaultCorrection("maria", "Mar\u00EDa")); // Mar’a
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue