diff options
Diffstat (limited to 'tests/src')
4 files changed, 551 insertions, 0 deletions
diff --git a/tests/src/com/android/inputmethod/latin/ImeLoggerTests.java b/tests/src/com/android/inputmethod/latin/ImeLoggerTests.java new file mode 100644 index 000000000..234559bb7 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/ImeLoggerTests.java @@ -0,0 +1,59 @@ +package com.android.inputmethod.latin; + +import android.test.ServiceTestCase; + +public class ImeLoggerTests extends ServiceTestCase<LatinIME> { + + private static final String WORD_SEPARATORS + = ".\u0009\u0020,;:!?\n()[]*&@{}<>;_+=|\\u0022"; + + public ImeLoggerTests() { + super(LatinIME.class); + } + static LatinImeLogger sLogger; + @Override + protected void setUp() { + try { + super.setUp(); + } catch (Exception e) { + e.printStackTrace(); + } + setupService(); + // startService(null); // can't be started because VoiceInput can't be found. + final LatinIME context = getService(); + context.mWordSeparators = WORD_SEPARATORS; + LatinImeLogger.init(context); + sLogger = LatinImeLogger.sLatinImeLogger; + } + /*********************** Tests *********************/ + public void testRingBuffer() { + for (int i = 0; i < sLogger.mRingCharBuffer.BUFSIZE * 2; ++i) { + LatinImeLogger.logOnDelete(); + } + assertEquals("", sLogger.mRingCharBuffer.getLastString()); + LatinImeLogger.logOnInputChar('t'); + LatinImeLogger.logOnInputChar('g'); + LatinImeLogger.logOnInputChar('i'); + LatinImeLogger.logOnInputChar('s'); + LatinImeLogger.logOnInputChar(' '); + LatinImeLogger.logOnAutoSuggestion("tgis", "this"); + LatinImeLogger.logOnInputChar(' '); + LatinImeLogger.logOnDelete(); + assertEquals("", sLogger.mRingCharBuffer.getLastString()); + LatinImeLogger.logOnDelete(); + assertEquals("tgis", sLogger.mRingCharBuffer.getLastString()); + assertEquals("tgis", LatinImeLogger.sLastAutoSuggestBefore); + LatinImeLogger.logOnAutoSuggestionCanceled(); + assertEquals("", LatinImeLogger.sLastAutoSuggestBefore); + LatinImeLogger.logOnDelete(); + assertEquals("tgi", sLogger.mRingCharBuffer.getLastString()); + for (int i = 0; i < sLogger.mRingCharBuffer.BUFSIZE * 2; ++i) { + LatinImeLogger.logOnDelete(); + } + assertEquals("", sLogger.mRingCharBuffer.getLastString()); + for (int i = 0; i < sLogger.mRingCharBuffer.BUFSIZE * 2; ++i) { + LatinImeLogger.logOnInputChar('a'); + } + assertEquals(sLogger.mRingCharBuffer.BUFSIZE, sLogger.mRingCharBuffer.length); + } +} diff --git a/tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java new file mode 100644 index 000000000..107f04c7c --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java @@ -0,0 +1,193 @@ +/* + * 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.tests; + +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; + +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; + +public class SuggestHelper { + private Suggest mSuggest; + private final String TAG; + + public SuggestHelper(String tag, Context context, int[] resId) { + TAG = tag; + InputStream[] res = null; + try { + // merging separated dictionary into one if dictionary is separated + int total = 0; + res = new InputStream[resId.length]; + for (int i = 0; i < resId.length; i++) { + res[i] = context.getResources().openRawResource(resId[i]); + total += res[i].available(); + } + + ByteBuffer byteBuffer = + ByteBuffer.allocateDirect(total).order(ByteOrder.nativeOrder()); + int got = 0; + for (int i = 0; i < resId.length; i++) { + got += Channels.newChannel(res[i]).read(byteBuffer); + } + if (got != total) { + Log.w(TAG, "Read " + got + " bytes, expected " + total); + } else { + mSuggest = new Suggest(context, byteBuffer); + Log.i(TAG, "Created mSuggest " + total + " bytes"); + } + } catch (IOException e) { + Log.w(TAG, "No available memory for binary dictionary"); + } finally { + try { + for (int i = 0;i < res.length; i++) { + res[i].close(); + } + } catch (IOException e) { + Log.w(TAG, "Failed to close input stream"); + } + } + mSuggest.setAutoTextEnabled(false); + mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM); + } + + 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))); + } + + boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) { + WordComposer word = createWordComposer(typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); + return isDefaultSuggestion(suggestions, expected); + } + + boolean isDefaultCorrection(CharSequence typed, CharSequence expected) { + WordComposer word = createWordComposer(typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); + return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection(); + } + + boolean isASuggestion(CharSequence typed, CharSequence expected) { + WordComposer word = createWordComposer(typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); + for (int i = 1; i < suggestions.size(); i++) { + if (TextUtils.equals(suggestions.get(i), expected)) return true; + } + return false; + } + + private void getBigramSuggestions(CharSequence previous, CharSequence typed) { + if(!TextUtils.isEmpty(previous) && (typed.length() > 1)) { + WordComposer firstChar = createWordComposer(typed.charAt(0) + ""); + mSuggest.getSuggestions(null, firstChar, false, previous); + } + } + + boolean isDefaultNextSuggestion(CharSequence previous, CharSequence typed, + CharSequence expected) { + WordComposer word = createWordComposer(typed); + getBigramSuggestions(previous, typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); + return isDefaultSuggestion(suggestions, expected); + } + + boolean isDefaultNextCorrection(CharSequence previous, CharSequence typed, + CharSequence expected) { + WordComposer word = createWordComposer(typed); + getBigramSuggestions(previous, typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); + return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection(); + } + + boolean isASuggestion(CharSequence previous, CharSequence typed, + CharSequence expected) { + WordComposer word = createWordComposer(typed); + getBigramSuggestions(previous, typed); + List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); + for (int i = 1; i < suggestions.size(); i++) { + if (TextUtils.equals(suggestions.get(i), expected)) return true; + } + return false; + } + + boolean isValid(CharSequence typed) { + return mSuggest.isValidWord(typed); + } + + 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/tests/SuggestPerformanceTests.java b/tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java new file mode 100644 index 000000000..473c440f9 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java @@ -0,0 +1,127 @@ +/* + * 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.tests; + +import android.test.AndroidTestCase; +import android.util.Log; + +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.BufferedReader; +import java.util.StringTokenizer; +import java.util.regex.Pattern; + +public class SuggestPerformanceTests extends AndroidTestCase { + private static final String TAG = "SuggestPerformanceTests"; + + private String mTestText; + private SuggestHelper sh; + + @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 = new int[] { R.raw.main0, R.raw.main1, R.raw.main2 }; + + int[] resId = new int[] { R.raw.test }; + + sh = new SuggestHelper(TAG, getTestContext(), resId); + loadString(); + } + + private void loadString() { + 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(); + } + mTestText = sb.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /************************** Helper functions ************************/ + private int lookForSuggestion(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; + } + } + } + return currentWord.length(); + } + + private double runText(boolean withBigrams) { + StringTokenizer st = new StringTokenizer(mTestText); + String prevWord = null; + int typeCount = 0; + int characterCount = 0; // without space + int wordCount = 0; + while (st.hasMoreTokens()) { + String currentWord = st.nextToken(); + boolean endCheck = false; + if (currentWord.matches("[\\w]*[\\.|?|!|*|@|&|/|:|;]")) { + currentWord = currentWord.substring(0, currentWord.length() - 1); + endCheck = true; + } + if (withBigrams && prevWord != null) { + typeCount += lookForSuggestion(prevWord, currentWord); + } else { + typeCount += lookForSuggestion(null, currentWord); + } + characterCount += currentWord.length(); + if (!endCheck) prevWord = currentWord; + wordCount++; + } + + double result = (double) (characterCount - typeCount) / characterCount * 100; + if (withBigrams) { + Log.i(TAG, "with bigrams -> " + result + " % saved!"); + } else { + Log.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); + return result; + } + + + /************************** Performance Tests ************************/ + /** + * Compare the Suggest with and without bigram + * Check the log for detail + */ + public void testSuggestPerformance() { + assertTrue(runText(false) < runText(true)); + } +} diff --git a/tests/src/com/android/inputmethod/latin/tests/SuggestTests.java b/tests/src/com/android/inputmethod/latin/tests/SuggestTests.java new file mode 100644 index 000000000..a42422b91 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/tests/SuggestTests.java @@ -0,0 +1,172 @@ +/* + * 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.tests; + +import android.test.AndroidTestCase; +import android.util.Log; + +public class SuggestTests extends AndroidTestCase { + private static final String TAG = "SuggestTests"; + + private SuggestHelper sh; + + @Override + protected void setUp() { + int[] resId = new int[] { R.raw.test }; + sh = new SuggestHelper(TAG, getTestContext(), resId); + } + + /************************** Tests ************************/ + + /** + * 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")); + } + + /** + * 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")); + } + + /** + * Tests for proximity errors. + */ + public void testProximityPositive() { + assertTrue(sh.isDefaultSuggestion("peiple", "people")); + assertTrue(sh.isDefaultSuggestion("peoole", "people")); + assertTrue(sh.isDefaultSuggestion("pwpple", "people")); + } + + /** + * Tests for proximity errors - negative, when the error key is not near. + */ + public void testProximityNegative() { + assertFalse(sh.isDefaultSuggestion("arout", "about")); + assertFalse(sh.isDefaultSuggestion("ire", "are")); + } + + /** + * Tests for checking if apostrophes are added automatically. + */ + public void testApostropheInsertion() { + assertTrue(sh.isDefaultSuggestion("im", "I'm")); + assertTrue(sh.isDefaultSuggestion("dont", "don't")); + } + + /** + * Test to make sure apostrophed word is not suggested for an apostrophed word. + */ + public void testApostrophe() { + assertFalse(sh.isDefaultSuggestion("don't", "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")); + } + + /** + * 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")); + } + + /** + * Does the suggestion engine recognize zero frequency words as valid words. + */ + public void testZeroFrequencyAccepted() { + assertTrue(sh.isValid("yikes")); + assertFalse(sh.isValid("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")); + } + + /** + * 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(sh.isASuggestion("sniyr", "about")); + assertFalse(sh.isDefaultCorrection("rjw", "the")); + } + + /** + * Make sure sh.isValid is case-sensitive. + */ + public void testValidityCaseSensitivity() { + assertTrue(sh.isValid("Sunday")); + assertFalse(sh.isValid("sunday")); + } + + /** + * Are accented forms of words suggested as corrections? + */ + public void testAccents() { + // ni<LATIN SMALL LETTER N WITH TILDE>o + assertTrue(sh.isDefaultCorrection("nino", "ni\u00F1o")); + // ni<LATIN SMALL LETTER N WITH TILDE>o + assertTrue(sh.isDefaultCorrection("nimo", "ni\u00F1o")); + // Mar<LATIN SMALL LETTER I WITH ACUTE>a + assertTrue(sh.isDefaultCorrection("maria", "Mar\u00EDa")); + } + + /** + * Make sure bigrams are showing when first character is typed + * 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")); + } + + /** + * Make sure bigrams score affects the original score + */ + public void testBigramsScoreEffect() { + assertTrue(sh.isDefaultCorrection("pa", "page")); + assertTrue(sh.isDefaultNextCorrection("about", "pa", "part")); + assertTrue(sh.isDefaultCorrection("sa", "said")); + assertTrue(sh.isDefaultNextCorrection("from", "sa", "same")); + } +} |