diff --git a/tests/Android.mk b/tests/Android.mk index fba7a8d74..658e8e294 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -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) diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java index e1c3678fd..d128cb3fa 100644 --- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java +++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java @@ -31,7 +31,7 @@ public class SubtypeLocaleTests extends AndroidTestCase { private static final String PACKAGE = LatinIME.class.getPackage().getName(); private Resources mRes; - private List mKeyboardSubtypes; + private List mKeyboardSubtypes = new ArrayList(); @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); } } diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java index bcc0d6cde..ce4e5dee7 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java +++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java @@ -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 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 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}, - }; } diff --git a/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java index c5913ab4f..95ce37e2c 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java +++ b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java @@ -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; } diff --git a/tests/src/com/android/inputmethod/latin/SuggestTests.java b/tests/src/com/android/inputmethod/latin/SuggestTests.java index c890394d0..38a6bf464 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestTests.java +++ b/tests/src/com/android/inputmethod/latin/SuggestTests.java @@ -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() { // nio - assertTrue(sh.isDefaultCorrection("nino", "ni\u00F1o")); + suggested("ni\u00F1o", mHelper.getAutoCorrection("nino")); // nio - assertTrue(sh.isDefaultCorrection("nimo", "ni\u00F1o")); + suggested("ni\u00F1o", mHelper.getAutoCorrection("nimo")); // Mara - 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")); } } diff --git a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java new file mode 100644 index 000000000..365cea865 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java @@ -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); + } +} diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java new file mode 100644 index 000000000..a6fb6e1e1 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java @@ -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(); + } + } +} diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java new file mode 100644 index 000000000..ab5329cfd --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java @@ -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"; +} diff --git a/tests/src/com/android/inputmethod/latin/UserBigramTests.java b/tests/src/com/android/inputmethod/latin/UserBigramTests.java deleted file mode 100644 index af527b02d..000000000 --- a/tests/src/com/android/inputmethod/latin/UserBigramTests.java +++ /dev/null @@ -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"; -}