aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src')
-rw-r--r--tests/src/com/android/inputmethod/latin/ImeLoggerTests.java59
-rw-r--r--tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java193
-rw-r--r--tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java127
-rw-r--r--tests/src/com/android/inputmethod/latin/tests/SuggestTests.java172
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"));
+ }
+}