Reorganize suggestion related unit test

Bug: 3414081
Change-Id: Ie98c7935b25d17f1547955f8fb6ba2c5c1edb997
main
Tadashi G. Takaoka 2011-02-08 18:30:26 +09:00
parent d94de20760
commit 5cb4eaeec0
9 changed files with 503 additions and 356 deletions

View File

@ -7,6 +7,11 @@ LOCAL_CERTIFICATE := shared
LOCAL_JAVA_LIBRARIES := android.test.runner
# Do not compress dictionary files to mmap dict data runtime
LOCAL_AAPT_FLAGS += -0 .dict
# Do not compress test data file
LOCAL_AAPT_FLAGS += -0 .txt
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

View File

@ -31,7 +31,7 @@ public class SubtypeLocaleTests extends AndroidTestCase {
private static final String PACKAGE = LatinIME.class.getPackage().getName();
private Resources mRes;
private List<InputMethodSubtype> mKeyboardSubtypes;
private List<InputMethodSubtype> mKeyboardSubtypes = new ArrayList<InputMethodSubtype>();
@Override
protected void setUp() throws Exception {
@ -60,11 +60,6 @@ public class SubtypeLocaleTests extends AndroidTestCase {
assertTrue("Can not find keyboard subtype", mKeyboardSubtypes.size() > 0);
}
// Copied from {@link java.junit.Assert#format(String, Object, Object)}
private static String format(String message, Object expected, Object actual) {
return message + " expected:<" + expected + "> but was:<" + actual + ">";
}
private String getStringWithLocale(int resId, Locale locale) {
final Locale savedLocale = Locale.getDefault();
try {
@ -76,6 +71,8 @@ public class SubtypeLocaleTests extends AndroidTestCase {
}
public void testSubtypeLocale() {
final StringBuilder messages = new StringBuilder();
int failedCount = 0;
for (final InputMethodSubtype subtype : mKeyboardSubtypes) {
final String localeCode = subtype.getLocale();
final Locale locale = new Locale(localeCode);
@ -85,9 +82,13 @@ public class SubtypeLocaleTests extends AndroidTestCase {
// The subtype name in its locale. For example 'English (US) Keyboard' or
// 'Clavier Francais (Canada)'. (c=\u008d)
final String subtypeName = getStringWithLocale(subtype.getNameResId(), locale);
assertTrue(
format("subtype display name of " + localeCode + ":", subtypeName, displayName),
subtypeName.contains(displayName));
if (subtypeName.contains(displayName)) {
failedCount++;
messages.append(String.format(
"subtype name is '%s' and should contain locale '%s' name '%s'\n",
subtypeName, localeCode, displayName));
}
}
assertEquals(messages.toString(), 0, failedCount);
}
}

View File

@ -16,98 +16,105 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.ProximityKeyDetector;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.latin.Suggest;
import com.android.inputmethod.latin.UserBigramDictionary;
import com.android.inputmethod.latin.WordComposer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.Channels;
import java.io.File;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
public class SuggestHelper {
private Suggest mSuggest;
private UserBigramDictionary mUserBigram;
private final String TAG;
protected final Suggest mSuggest;
private final LatinKeyboard mKeyboard;
private final KeyDetector mKeyDetector;
/** Uses main dictionary only **/
public SuggestHelper(String tag, Context context, int resId) {
TAG = tag;
mSuggest = new Suggest(context, resId);
public SuggestHelper(Context context, int dictionaryId, KeyboardId keyboardId) {
mSuggest = new Suggest(context, dictionaryId);
mKeyboard = new LatinKeyboard(context, keyboardId);
mKeyDetector = new ProximityKeyDetector();
init();
}
protected SuggestHelper(Context context, File dictionaryPath, long startOffset, long length,
KeyboardId keyboardId) {
mSuggest = new Suggest(dictionaryPath, startOffset, length);
mKeyboard = new LatinKeyboard(context, keyboardId);
mKeyDetector = new ProximityKeyDetector();
init();
}
private void init() {
mSuggest.setQuickFixesEnabled(false);
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
mKeyDetector.setKeyboard(mKeyboard, 0, 0);
mKeyDetector.setProximityCorrectionEnabled(true);
mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(mKeyboard));
}
/** Uses both main dictionary and user-bigram dictionary **/
public SuggestHelper(String tag, Context context, int resId, int userBigramMax,
int userBigramDelete) {
this(tag, context, resId);
mUserBigram = new UserBigramDictionary(context, null, Locale.US.toString(),
Suggest.DIC_USER);
mUserBigram.setDatabaseMax(userBigramMax);
mUserBigram.setDatabaseDelete(userBigramDelete);
mSuggest.setUserBigramDictionary(mUserBigram);
public void setCorrectionMode(int correctionMode) {
mSuggest.setCorrectionMode(correctionMode);
}
void changeUserBigramLocale(Context context, Locale locale) {
if (mUserBigram != null) {
flushUserBigrams();
mUserBigram.close();
mUserBigram = new UserBigramDictionary(context, null, locale.toString(),
Suggest.DIC_USER);
mSuggest.setUserBigramDictionary(mUserBigram);
public boolean hasMainDictionary() {
return mSuggest.hasMainDictionary();
}
private int[] getProximityCodes(char c) {
final List<Key> keys = mKeyboard.getKeys();
for (final Key key : keys) {
if (key.mCode == c) {
final int x = key.mX + key.mWidth / 2;
final int y = key.mY + key.mHeight / 2;
final int[] codes = mKeyDetector.newCodeArray();
mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
return codes;
}
}
return new int[] { c };
}
private WordComposer createWordComposer(CharSequence s) {
protected 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);
word.add(c, getProximityCodes(c));
}
return word;
}
private boolean isDefaultSuggestion(SuggestedWords 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.getWord(1), word)));
public boolean isValidWord(CharSequence typed) {
return mSuggest.isValidWord(typed);
}
boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) {
public CharSequence getFirstSuggestion(CharSequence typed) {
WordComposer word = createWordComposer(typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
return isDefaultSuggestion(suggestions, expected);
// Note that suggestions.getWord(0) is the word user typed.
return suggestions.size() > 1 ? suggestions.getWord(1) : null;
}
boolean isDefaultCorrection(CharSequence typed, CharSequence expected) {
public CharSequence getAutoCorrection(CharSequence typed) {
WordComposer word = createWordComposer(typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
return isDefaultSuggestion(suggestions, expected) && mSuggest.hasAutoCorrection();
// Note that suggestions.getWord(0) is the word user typed.
return (suggestions.size() > 1 && mSuggest.hasAutoCorrection())
? suggestions.getWord(1) : null;
}
boolean isASuggestion(CharSequence typed, CharSequence expected) {
public int getSuggestIndex(CharSequence typed, CharSequence expected) {
WordComposer word = createWordComposer(typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, null);
// Note that suggestions.getWord(0) is the word user typed.
for (int i = 1; i < suggestions.size(); i++) {
if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
if (TextUtils.equals(suggestions.getWord(i), expected))
return i;
}
return false;
return -1;
}
private void getBigramSuggestions(CharSequence previous, CharSequence typed) {
@ -117,109 +124,30 @@ public class SuggestHelper {
}
}
boolean isDefaultNextSuggestion(CharSequence previous, CharSequence typed,
CharSequence expected) {
public CharSequence getBigramFirstSuggestion(CharSequence previous, CharSequence typed) {
WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
return isDefaultSuggestion(suggestions, expected);
return suggestions.size() > 1 ? suggestions.getWord(1) : null;
}
boolean isDefaultNextCorrection(CharSequence previous, CharSequence typed,
CharSequence expected) {
public CharSequence getBigramAutoCorrection(CharSequence previous, CharSequence typed) {
WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
return isDefaultSuggestion(suggestions, expected) && mSuggest.hasAutoCorrection();
return (suggestions.size() > 1 && mSuggest.hasAutoCorrection())
? suggestions.getWord(1) : null;
}
boolean isASuggestion(CharSequence previous, CharSequence typed,
public int searchBigramSuggestion(CharSequence previous, CharSequence typed,
CharSequence expected) {
WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed);
SuggestedWords suggestions = mSuggest.getSuggestions(null, word, previous);
for (int i = 1; i < suggestions.size(); i++) {
if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
if (TextUtils.equals(suggestions.getWord(i), expected))
return i;
}
return false;
return -1;
}
boolean isValid(CharSequence typed) {
return mSuggest.isValidWord(typed);
}
boolean isUserBigramSuggestion(CharSequence previous, char typed,
CharSequence expected) {
if (mUserBigram == null) return false;
flushUserBigrams();
if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) {
WordComposer firstChar = createWordComposer(Character.toString(typed));
mSuggest.getSuggestions(null, firstChar, previous);
boolean reloading = mUserBigram.reloadDictionaryIfRequired();
if (reloading) mUserBigram.waitForDictionaryLoading();
mUserBigram.getBigrams(firstChar, previous, mSuggest, null);
}
List<CharSequence> suggestions = mSuggest.mBigramSuggestions;
for (int i = 0; i < suggestions.size(); i++) {
if (TextUtils.equals(suggestions.get(i), expected)) return true;
}
return false;
}
void addToUserBigram(String sentence) {
StringTokenizer st = new StringTokenizer(sentence);
String previous = null;
while (st.hasMoreTokens()) {
String current = st.nextToken();
if (previous != null) {
addToUserBigram(new String[] {previous, current});
}
previous = current;
}
}
void addToUserBigram(String[] pair) {
if (mUserBigram != null && pair.length == 2) {
mUserBigram.addBigrams(pair[0], pair[1]);
}
}
void flushUserBigrams() {
if (mUserBigram != null) {
mUserBigram.flushPendingWrites();
mUserBigram.waitUntilUpdateDBDone();
}
}
final 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},
};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2010,2011 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
@ -15,70 +15,76 @@
*/
package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import android.util.Log;
import com.android.inputmethod.latin.tests.R;
import java.io.InputStreamReader;
import java.io.InputStream;
import android.content.res.AssetFileDescriptor;
import android.text.TextUtils;
import android.util.Slog;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class SuggestPerformanceTests extends AndroidTestCase {
private static final String TAG = "SuggestPerformanceTests";
public class SuggestPerformanceTests extends SuggestTestsBase {
private static final String TAG = SuggestPerformanceTests.class.getSimpleName();
private String mTestText;
private SuggestHelper sh;
private SuggestHelper mHelper;
@Override
protected void setUp() {
// TODO Figure out a way to directly using the dictionary rather than copying it over
// For testing with real dictionary, TEMPORARILY COPY main dictionary into test directory.
// DO NOT SUBMIT real dictionary under test directory.
//int resId = R.raw.main;
int resId = R.raw.test;
sh = new SuggestHelper(TAG, getTestContext(), resId);
loadString();
protected void setUp() throws Exception {
super.setUp();
final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
mHelper = new SuggestHelper(
getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
US_KEYBOARD_ID);
loadString(R.raw.testtext);
}
private void loadString() {
private void loadString(int testFileId) {
final String testFile = getTestContext().getResources().getResourceName(testFileId);
BufferedReader reader = null;
try {
InputStream is = getTestContext().getResources().openRawResource(R.raw.testtext);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = reader.readLine();
while (line != null) {
sb.append(line + " ");
line = reader.readLine();
reader = new BufferedReader(
new InputStreamReader(openTestRawResource(testFileId)));
final StringBuilder sb = new StringBuilder();
String line;
Slog.i(TAG, "Reading test file " + testFile);
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append(" ");
}
mTestText = sb.toString();
} catch (Exception e) {
Slog.e(TAG, "Can not read " + testFile);
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
Slog.e(TAG, "Closing " + testFile + " failed");
}
}
}
}
/************************** Helper functions ************************/
private int lookForSuggestion(String prevWord, String currentWord) {
private int lookForBigramSuggestion(String prevWord, String currentWord) {
for (int i = 1; i < currentWord.length(); i++) {
if (i == 1) {
if (sh.isDefaultNextSuggestion(prevWord, currentWord.substring(0, i),
currentWord)) {
return i;
}
} else {
if (sh.isDefaultNextCorrection(prevWord, currentWord.substring(0, i),
currentWord)) {
return i;
}
}
final CharSequence prefix = currentWord.substring(0, i);
final CharSequence word = (i == 1)
? mHelper.getBigramFirstSuggestion(prevWord, prefix)
: mHelper.getBigramAutoCorrection(prevWord, prefix);
if (TextUtils.equals(word, currentWord))
return i;
}
return currentWord.length();
}
private double runText(boolean withBigrams) {
mHelper.setCorrectionMode(
withBigrams ? Suggest.CORRECTION_FULL_BIGRAM : Suggest.CORRECTION_FULL);
StringTokenizer st = new StringTokenizer(mTestText);
String prevWord = null;
int typeCount = 0;
@ -92,9 +98,9 @@ public class SuggestPerformanceTests extends AndroidTestCase {
endCheck = true;
}
if (withBigrams && prevWord != null) {
typeCount += lookForSuggestion(prevWord, currentWord);
typeCount += lookForBigramSuggestion(prevWord, currentWord);
} else {
typeCount += lookForSuggestion(null, currentWord);
typeCount += lookForBigramSuggestion(null, currentWord);
}
characterCount += currentWord.length();
if (!endCheck) prevWord = currentWord;
@ -103,14 +109,14 @@ public class SuggestPerformanceTests extends AndroidTestCase {
double result = (double) (characterCount - typeCount) / characterCount * 100;
if (withBigrams) {
Log.i(TAG, "with bigrams -> " + result + " % saved!");
Slog.i(TAG, "with bigrams -> " + result + " % saved!");
} else {
Log.i(TAG, "without bigrams -> " + result + " % saved!");
Slog.i(TAG, "without bigrams -> " + result + " % saved!");
}
Log.i(TAG, "\ttotal number of words: " + wordCount);
Log.i(TAG, "\ttotal number of characters: " + mTestText.length());
Log.i(TAG, "\ttotal number of characters without space: " + characterCount);
Log.i(TAG, "\ttotal number of characters typed: " + typeCount);
Slog.i(TAG, "\ttotal number of words: " + wordCount);
Slog.i(TAG, "\ttotal number of characters: " + mTestText.length());
Slog.i(TAG, "\ttotal number of characters without space: " + characterCount);
Slog.i(TAG, "\ttotal number of characters typed: " + typeCount);
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2010,2011 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
@ -16,18 +16,21 @@
package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import com.android.inputmethod.latin.tests.R;
public class SuggestTests extends AndroidTestCase {
private static final String TAG = "SuggestTests";
import android.content.res.AssetFileDescriptor;
private SuggestHelper sh;
public class SuggestTests extends SuggestTestsBase {
private SuggestHelper mHelper;
@Override
protected void setUp() {
int resId = R.raw.test;
sh = new SuggestHelper(TAG, getTestContext(), resId);
protected void setUp() throws Exception {
super.setUp();
final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
mHelper = new SuggestHelper(
getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
US_KEYBOARD_ID);
mHelper.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
}
/************************** Tests ************************/
@ -36,105 +39,105 @@ public class SuggestTests extends AndroidTestCase {
* Tests for simple completions of one character.
*/
public void testCompletion1char() {
assertTrue(sh.isDefaultSuggestion("peopl", "people"));
assertTrue(sh.isDefaultSuggestion("abou", "about"));
assertTrue(sh.isDefaultSuggestion("thei", "their"));
suggested("people", mHelper.getFirstSuggestion("peopl"));
suggested("about", mHelper.getFirstSuggestion("abou"));
suggested("their", mHelper.getFirstSuggestion("thei"));
}
/**
* Tests for simple completions of two characters.
*/
public void testCompletion2char() {
assertTrue(sh.isDefaultSuggestion("peop", "people"));
assertTrue(sh.isDefaultSuggestion("calli", "calling"));
assertTrue(sh.isDefaultSuggestion("busine", "business"));
suggested("people", mHelper.getFirstSuggestion("peop"));
suggested("calling", mHelper.getFirstSuggestion("calli"));
suggested("business", mHelper.getFirstSuggestion("busine"));
}
/**
* Tests for proximity errors.
*/
public void testProximityPositive() {
assertTrue(sh.isDefaultSuggestion("peiple", "people"));
assertTrue(sh.isDefaultSuggestion("peoole", "people"));
assertTrue(sh.isDefaultSuggestion("pwpple", "people"));
suggested("typed peiple", "people", mHelper.getFirstSuggestion("peiple"));
suggested("typed peoole", "people", mHelper.getFirstSuggestion("peoole"));
suggested("typed pwpple", "people", mHelper.getFirstSuggestion("pwpple"));
}
/**
* Tests for proximity errors - negative, when the error key is not near.
* Tests for proximity errors - negative, when the error key is not close.
*/
public void testProximityNegative() {
assertFalse(sh.isDefaultSuggestion("arout", "about"));
assertFalse(sh.isDefaultSuggestion("ire", "are"));
notSuggested("about", mHelper.getFirstSuggestion("arout"));
notSuggested("are", mHelper.getFirstSuggestion("ire"));
}
/**
* Tests for checking if apostrophes are added automatically.
*/
public void testApostropheInsertion() {
assertTrue(sh.isDefaultSuggestion("im", "I'm"));
assertTrue(sh.isDefaultSuggestion("dont", "don't"));
suggested("I'm", mHelper.getFirstSuggestion("im"));
suggested("don't", mHelper.getFirstSuggestion("dont"));
}
/**
* Test to make sure apostrophed word is not suggested for an apostrophed word.
*/
public void testApostrophe() {
assertFalse(sh.isDefaultSuggestion("don't", "don't"));
notSuggested("don't", mHelper.getFirstSuggestion("don't"));
}
/**
* Tests for suggestion of capitalized version of a word.
*/
public void testCapitalization() {
assertTrue(sh.isDefaultSuggestion("i'm", "I'm"));
assertTrue(sh.isDefaultSuggestion("sunday", "Sunday"));
assertTrue(sh.isDefaultSuggestion("sundat", "Sunday"));
suggested("I'm", mHelper.getFirstSuggestion("i'm"));
suggested("Sunday", mHelper.getFirstSuggestion("sunday"));
suggested("Sunday", mHelper.getFirstSuggestion("sundat"));
}
/**
* Tests to see if more than one completion is provided for certain prefixes.
*/
public void testMultipleCompletions() {
assertTrue(sh.isASuggestion("com", "come"));
assertTrue(sh.isASuggestion("com", "company"));
assertTrue(sh.isASuggestion("th", "the"));
assertTrue(sh.isASuggestion("th", "that"));
assertTrue(sh.isASuggestion("th", "this"));
assertTrue(sh.isASuggestion("th", "they"));
isInSuggestions("com: come", mHelper.getSuggestIndex("com", "come"));
isInSuggestions("com: company", mHelper.getSuggestIndex("com", "company"));
isInSuggestions("th: the", mHelper.getSuggestIndex("th", "the"));
isInSuggestions("th: that", mHelper.getSuggestIndex("th", "that"));
isInSuggestions("th: this", mHelper.getSuggestIndex("th", "this"));
isInSuggestions("th: they", mHelper.getSuggestIndex("th", "they"));
}
/**
* Does the suggestion engine recognize zero frequency words as valid words.
*/
public void testZeroFrequencyAccepted() {
assertTrue(sh.isValid("yikes"));
assertFalse(sh.isValid("yike"));
assertTrue("valid word yikes", mHelper.isValidWord("yikes"));
assertFalse("non valid word yike", mHelper.isValidWord("yike"));
}
/**
* Tests to make sure that zero frequency words are not suggested as completions.
*/
public void testZeroFrequencySuggestionsNegative() {
assertFalse(sh.isASuggestion("yike", "yikes"));
assertFalse(sh.isASuggestion("what", "whatcha"));
assertNull(mHelper.getSuggestIndex("yike", "yikes"));
assertNull(mHelper.getSuggestIndex("what", "whatcha"));
}
/**
* Tests to ensure that words with large edit distances are not suggested, in some cases
* and not considered corrections, in some cases.
* Tests to ensure that words with large edit distances are not suggested, in some cases.
* Also such word is not considered auto correction, in some cases.
*/
public void testTooLargeEditDistance() {
assertFalse(sh.isASuggestion("sniyr", "about"));
assertNull(mHelper.getSuggestIndex("sniyr", "about"));
// TODO: The following test fails.
// assertFalse(sh.isDefaultCorrection("rjw", "the"));
// notSuggested("the", mHelper.getAutoCorrection("rjw"));
}
/**
* Make sure sh.isValid is case-sensitive.
* Make sure mHelper.isValidWord is case-sensitive.
*/
public void testValidityCaseSensitivity() {
assertTrue(sh.isValid("Sunday"));
assertFalse(sh.isValid("sunday"));
assertTrue("valid word Sunday", mHelper.isValidWord("Sunday"));
assertFalse("non valid word sunday", mHelper.isValidWord("sunday"));
}
/**
@ -142,11 +145,11 @@ public class SuggestTests extends AndroidTestCase {
*/
public void testAccents() {
// ni<LATIN SMALL LETTER N WITH TILDE>o
assertTrue(sh.isDefaultCorrection("nino", "ni\u00F1o"));
suggested("ni\u00F1o", mHelper.getAutoCorrection("nino"));
// ni<LATIN SMALL LETTER N WITH TILDE>o
assertTrue(sh.isDefaultCorrection("nimo", "ni\u00F1o"));
suggested("ni\u00F1o", mHelper.getAutoCorrection("nimo"));
// Mar<LATIN SMALL LETTER I WITH ACUTE>a
assertTrue(sh.isDefaultCorrection("maria", "Mar\u00EDa"));
suggested("Mar\u00EDa", mHelper.getAutoCorrection("maria"));
}
/**
@ -154,21 +157,29 @@ public class SuggestTests extends AndroidTestCase {
* and don't show any when there aren't any
*/
public void testBigramsAtFirstChar() {
assertTrue(sh.isDefaultNextSuggestion("about", "p", "part"));
assertTrue(sh.isDefaultNextSuggestion("I'm", "a", "about"));
assertTrue(sh.isDefaultNextSuggestion("about", "b", "business"));
assertTrue(sh.isASuggestion("about", "b", "being"));
assertFalse(sh.isDefaultNextSuggestion("about", "p", "business"));
suggested("bigram: about p[art]",
"part", mHelper.getBigramFirstSuggestion("about", "p"));
suggested("bigram: I'm a[bout]",
"about", mHelper.getBigramFirstSuggestion("I'm", "a"));
suggested("bigram: about b[usiness]",
"business", mHelper.getBigramFirstSuggestion("about", "b"));
isInSuggestions("bigram: about b[eing]",
mHelper.searchBigramSuggestion("about", "b", "being"));
notSuggested("bigram: about p",
"business", mHelper.getBigramFirstSuggestion("about", "p"));
}
/**
* Make sure bigrams score affects the original score
*/
public void testBigramsScoreEffect() {
assertTrue(sh.isDefaultCorrection("pa", "page"));
assertTrue(sh.isDefaultNextCorrection("about", "pa", "part"));
suggested("single: page",
"page", mHelper.getAutoCorrection("pa"));
suggested("bigram: about pa[rt]",
"part", mHelper.getBigramAutoCorrection("about", "pa"));
// TODO: The following test fails.
// assertTrue(sh.isDefaultCorrection("sa", "said"));
assertTrue(sh.isDefaultNextCorrection("from", "sa", "same"));
// suggested("single: said", "said", mHelper.getAutoCorrection("sa"));
suggested("bigram: from sa[me]",
"same", mHelper.getBigramAutoCorrection("from", "sa"));
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2011 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.
*/
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardView;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import java.io.File;
import java.io.InputStream;
import java.util.Locale;
public class SuggestTestsBase extends AndroidTestCase {
protected static final KeyboardId US_KEYBOARD_ID = new KeyboardId("en_US qwerty keyboard",
com.android.inputmethod.latin.R.xml.kbd_qwerty, Locale.US,
Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT,
KeyboardView.COLOR_SCHEME_WHITE, false, false, false, 0, false);
protected File mTestPackageFile;
@Override
protected void setUp() throws Exception {
super.setUp();
mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir);
}
protected InputStream openTestRawResource(int resIdInTest) {
return getTestContext().getResources().openRawResource(resIdInTest);
}
protected AssetFileDescriptor openTestRawResourceFd(int resIdInTest) {
return getTestContext().getResources().openRawResourceFd(resIdInTest);
}
private static String format(String message, Object expected, Object actual) {
return message + " expected:<" + expected + "> but was:<" + actual + ">";
}
protected static void suggested(CharSequence expected, CharSequence actual) {
if (!TextUtils.equals(expected, actual))
fail(format("assertEquals", expected, actual));
}
protected static void suggested(String message, CharSequence expected, CharSequence actual) {
if (!TextUtils.equals(expected, actual))
fail(format(message, expected, actual));
}
protected static void notSuggested(CharSequence expected, CharSequence actual) {
if (TextUtils.equals(expected, actual))
fail(format("assertNotEquals", expected, actual));
}
protected static void notSuggested(String message, CharSequence expected, CharSequence actual) {
if (TextUtils.equals(expected, actual))
fail(format(message, expected, actual));
}
protected static void isInSuggestions(String message, int position) {
assertTrue(message, position >= 0);
}
protected static void isNotInSuggestions(String message, int position) {
assertTrue(message, position < 0);
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2011 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.
*/
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.KeyboardId;
import android.content.Context;
import android.text.TextUtils;
import java.io.File;
import java.util.Locale;
import java.util.StringTokenizer;
public class UserBigramSuggestHelper extends SuggestHelper {
private final Context mContext;
private UserBigramDictionary mUserBigram;
public UserBigramSuggestHelper(Context context, File dictionaryPath, long startOffset,
long length, int userBigramMax, int userBigramDelete, KeyboardId keyboardId) {
super(context, dictionaryPath, startOffset, length, keyboardId);
mContext = context;
mUserBigram = new UserBigramDictionary(context, null, Locale.US.toString(),
Suggest.DIC_USER);
mUserBigram.setDatabaseMax(userBigramMax);
mUserBigram.setDatabaseDelete(userBigramDelete);
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
mSuggest.setUserBigramDictionary(mUserBigram);
}
public void changeUserBigramLocale(Locale locale) {
if (mUserBigram != null) {
flushUserBigrams();
mUserBigram.close();
mUserBigram = new UserBigramDictionary(mContext, null, locale.toString(),
Suggest.DIC_USER);
mSuggest.setUserBigramDictionary(mUserBigram);
}
}
public int searchUserBigramSuggestion(CharSequence previous, char typed,
CharSequence expected) {
if (mUserBigram == null) return -1;
flushUserBigrams();
if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) {
WordComposer firstChar = createWordComposer(Character.toString(typed));
mSuggest.getSuggestions(null, firstChar, previous);
boolean reloading = mUserBigram.reloadDictionaryIfRequired();
if (reloading) mUserBigram.waitForDictionaryLoading();
mUserBigram.getBigrams(firstChar, previous, mSuggest, null);
}
for (int i = 0; i < mSuggest.mBigramSuggestions.size(); i++) {
final CharSequence word = mSuggest.mBigramSuggestions.get(i);
if (TextUtils.equals(word, expected))
return i;
}
return -1;
}
public void addToUserBigram(String sentence) {
StringTokenizer st = new StringTokenizer(sentence);
String previous = null;
while (st.hasMoreTokens()) {
String current = st.nextToken();
if (previous != null) {
addToUserBigram(new String[] {previous, current});
}
previous = current;
}
}
public void addToUserBigram(String[] pair) {
if (mUserBigram != null && pair.length == 2) {
mUserBigram.addBigrams(pair[0], pair[1]);
}
}
public void flushUserBigrams() {
if (mUserBigram != null) {
mUserBigram.flushPendingWrites();
mUserBigram.waitUntilUpdateDBDone();
}
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (C) 2010,2011 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.
*/
package com.android.inputmethod.latin;
import com.android.inputmethod.latin.tests.R;
import android.content.res.AssetFileDescriptor;
import java.util.Locale;
public class UserBigramSuggestTests extends SuggestTestsBase {
private static final int SUGGESTION_STARTS = 6;
private static final int MAX_DATA = 20;
private static final int DELETE_DATA = 10;
private UserBigramSuggestHelper mHelper;
@Override
protected void setUp() throws Exception {
super.setUp();
final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test);
mHelper = new UserBigramSuggestHelper(
getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(),
MAX_DATA, DELETE_DATA, US_KEYBOARD_ID);
}
/************************** Tests ************************/
/**
* Test suggestion started at right time
*/
public void testUserBigram() {
for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair1);
for (int i = 0; i < (SUGGESTION_STARTS - 1); i++) mHelper.addToUserBigram(pair2);
isInSuggestions("bigram", mHelper.searchUserBigramSuggestion("user", 'b', "bigram"));
isNotInSuggestions("platform",
mHelper.searchUserBigramSuggestion("android", 'p', "platform"));
}
/**
* Test loading correct (locale) bigrams
*/
public void testOpenAndClose() {
for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair1);
isInSuggestions("bigram in default locale",
mHelper.searchUserBigramSuggestion("user", 'b', "bigram"));
// change to fr_FR
mHelper.changeUserBigramLocale(Locale.FRANCE);
for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair3);
isInSuggestions("france in fr_FR",
mHelper.searchUserBigramSuggestion("locale", 'f', "france"));
isNotInSuggestions("bigram in fr_FR",
mHelper.searchUserBigramSuggestion("user", 'b', "bigram"));
// change back to en_US
mHelper.changeUserBigramLocale(Locale.US);
isNotInSuggestions("france in en_US",
mHelper.searchUserBigramSuggestion("locale", 'f', "france"));
isInSuggestions("bigram in en_US",
mHelper.searchUserBigramSuggestion("user", 'b', "bigram"));
}
/**
* Test data gets pruned when it is over maximum
*/
public void testPruningData() {
for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(sentence0);
mHelper.flushUserBigrams();
isInSuggestions("world after several sentence 0",
mHelper.searchUserBigramSuggestion("Hello", 'w', "world"));
mHelper.addToUserBigram(sentence1);
mHelper.addToUserBigram(sentence2);
isInSuggestions("world after sentence 1 and 2",
mHelper.searchUserBigramSuggestion("Hello", 'w', "world"));
// pruning should happen
mHelper.addToUserBigram(sentence3);
mHelper.addToUserBigram(sentence4);
// trying to reopen database to check pruning happened in database
mHelper.changeUserBigramLocale(Locale.US);
isNotInSuggestions("world after sentence 3 and 4",
mHelper.searchUserBigramSuggestion("Hello", 'w', "world"));
}
private static final String[] pair1 = {"user", "bigram"};
private static final String[] pair2 = {"android","platform"};
private static final String[] pair3 = {"locale", "france"};
private static final String sentence0 = "Hello world";
private static final String sentence1 = "This is a test for user input based bigram";
private static final String sentence2 = "It learns phrases that contain both dictionary and "
+ "nondictionary words";
private static final String sentence3 = "This should give better suggestions than the previous "
+ "version";
private static final String sentence4 = "Android stock keyboard is improving";
}

View File

@ -1,100 +0,0 @@
/*
* 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.
*/
package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import com.android.inputmethod.latin.tests.R;
import java.util.Locale;
public class UserBigramTests extends AndroidTestCase {
private static final String TAG = "UserBigramTests";
private static final int SUGGESTION_STARTS = 6;
private static final int MAX_DATA = 20;
private static final int DELETE_DATA = 10;
private SuggestHelper sh;
@Override
protected void setUp() {
int resId = R.raw.test;
sh = new SuggestHelper(TAG, getTestContext(), resId, MAX_DATA, DELETE_DATA);
}
/************************** Tests ************************/
/**
* Test suggestion started at right time
*/
public void testUserBigram() {
for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair1);
for (int i = 0; i < (SUGGESTION_STARTS - 1); i++) sh.addToUserBigram(pair2);
assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
assertFalse(sh.isUserBigramSuggestion("android", 'p', "platform"));
}
/**
* Test loading correct (locale) bigrams
*/
public void testOpenAndClose() {
for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair1);
assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
// change to fr_FR
sh.changeUserBigramLocale(getTestContext(), Locale.FRANCE);
for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair3);
assertTrue(sh.isUserBigramSuggestion("locale", 'f', "france"));
assertFalse(sh.isUserBigramSuggestion("user", 'b', "bigram"));
// change back to en_US
sh.changeUserBigramLocale(getTestContext(), Locale.US);
assertFalse(sh.isUserBigramSuggestion("locale", 'f', "france"));
assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
}
/**
* Test data gets pruned when it is over maximum
*/
public void testPruningData() {
for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(sentence0);
sh.flushUserBigrams();
assertTrue(sh.isUserBigramSuggestion("Hello", 'w', "world"));
sh.addToUserBigram(sentence1);
sh.addToUserBigram(sentence2);
assertTrue(sh.isUserBigramSuggestion("Hello", 'w', "world"));
// pruning should happen
sh.addToUserBigram(sentence3);
sh.addToUserBigram(sentence4);
// trying to reopen database to check pruning happened in database
sh.changeUserBigramLocale(getTestContext(), Locale.US);
assertFalse(sh.isUserBigramSuggestion("Hello", 'w', "world"));
}
final String[] pair1 = new String[] {"user", "bigram"};
final String[] pair2 = new String[] {"android","platform"};
final String[] pair3 = new String[] {"locale", "france"};
final String sentence0 = "Hello world";
final String sentence1 = "This is a test for user input based bigram";
final String sentence2 = "It learns phrases that contain both dictionary and nondictionary "
+ "words";
final String sentence3 = "This should give better suggestions than the previous version";
final String sentence4 = "Android stock keyboard is improving";
}