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