aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src')
-rw-r--r--tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java2
-rw-r--r--tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java2
-rw-r--r--tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java216
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java11
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java2
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java24
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java52
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java135
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java25
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java628
-rw-r--r--tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java55
-rw-r--r--tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java18
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java52
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java105
-rw-r--r--tests/src/com/android/inputmethod/latin/InputPointersTests.java18
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java42
-rw-r--r--tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java (renamed from tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java)128
-rw-r--r--tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java357
-rw-r--r--tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java44
-rw-r--r--tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java119
-rw-r--r--tests/src/com/android/inputmethod/latin/WordComposerTests.java93
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java684
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java601
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java217
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java65
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java160
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver3DictDecoderTests.java150
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java246
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java73
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/Base64ReaderTests.java225
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java (renamed from tests/src/com/android/inputmethod/latin/CapsModeUtilsTests.java)2
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CsvUtilsTests.java424
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ForgettingCurveTests.java (renamed from tests/src/com/android/inputmethod/latin/ForgettingCurveTests.java)2
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java105
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java (renamed from tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java)2
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java (renamed from tests/src/com/android/inputmethod/latin/ResizableIntArrayTests.java)16
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ResourceUtilsTests.java (renamed from tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java)4
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java58
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java (renamed from tests/src/com/android/inputmethod/latin/StringUtilsTests.java)40
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java387
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java (renamed from tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java)56
41 files changed, 4086 insertions, 1559 deletions
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
index 01814ae13..6d9c3fdbb 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
@@ -47,7 +47,7 @@ public class MoreKeysKeyboardBuilderFixedOrderTests extends AndroidTestCase {
final int coordXInParent) {
final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParent, KEYBOARD_WIDTH,
- /* isFixedOrderColumn */true, /* dividerWidth */0);
+ true /* isFixedOrderColumn */, 0 /* dividerWidth */);
return params;
}
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
index ce5573da9..b213721bd 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
@@ -47,7 +47,7 @@ public class MoreKeysKeyboardBuilderTests extends AndroidTestCase {
final int coordXInParent) {
final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
params.setParameters(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParent, KEYBOARD_WIDTH,
- /* isFixedOrderColumn */false, /* dividerWidth */0);
+ false /* isFixedOrderColumn */, 0 /* dividerWidth */);
return params;
}
diff --git a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java b/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
deleted file mode 100644
index 850af94f7..000000000
--- a/tests/src/com/android/inputmethod/keyboard/SpacebarTextTests.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2012 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.keyboard;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.AdditionalSubtype;
-import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.StringUtils;
-import com.android.inputmethod.latin.SubtypeLocale;
-import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SmallTest
-public class SpacebarTextTests extends AndroidTestCase {
- // Locale to subtypes list.
- private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList();
-
- private RichInputMethodManager mRichImm;
- private Resources mRes;
-
- InputMethodSubtype EN_US;
- InputMethodSubtype EN_GB;
- InputMethodSubtype ES_US;
- InputMethodSubtype FR;
- InputMethodSubtype FR_CA;
- InputMethodSubtype DE;
- InputMethodSubtype ZZ;
- InputMethodSubtype DE_QWERTY;
- InputMethodSubtype FR_QWERTZ;
- InputMethodSubtype US_AZERTY;
- InputMethodSubtype ZZ_AZERTY;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- final Context context = getContext();
- RichInputMethodManager.init(context);
- mRichImm = RichInputMethodManager.getInstance();
- mRes = context.getResources();
- SubtypeLocale.init(context);
-
- EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.US.toString(), "qwerty");
- EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.UK.toString(), "qwerty");
- ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("es_US", "spanish");
- FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.FRENCH.toString(), "azerty");
- FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.CANADA_FRENCH.toString(), "qwerty");
- DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(Locale.GERMAN.toString(), "qwertz");
- ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(SubtypeLocale.NO_LANGUAGE, "qwerty");
- DE_QWERTY = AdditionalSubtype.createAdditionalSubtype(
- Locale.GERMAN.toString(), "qwerty", null);
- FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
- Locale.FRENCH.toString(), "qwertz", null);
- US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
- Locale.US.toString(), "azerty", null);
- ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
- SubtypeLocale.NO_LANGUAGE, "azerty", null);
- }
-
- public void testAllFullDisplayName() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
- final String spacebarText = MainKeyboardView.getFullDisplayName(subtype);
- final String languageName =
- SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
- if (SubtypeLocale.isNoLanguage(subtype)) {
- assertFalse(subtypeName, spacebarText.contains(languageName));
- } else {
- assertTrue(subtypeName, spacebarText.contains(languageName));
- }
- }
- }
-
- public void testAllMiddleDisplayName() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
- final String spacebarText = MainKeyboardView.getMiddleDisplayName(subtype);
- if (SubtypeLocale.isNoLanguage(subtype)) {
- assertEquals(subtypeName,
- SubtypeLocale.getKeyboardLayoutSetName(subtype), spacebarText);
- } else {
- assertEquals(subtypeName,
- SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale()),
- spacebarText);
- }
- }
- }
-
- public void testAllShortDisplayName() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
- final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
- final String spacebarText = MainKeyboardView.getShortDisplayName(subtype);
- final String languageCode = StringUtils.capitalizeFirstCodePoint(
- locale.getLanguage(), locale);
- if (SubtypeLocale.isNoLanguage(subtype)) {
- assertEquals(subtypeName, "", spacebarText);
- } else {
- assertEquals(subtypeName, languageCode, spacebarText);
- }
- }
- }
-
- // InputMethodSubtype's display name for spacebar text in its locale.
- // isAdditionalSubtype (T=true, F=false)
- // locale layout | Short Middle Full
- // ------ ------- - ---- --------- ----------------------
- // en_US qwerty F En English English (US) exception
- // en_GB qwerty F En English English (UK) exception
- // es_US spanish F Es Español Español (EE.UU.) exception
- // fr azerty F Fr Français Français
- // fr_CA qwerty F Fr Français Français (Canada)
- // de qwertz F De Deutsch Deutsch
- // zz qwerty F QWERTY QWERTY
- // fr qwertz T Fr Français Français
- // de qwerty T De Deutsch Deutsch
- // en_US azerty T En English English (US)
- // zz azerty T AZERTY AZERTY
-
- private final RunInLocale<Void> testsPredefinedSubtypes = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("en_US", "English (US)", MainKeyboardView.getFullDisplayName(EN_US));
- assertEquals("en_GB", "English (UK)", MainKeyboardView.getFullDisplayName(EN_GB));
- assertEquals("es_US", "Español (EE.UU.)", MainKeyboardView.getFullDisplayName(ES_US));
- assertEquals("fr ", "Français", MainKeyboardView.getFullDisplayName(FR));
- assertEquals("fr_CA", "Français (Canada)", MainKeyboardView.getFullDisplayName(FR_CA));
- assertEquals("de ", "Deutsch", MainKeyboardView.getFullDisplayName(DE));
- assertEquals("zz ", "QWERTY", MainKeyboardView.getFullDisplayName(ZZ));
-
- assertEquals("en_US", "English", MainKeyboardView.getMiddleDisplayName(EN_US));
- assertEquals("en_GB", "English", MainKeyboardView.getMiddleDisplayName(EN_GB));
- assertEquals("es_US", "Español", MainKeyboardView.getMiddleDisplayName(ES_US));
- assertEquals("fr ", "Français", MainKeyboardView.getMiddleDisplayName(FR));
- assertEquals("fr_CA", "Français", MainKeyboardView.getMiddleDisplayName(FR_CA));
- assertEquals("de ", "Deutsch", MainKeyboardView.getMiddleDisplayName(DE));
- assertEquals("zz ", "QWERTY", MainKeyboardView.getMiddleDisplayName(ZZ));
-
- assertEquals("en_US", "En", MainKeyboardView.getShortDisplayName(EN_US));
- assertEquals("en_GB", "En", MainKeyboardView.getShortDisplayName(EN_GB));
- assertEquals("es_US", "Es", MainKeyboardView.getShortDisplayName(ES_US));
- assertEquals("fr ", "Fr", MainKeyboardView.getShortDisplayName(FR));
- assertEquals("fr_CA", "Fr", MainKeyboardView.getShortDisplayName(FR_CA));
- assertEquals("de ", "De", MainKeyboardView.getShortDisplayName(DE));
- assertEquals("zz ", "", MainKeyboardView.getShortDisplayName(ZZ));
- return null;
- }
- };
-
- private final RunInLocale<Void> testsAdditionalSubtypes = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("fr qwertz", "Français",
- MainKeyboardView.getFullDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- MainKeyboardView.getFullDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English (US)",
- MainKeyboardView.getFullDisplayName(US_AZERTY));
- assertEquals("zz azerty", "AZERTY",
- MainKeyboardView.getFullDisplayName(ZZ_AZERTY));
-
- assertEquals("fr qwertz", "Français",
- MainKeyboardView.getMiddleDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- MainKeyboardView.getMiddleDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English",
- MainKeyboardView.getMiddleDisplayName(US_AZERTY));
- assertEquals("zz azerty", "AZERTY",
- MainKeyboardView.getMiddleDisplayName(ZZ_AZERTY));
-
- assertEquals("fr qwertz", "Fr", MainKeyboardView.getShortDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "De", MainKeyboardView.getShortDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "En", MainKeyboardView.getShortDisplayName(US_AZERTY));
- assertEquals("zz azerty", "", MainKeyboardView.getShortDisplayName(ZZ_AZERTY));
- return null;
- }
- };
-
- public void testPredefinedSubtypesInEnglish() {
- testsPredefinedSubtypes.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testAdditionalSubtypeInEnglish() {
- testsAdditionalSubtypes.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testPredefinedSubtypesInFrench() {
- testsPredefinedSubtypes.runInLocale(mRes, Locale.FRENCH);
- }
-
- public void testAdditionalSubtypeInFrench() {
- testsAdditionalSubtypes.runInLocale(mRes, Locale.FRENCH);
- }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
index eea1efc49..2eb448c82 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
@@ -22,8 +22,8 @@ import android.content.res.Resources;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
-import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.RunInLocale;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -51,9 +51,10 @@ public class KeySpecParserSplitTests extends InstrumentationTestCase {
}.runInLocale(targetContext.getResources(), TEST_LOCALE);
final String[] testResourceNames = getAllResourceIdNames(
com.android.inputmethod.latin.tests.R.string.class);
- mTextsSet.loadStringResourcesInternal(instrumentation.getContext(),
- testResourceNames,
- com.android.inputmethod.latin.tests.R.string.empty_string);
+ mTextsSet.loadStringResourcesInternal(instrumentation.getContext(), testResourceNames,
+ // This dummy raw resource is needed to be able to load string resources from a test
+ // APK successfully.
+ com.android.inputmethod.latin.tests.R.raw.dummy_resource_for_testing);
}
private static String[] getAllResourceIdNames(final Class<?> resourceIdClass) {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
index b55158d3e..afb2b0343 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
@@ -26,7 +26,7 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
+import com.android.inputmethod.latin.utils.RunInLocale;
import java.util.Arrays;
import java.util.Locale;
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
index b193e66dc..9ad81c01d 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
@@ -60,7 +60,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Chording input in shift locked.
public void testChordingShiftLocked() {
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press shift key and hold, enter into choring shift state.
@@ -119,7 +119,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -137,7 +137,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -196,7 +196,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -216,7 +216,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -397,29 +397,29 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
public void testLongPressShiftAndChording() {
// Long press shift key, enter maybe shift locked.
- longPressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+ longPressShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Press/release letter key, remain in manual shifted.
chordingPressAndReleaseKey('A', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Release shift key, back to alphabet (not shift locked).
releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Long press shift key, enter maybe alphabet.
- longPressKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED);
+ longPressShiftKey(ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED);
// Press/release letter key, remain in manual shifted.
chordingPressAndReleaseKey('A', ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED);
// Release shift key, back to shift locked (not alphabet).
releaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCKED);
// Long press shift key, enter alphabet
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
ALPHABET_UNSHIFTED);
// Press/release shift key, enter alphabet shifted.
pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Long press shift key, enter maybe alphabet.
- longPressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+ longPressShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Press/release letter key, remain in manual shifted.
chordingPressAndReleaseKey('A', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Release shift key, back to alphabet shifted (not alphabet).
@@ -430,7 +430,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// Load keyboard, should be in automatic shifted.
loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
// Long press shift key, enter maybe shift locked.
- longPressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+ longPressShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Press/release letter key, remain in manual shifted.
chordingPressAndReleaseKey('A', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Release shift key, back to alphabet (not shift locked).
@@ -449,7 +449,7 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
// releaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
//
// // Long press shift key, enter alphabet shift locked.
-// longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+// longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
// ALPHABET_SHIFT_LOCKED);
// // First shift key tap.
// pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
index d5b9d1dfd..c7ac76d93 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
@@ -91,7 +91,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Switching between alphabet shift locked and symbols.
public void testAlphabetShiftLockedAndSymbols() {
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
@@ -133,7 +133,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Automatic switch back to alphabet shift locked test by space key.
public void testSwitchBackBySpaceShiftLocked() {
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
@@ -196,13 +196,13 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard, should be in alphabet.
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release shift key, back to alphabet.
pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release letter key, remain in shift locked.
pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED);
@@ -212,16 +212,16 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Long press shift key, back to alphabet.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
ALPHABET_UNSHIFTED);
// Press/release shift key, enter alphabet shifted.
pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release shift key, back to alphabet.
pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
@@ -231,7 +231,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard, should be in automatic shifted.
loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release shift key, back to alphabet.
pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
@@ -293,12 +293,12 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
updateShiftState(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Update shift state, remained in alphabet shift locked.
updateShiftState(ALPHABET_SHIFT_LOCKED);
// Long press shift key, back to alphabet.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
ALPHABET_UNSHIFTED);
// Press/release "?123" key, enter into symbols.
@@ -326,12 +326,12 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
updateShiftState(ALPHABET_AUTOMATIC_SHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Update shift state, remained in alphabet shift locked (not automatic shifted).
updateShiftState(ALPHABET_SHIFT_LOCKED);
// Long press shift key, back to alphabet.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED,
ALPHABET_UNSHIFTED);
// Load keyboard, should be in automatic shifted.
@@ -383,7 +383,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Alphabet shift locked -> shift key + letter -> alphabet shift locked.
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press and slide from "123?" key, enter symbols.
pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -441,7 +441,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Alphabet shift locked -> shift key + letter -> cancel -> alphabet shift locked.
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press and slide from "123?" key, enter symbols.
pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -500,7 +500,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -517,7 +517,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -574,7 +574,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -592,7 +592,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -651,7 +651,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -670,7 +670,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -733,7 +733,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -753,7 +753,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Load keyboard
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release "?123" key, enter into symbols.
pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
@@ -777,7 +777,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
loadKeyboard(ALPHABET_UNSHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Change focus to new text field.
loadKeyboard(ALPHABET_UNSHIFTED);
@@ -808,7 +808,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Change focus to new text field.
loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
@@ -852,7 +852,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
// Alphabet shift locked -> rotate -> alphabet shift locked.
// Long press shift key, enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Rotate device, remain in alphabet shift locked.
rotateDevice(ALPHABET_SHIFT_LOCKED);
@@ -936,7 +936,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
// Long press shift key to enter alphabet shift locked.
- longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
+ longPressAndReleaseShiftKey(ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED,
ALPHABET_SHIFT_LOCKED);
// Press/release shift key
pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index e06ca064a..3ffd0a96a 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.keyboard.internal;
import android.test.AndroidTestCase;
+import com.android.inputmethod.latin.Constants;
+
public class KeyboardStateTestsBase extends AndroidTestCase
implements MockKeyboardSwitcher.MockConstants {
protected MockKeyboardSwitcher mSwitcher;
@@ -32,6 +34,11 @@ public class KeyboardStateTestsBase extends AndroidTestCase
loadKeyboard(ALPHABET_UNSHIFTED);
}
+ /**
+ * Set auto caps mode.
+ *
+ * @param autoCaps the auto cap mode.
+ */
public void setAutoCapsMode(final int autoCaps) {
mSwitcher.setAutoCapsMode(autoCaps);
}
@@ -42,17 +49,32 @@ public class KeyboardStateTestsBase extends AndroidTestCase
expected == actual);
}
+ /**
+ * Emulate update keyboard shift state.
+ *
+ * @param afterUpdate the keyboard state after updating the keyboard shift state.
+ */
public void updateShiftState(final int afterUpdate) {
mSwitcher.updateShiftState();
assertLayout("afterUpdate", afterUpdate, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate load default keyboard.
+ *
+ * @param afterLoad the keyboard state after loading default keyboard.
+ */
public void loadKeyboard(final int afterLoad) {
mSwitcher.loadKeyboard();
mSwitcher.updateShiftState();
assertLayout("afterLoad", afterLoad, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate rotate device.
+ *
+ * @param afterRotate the keyboard state after rotating device.
+ */
public void rotateDevice(final int afterRotate) {
mSwitcher.saveKeyboardState();
mSwitcher.loadKeyboard();
@@ -65,45 +87,97 @@ public class KeyboardStateTestsBase extends AndroidTestCase
assertLayout("afterPress", afterPress, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate key press.
+ *
+ * @param code the key code to press.
+ * @param afterPress the keyboard state after pressing the key.
+ */
public void pressKey(final int code, final int afterPress) {
mSwitcher.expireDoubleTapTimeout();
pressKeyWithoutTimerExpire(code, true, afterPress);
}
+ /**
+ * Emulate key release and register.
+ *
+ * @param code the key code to release and register
+ * @param afterRelease the keyboard state after releasing the key.
+ */
public void releaseKey(final int code, final int afterRelease) {
mSwitcher.onCodeInput(code);
mSwitcher.onReleaseKey(code, NOT_SLIDING);
assertLayout("afterRelease", afterRelease, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate key press and release.
+ *
+ * @param code the key code to press and release.
+ * @param afterPress the keyboard state after pressing the key.
+ * @param afterRelease the keyboard state after releasing the key.
+ */
public void pressAndReleaseKey(final int code, final int afterPress, final int afterRelease) {
pressKey(code, afterPress);
releaseKey(code, afterRelease);
}
+ /**
+ * Emulate chording key press.
+ *
+ * @param code the chording key code.
+ * @param afterPress the keyboard state after pressing chording key.
+ */
public void chordingPressKey(final int code, final int afterPress) {
mSwitcher.expireDoubleTapTimeout();
pressKeyWithoutTimerExpire(code, false, afterPress);
}
+ /**
+ * Emulate chording key release.
+ *
+ * @param code the cording key code.
+ * @param afterRelease the keyboard state after releasing chording key.
+ */
public void chordingReleaseKey(final int code, final int afterRelease) {
mSwitcher.onCodeInput(code);
mSwitcher.onReleaseKey(code, NOT_SLIDING);
assertLayout("afterRelease", afterRelease, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate chording key press and release.
+ *
+ * @param code the chording key code.
+ * @param afterPress the keyboard state after pressing chording key.
+ * @param afterRelease the keyboard state after releasing chording key.
+ */
public void chordingPressAndReleaseKey(final int code, final int afterPress,
final int afterRelease) {
chordingPressKey(code, afterPress);
chordingReleaseKey(code, afterRelease);
}
+ /**
+ * Emulate start of the sliding key input.
+ *
+ * @param code the key code to start sliding.
+ * @param afterPress the keyboard state after pressing the key.
+ * @param afterSlide the keyboard state after releasing the key with sliding input.
+ */
public void pressAndSlideFromKey(final int code, final int afterPress, final int afterSlide) {
pressKey(code, afterPress);
mSwitcher.onReleaseKey(code, SLIDING);
assertLayout("afterSlide", afterSlide, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate end of the sliding key input.
+ *
+ * @param code the key code to stop sliding.
+ * @param afterPress the keyboard state after pressing the key.
+ * @param afterSlide the keyboard state after releasing the key and stop sliding.
+ */
public void stopSlidingOnKey(final int code, final int afterPress, final int afterSlide) {
pressKey(code, afterPress);
mSwitcher.onCodeInput(code);
@@ -112,28 +186,67 @@ public class KeyboardStateTestsBase extends AndroidTestCase
assertLayout("afterSlide", afterSlide, mSwitcher.getLayoutId());
}
+ /**
+ * Emulate cancel the sliding key input.
+ *
+ * @param afterCancelSliding the keyboard state after canceling sliding input.
+ */
public void stopSlidingAndCancel(final int afterCancelSliding) {
mSwitcher.onFinishSlidingInput();
assertLayout("afterCancelSliding", afterCancelSliding, mSwitcher.getLayoutId());
}
- public void longPressKey(final int code, final int afterPress, final int afterLongPress) {
- pressKey(code, afterPress);
- mSwitcher.onLongPressTimeout(code);
+ /**
+ * Emulate long press shift key.
+ *
+ * @param afterPress the keyboard state after pressing shift key.
+ * @param afterLongPress the keyboard state after long press fired.
+ */
+ public void longPressShiftKey(final int afterPress, final int afterLongPress) {
+ // Long press shift key will register {@link Constants#CODE_CAPS_LOCK}. See
+ // {@link R.xml#key_styles_common} and its baseForShiftKeyStyle. We thus emulate the
+ // behavior that is implemented in {@link MainKeyboardView#onLongPress(PointerTracker)}.
+ pressKey(Constants.CODE_SHIFT, afterPress);
+ mSwitcher.onPressKey(Constants.CODE_CAPSLOCK, true /* isSinglePointer */);
+ mSwitcher.onCodeInput(Constants.CODE_CAPSLOCK);
assertLayout("afterLongPress", afterLongPress, mSwitcher.getLayoutId());
}
- public void longPressAndReleaseKey(final int code, final int afterPress,
- final int afterLongPress, final int afterRelease) {
- longPressKey(code, afterPress, afterLongPress);
- releaseKey(code, afterRelease);
- }
-
- public void secondPressKey(int code, int afterPress) {
+ /**
+ * Emulate long press shift key and release.
+ *
+ * @param afterPress the keyboard state after pressing shift key.
+ * @param afterLongPress the keyboard state after long press fired.
+ * @param afterRelease the keyboard state after shift key is released.
+ */
+ public void longPressAndReleaseShiftKey(final int afterPress, final int afterLongPress,
+ final int afterRelease) {
+ // Long press shift key will register {@link Constants#CODE_CAPS_LOCK}. See
+ // {@link R.xml#key_styles_common} and its baseForShiftKeyStyle. We thus emulate the
+ // behavior that is implemented in {@link MainKeyboardView#onLongPress(PointerTracker)}.
+ longPressShiftKey(afterPress, afterLongPress);
+ releaseKey(Constants.CODE_CAPSLOCK, afterRelease);
+ }
+
+ /**
+ * Emulate the second press of the double tap.
+ *
+ * @param code the key code to double tap.
+ * @param afterPress the keyboard state after pressing the second tap.
+ */
+ public void secondPressKey(final int code, final int afterPress) {
pressKeyWithoutTimerExpire(code, true, afterPress);
}
- public void secondPressAndReleaseKey(int code, int afterPress, int afterRelease) {
+ /**
+ * Emulate the second tap of the double tap.
+ *
+ * @param code the key code to double tap.
+ * @param afterPress the keyboard state after pressing the second tap.
+ * @param afterRelease the keyboard state after releasing the second tap.
+ */
+ public void secondPressAndReleaseKey(final int code, final int afterPress,
+ final int afterRelease) {
secondPressKey(code, afterPress);
releaseKey(code, afterRelease);
}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index 90dbaabc9..6e3e37add 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -19,7 +19,7 @@ package com.android.inputmethod.keyboard.internal;
import android.text.TextUtils;
import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.RecapitalizeStatus;
+import com.android.inputmethod.latin.utils.RecapitalizeStatus;
public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
public interface MockConstants {
@@ -120,6 +120,11 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
}
@Override
+ public void setEmojiKeyboard() {
+ // Just ignore.
+ }
+
+ @Override
public void requestUpdatingShiftState() {
mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
}
@@ -139,24 +144,6 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
return mIsInDoubleTapShiftKeyTimeout;
}
- @Override
- public void startLongPressTimer(final int code) {
- mLongPressTimeoutCode = code;
- }
-
- @Override
- public void cancelLongPressTimer() {
- mLongPressTimeoutCode = 0;
- }
-
- public void onLongPressTimeout(final int code) {
- // TODO: Handle simultaneous long presses.
- if (mLongPressTimeoutCode == code) {
- mLongPressTimeoutCode = 0;
- mState.onLongPressTimeout(code);
- }
- }
-
public void updateShiftState() {
mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
new file mode 100644
index 000000000..7ed3ee180
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2013 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 android.test.suitebuilder.annotation.LargeTest;
+import android.util.Pair;
+
+import com.android.inputmethod.latin.makedict.CodePointUtils;
+import com.android.inputmethod.latin.makedict.FormatSpec;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+@LargeTest
+public class BinaryDictionaryTests extends AndroidTestCase {
+ private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
+ private static final String TEST_LOCALE = "test";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private File createEmptyDictionaryAndGetFile(final String filename) throws IOException {
+ final File file = File.createTempFile(filename, TEST_DICT_FILE_EXTENSION,
+ getContext().getCacheDir());
+ Map<String, String> attributeMap = new HashMap<String, String>();
+ attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE,
+ FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
+ if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(),
+ 3 /* dictVersion */, attributeMap)) {
+ return file;
+ } else {
+ throw new IOException("Empty dictionary cannot be created.");
+ }
+ }
+
+ public void testIsValidDictionary() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ assertTrue("binaryDictionary must be valid for existing valid dictionary file.",
+ binaryDictionary.isValidDictionary());
+ binaryDictionary.close();
+ assertFalse("binaryDictionary must be invalid after closing.",
+ binaryDictionary.isValidDictionary());
+ dictFile.delete();
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */,
+ dictFile.length(), true /* useFullEditDistance */, Locale.getDefault(),
+ TEST_LOCALE, true /* isUpdatable */);
+ assertFalse("binaryDictionary must be invalid for not existing dictionary file.",
+ binaryDictionary.isValidDictionary());
+ binaryDictionary.close();
+ }
+
+ public void testAddUnigramWord() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final int probability = 100;
+ binaryDictionary.addUnigramWord("aaa", probability);
+ // Reallocate and create.
+ binaryDictionary.addUnigramWord("aab", probability);
+ // Insert into children.
+ binaryDictionary.addUnigramWord("aac", probability);
+ // Make terminal.
+ binaryDictionary.addUnigramWord("aa", probability);
+ // Create children.
+ binaryDictionary.addUnigramWord("aaaa", probability);
+ // Reallocate and make termianl.
+ binaryDictionary.addUnigramWord("a", probability);
+
+ final int updatedProbability = 200;
+ // Update.
+ binaryDictionary.addUnigramWord("aaa", updatedProbability);
+
+ assertEquals(probability, binaryDictionary.getFrequency("aab"));
+ assertEquals(probability, binaryDictionary.getFrequency("aac"));
+ assertEquals(probability, binaryDictionary.getFrequency("aa"));
+ assertEquals(probability, binaryDictionary.getFrequency("aaaa"));
+ assertEquals(probability, binaryDictionary.getFrequency("a"));
+ assertEquals(updatedProbability, binaryDictionary.getFrequency("aaa"));
+
+ dictFile.delete();
+ }
+
+ public void testRandomlyAddUnigramWord() {
+ final int wordCount = 1000;
+ final int codePointSetSize = 50;
+ final int seed = 123456789;
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final HashMap<String, Integer> probabilityMap = new HashMap<String, Integer>();
+ // Test a word that isn't contained within the dictionary.
+ final Random random = new Random(seed);
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ for (int i = 0; i < wordCount; ++i) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ probabilityMap.put(word, random.nextInt(0xFF));
+ }
+ for (String word : probabilityMap.keySet()) {
+ binaryDictionary.addUnigramWord(word, probabilityMap.get(word));
+ }
+ for (String word : probabilityMap.keySet()) {
+ assertEquals(word, (int)probabilityMap.get(word), binaryDictionary.getFrequency(word));
+ }
+ dictFile.delete();
+ }
+
+ public void testAddBigramWords() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final int unigramProbability = 100;
+ final int bigramProbability = 10;
+ final int updatedBigramProbability = 15;
+ binaryDictionary.addUnigramWord("aaa", unigramProbability);
+ binaryDictionary.addUnigramWord("abb", unigramProbability);
+ binaryDictionary.addUnigramWord("bcc", unigramProbability);
+ binaryDictionary.addBigramWords("aaa", "abb", bigramProbability);
+ binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "aaa", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "bcc", bigramProbability);
+
+ final int probability = binaryDictionary.calculateProbability(unigramProbability,
+ bigramProbability);
+ assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb"));
+ assertEquals(true, binaryDictionary.isValidBigram("aaa", "bcc"));
+ assertEquals(true, binaryDictionary.isValidBigram("abb", "aaa"));
+ assertEquals(true, binaryDictionary.isValidBigram("abb", "bcc"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "abb"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "bcc"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("abb", "aaa"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("abb", "bcc"));
+
+ binaryDictionary.addBigramWords("aaa", "abb", updatedBigramProbability);
+ final int updatedProbability = binaryDictionary.calculateProbability(unigramProbability,
+ updatedBigramProbability);
+ assertEquals(updatedProbability, binaryDictionary.getBigramProbability("aaa", "abb"));
+
+ assertEquals(false, binaryDictionary.isValidBigram("bcc", "aaa"));
+ assertEquals(false, binaryDictionary.isValidBigram("bcc", "bbc"));
+ assertEquals(false, binaryDictionary.isValidBigram("aaa", "aaa"));
+ assertEquals(Dictionary.NOT_A_PROBABILITY,
+ binaryDictionary.getBigramProbability("bcc", "aaa"));
+ assertEquals(Dictionary.NOT_A_PROBABILITY,
+ binaryDictionary.getBigramProbability("bcc", "bbc"));
+ assertEquals(Dictionary.NOT_A_PROBABILITY,
+ binaryDictionary.getBigramProbability("aaa", "aaa"));
+
+ // Testing bigram link.
+ binaryDictionary.addUnigramWord("abcde", unigramProbability);
+ binaryDictionary.addUnigramWord("fghij", unigramProbability);
+ binaryDictionary.addBigramWords("abcde", "fghij", bigramProbability);
+ binaryDictionary.addUnigramWord("fgh", unigramProbability);
+ binaryDictionary.addUnigramWord("abc", unigramProbability);
+ binaryDictionary.addUnigramWord("f", unigramProbability);
+ assertEquals(probability, binaryDictionary.getBigramProbability("abcde", "fghij"));
+ assertEquals(Dictionary.NOT_A_PROBABILITY,
+ binaryDictionary.getBigramProbability("abcde", "fgh"));
+ binaryDictionary.addBigramWords("abcde", "fghij", updatedBigramProbability);
+ assertEquals(updatedProbability, binaryDictionary.getBigramProbability("abcde", "fghij"));
+
+ dictFile.delete();
+ }
+
+ public void testRandomlyAddBigramWords() {
+ final int wordCount = 100;
+ final int bigramCount = 1000;
+ final int codePointSetSize = 50;
+ final int seed = 11111;
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final ArrayList<String> words = new ArrayList<String>();
+ // Test a word that isn't contained within the dictionary.
+ final Random random = new Random(seed);
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ final int[] unigramProbabilities = new int[wordCount];
+ for (int i = 0; i < wordCount; ++i) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ words.add(word);
+ final int unigramProbability = random.nextInt(0xFF);
+ unigramProbabilities[i] = unigramProbability;
+ binaryDictionary.addUnigramWord(word, unigramProbability);
+ }
+
+ final int[][] probabilities = new int[wordCount][wordCount];
+
+ for (int i = 0; i < wordCount; ++i) {
+ for (int j = 0; j < wordCount; ++j) {
+ probabilities[i][j] = Dictionary.NOT_A_PROBABILITY;
+ }
+ }
+
+ for (int i = 0; i < bigramCount; i++) {
+ final int word0Index = random.nextInt(wordCount);
+ final int word1Index = random.nextInt(wordCount);
+ final String word0 = words.get(word0Index);
+ final String word1 = words.get(word1Index);
+ final int bigramProbability = random.nextInt(0xF);
+ probabilities[word0Index][word1Index] = binaryDictionary.calculateProbability(
+ unigramProbabilities[word1Index], bigramProbability);
+ binaryDictionary.addBigramWords(word0, word1, bigramProbability);
+ }
+
+ for (int i = 0; i < words.size(); i++) {
+ for (int j = 0; j < words.size(); j++) {
+ assertEquals(probabilities[i][j],
+ binaryDictionary.getBigramProbability(words.get(i), words.get(j)));
+ }
+ }
+
+ dictFile.delete();
+ }
+
+ public void testRemoveBigramWords() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final int unigramProbability = 100;
+ final int bigramProbability = 10;
+ binaryDictionary.addUnigramWord("aaa", unigramProbability);
+ binaryDictionary.addUnigramWord("abb", unigramProbability);
+ binaryDictionary.addUnigramWord("bcc", unigramProbability);
+ binaryDictionary.addBigramWords("aaa", "abb", bigramProbability);
+ binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "aaa", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "bcc", bigramProbability);
+
+ assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb"));
+ assertEquals(true, binaryDictionary.isValidBigram("aaa", "bcc"));
+ assertEquals(true, binaryDictionary.isValidBigram("abb", "aaa"));
+ assertEquals(true, binaryDictionary.isValidBigram("abb", "bcc"));
+
+ binaryDictionary.removeBigramWords("aaa", "abb");
+ assertEquals(false, binaryDictionary.isValidBigram("aaa", "abb"));
+ binaryDictionary.addBigramWords("aaa", "abb", bigramProbability);
+ assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb"));
+
+
+ binaryDictionary.removeBigramWords("aaa", "bcc");
+ assertEquals(false, binaryDictionary.isValidBigram("aaa", "bcc"));
+ binaryDictionary.removeBigramWords("abb", "aaa");
+ assertEquals(false, binaryDictionary.isValidBigram("abb", "aaa"));
+ binaryDictionary.removeBigramWords("abb", "bcc");
+ assertEquals(false, binaryDictionary.isValidBigram("abb", "bcc"));
+
+ binaryDictionary.removeBigramWords("aaa", "abb");
+ // Test remove non-existing bigram operation.
+ binaryDictionary.removeBigramWords("aaa", "abb");
+ binaryDictionary.removeBigramWords("bcc", "aaa");
+
+ dictFile.delete();
+ }
+
+ public void testFlushDictionary() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final int probability = 100;
+ binaryDictionary.addUnigramWord("aaa", probability);
+ binaryDictionary.addUnigramWord("abcd", probability);
+ // Close without flushing.
+ binaryDictionary.close();
+
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency("aaa"));
+ assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency("abcd"));
+
+ binaryDictionary.addUnigramWord("aaa", probability);
+ binaryDictionary.addUnigramWord("abcd", probability);
+ binaryDictionary.flush();
+ binaryDictionary.close();
+
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ assertEquals(probability, binaryDictionary.getFrequency("aaa"));
+ assertEquals(probability, binaryDictionary.getFrequency("abcd"));
+ binaryDictionary.addUnigramWord("bcde", probability);
+ binaryDictionary.flush();
+ binaryDictionary.close();
+
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ assertEquals(probability, binaryDictionary.getFrequency("bcde"));
+ binaryDictionary.close();
+
+ dictFile.delete();
+ }
+
+ public void testFlushWithGCDictionary() {
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ final int unigramProbability = 100;
+ final int bigramProbability = 10;
+ binaryDictionary.addUnigramWord("aaa", unigramProbability);
+ binaryDictionary.addUnigramWord("abb", unigramProbability);
+ binaryDictionary.addUnigramWord("bcc", unigramProbability);
+ binaryDictionary.addBigramWords("aaa", "abb", bigramProbability);
+ binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "aaa", bigramProbability);
+ binaryDictionary.addBigramWords("abb", "bcc", bigramProbability);
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final int probability = binaryDictionary.calculateProbability(unigramProbability,
+ bigramProbability);
+ assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
+ assertEquals(unigramProbability, binaryDictionary.getFrequency("abb"));
+ assertEquals(unigramProbability, binaryDictionary.getFrequency("bcc"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "abb"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "bcc"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("abb", "aaa"));
+ assertEquals(probability, binaryDictionary.getBigramProbability("abb", "bcc"));
+ assertEquals(false, binaryDictionary.isValidBigram("bcc", "aaa"));
+ assertEquals(false, binaryDictionary.isValidBigram("bcc", "bbc"));
+ assertEquals(false, binaryDictionary.isValidBigram("aaa", "aaa"));
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+
+ dictFile.delete();
+ }
+
+ // TODO: Evaluate performance of GC
+ public void testAddBigramWordsAndFlashWithGC() {
+ final int wordCount = 100;
+ final int bigramCount = 1000;
+ final int codePointSetSize = 30;
+ // TODO: Use various seeds such as a current timestamp to make this test more random.
+ final int seed = 314159265;
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final ArrayList<String> words = new ArrayList<String>();
+ // Test a word that isn't contained within the dictionary.
+ final Random random = new Random(seed);
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ final int[] unigramProbabilities = new int[wordCount];
+ for (int i = 0; i < wordCount; ++i) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ words.add(word);
+ final int unigramProbability = random.nextInt(0xFF);
+ unigramProbabilities[i] = unigramProbability;
+ binaryDictionary.addUnigramWord(word, unigramProbability);
+ }
+
+ final int[][] probabilities = new int[wordCount][wordCount];
+
+ for (int i = 0; i < wordCount; ++i) {
+ for (int j = 0; j < wordCount; ++j) {
+ probabilities[i][j] = Dictionary.NOT_A_PROBABILITY;
+ }
+ }
+
+ for (int i = 0; i < bigramCount; i++) {
+ final int word0Index = random.nextInt(wordCount);
+ final int word1Index = random.nextInt(wordCount);
+ final String word0 = words.get(word0Index);
+ final String word1 = words.get(word1Index);
+ final int bigramProbability = random.nextInt(0xF);
+ probabilities[word0Index][word1Index] = binaryDictionary.calculateProbability(
+ unigramProbabilities[word1Index], bigramProbability);
+ binaryDictionary.addBigramWords(word0, word1, bigramProbability);
+ }
+
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ for (int i = 0; i < words.size(); i++) {
+ for (int j = 0; j < words.size(); j++) {
+ assertEquals(probabilities[i][j],
+ binaryDictionary.getBigramProbability(words.get(i), words.get(j)));
+ }
+ }
+ dictFile.delete();
+ }
+
+ public void testRandomOperetionsAndFlashWithGC() {
+ final int flashWithGCIterationCount = 50;
+ final int operationCountInEachIteration = 200;
+ final int initialUnigramCount = 100;
+ final float addUnigramProb = 0.5f;
+ final float addBigramProb = 0.8f;
+ final float removeBigramProb = 0.2f;
+ final int codePointSetSize = 30;
+ final int seed = 141421356;
+
+ final Random random = new Random(seed);
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+
+ BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final ArrayList<String> words = new ArrayList<String>();
+ final ArrayList<Pair<String, String>> bigramWords = new ArrayList<Pair<String,String>>();
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ final HashMap<String, Integer> unigramProbabilities = new HashMap<String, Integer>();
+ final HashMap<Pair<String, String>, Integer> bigramProbabilities =
+ new HashMap<Pair<String, String>, Integer>();
+ for (int i = 0; i < initialUnigramCount; ++i) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ words.add(word);
+ final int unigramProbability = random.nextInt(0xFF);
+ unigramProbabilities.put(word, unigramProbability);
+ binaryDictionary.addUnigramWord(word, unigramProbability);
+ }
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+
+ for (int gcCount = 0; gcCount < flashWithGCIterationCount; gcCount++) {
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ for (int opCount = 0; opCount < operationCountInEachIteration; opCount++) {
+ // Add unigram.
+ if (random.nextFloat() < addUnigramProb) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ words.add(word);
+ final int unigramProbability = random.nextInt(0xFF);
+ unigramProbabilities.put(word, unigramProbability);
+ binaryDictionary.addUnigramWord(word, unigramProbability);
+ }
+ // Add bigram.
+ if (random.nextFloat() < addBigramProb && words.size() > 2) {
+ final int word0Index = random.nextInt(words.size());
+ int word1Index = random.nextInt(words.size() - 1);
+ if (word0Index <= word1Index) {
+ word1Index++;
+ }
+ final String word0 = words.get(word0Index);
+ final String word1 = words.get(word1Index);
+ final int bigramProbability = random.nextInt(0xF);
+ final Pair<String, String> bigram = new Pair<String, String>(word0, word1);
+ bigramWords.add(bigram);
+ bigramProbabilities.put(bigram, bigramProbability);
+ binaryDictionary.addBigramWords(word0, word1, bigramProbability);
+ }
+ // Remove bigram.
+ if (random.nextFloat() < removeBigramProb && !bigramWords.isEmpty()) {
+ final int bigramIndex = random.nextInt(bigramWords.size());
+ final Pair<String, String> bigram = bigramWords.get(bigramIndex);
+ bigramWords.remove(bigramIndex);
+ bigramProbabilities.remove(bigram);
+ binaryDictionary.removeBigramWords(bigram.first, bigram.second);
+ }
+ }
+
+ // Test whether the all unigram operations are collectlly handled.
+ for (int i = 0; i < words.size(); i++) {
+ final String word = words.get(i);
+ final int unigramProbability = unigramProbabilities.get(word);
+ assertEquals(word, unigramProbability, binaryDictionary.getFrequency(word));
+ }
+ // Test whether the all bigram operations are collectlly handled.
+ for (int i = 0; i < bigramWords.size(); i++) {
+ final Pair<String, String> bigram = bigramWords.get(i);
+ final int unigramProbability = unigramProbabilities.get(bigram.second);
+ final int probability;
+ if (bigramProbabilities.containsKey(bigram)) {
+ final int bigramProbability = bigramProbabilities.get(bigram);
+ probability = binaryDictionary.calculateProbability(unigramProbability,
+ bigramProbability);
+ } else {
+ probability = Dictionary.NOT_A_PROBABILITY;
+ }
+ assertEquals(probability,
+ binaryDictionary.getBigramProbability(bigram.first, bigram.second));
+ }
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+ }
+
+ dictFile.delete();
+ }
+
+ public void testAddManyUnigramsAndFlushWithGC() {
+ final int flashWithGCIterationCount = 3;
+ final int codePointSetSize = 50;
+ final int seed = 22360679;
+
+ final Random random = new Random(seed);
+
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary");
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+
+ final ArrayList<String> words = new ArrayList<String>();
+ final HashMap<String, Integer> unigramProbabilities = new HashMap<String, Integer>();
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+
+ BinaryDictionary binaryDictionary;
+ for (int i = 0; i < flashWithGCIterationCount; i++) {
+ binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ while(!binaryDictionary.needsToRunGC()) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ words.add(word);
+ final int unigramProbability = random.nextInt(0xFF);
+ unigramProbabilities.put(word, unigramProbability);
+ binaryDictionary.addUnigramWord(word, unigramProbability);
+ }
+
+ for (int j = 0; j < words.size(); j++) {
+ final String word = words.get(j);
+ final int unigramProbability = unigramProbabilities.get(word);
+ assertEquals(word, unigramProbability, binaryDictionary.getFrequency(word));
+ }
+
+ binaryDictionary.flushWithGC();
+ binaryDictionary.close();
+ }
+
+ dictFile.delete();
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java b/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java
new file mode 100644
index 000000000..ecf3af736
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 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 android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Unit test for ExpandableDictionary
+ */
+@SmallTest
+public class ExpandableDictionaryTests extends AndroidTestCase {
+
+ private final static int UNIGRAM_FREQ = 50;
+
+ public void testAddWordAndGetWordFrequency() {
+ final ExpandableDictionary dict = new ExpandableDictionary(Dictionary.TYPE_USER);
+
+ // Add words
+ dict.addWord("abcde", "abcde", UNIGRAM_FREQ);
+ dict.addWord("abcef", null, UNIGRAM_FREQ + 1);
+
+ // Check words
+ assertFalse(dict.isValidWord("abcde"));
+ assertEquals(UNIGRAM_FREQ, dict.getWordFrequency("abcde"));
+ assertTrue(dict.isValidWord("abcef"));
+ assertEquals(UNIGRAM_FREQ+1, dict.getWordFrequency("abcef"));
+
+ dict.addWord("abc", null, UNIGRAM_FREQ + 2);
+ assertTrue(dict.isValidWord("abc"));
+ assertEquals(UNIGRAM_FREQ + 2, dict.getWordFrequency("abc"));
+
+ // Add existing word with lower frequency
+ dict.addWord("abc", null, UNIGRAM_FREQ);
+ assertEquals(UNIGRAM_FREQ + 2, dict.getWordFrequency("abc"));
+
+ // Add existing word with higher frequency
+ dict.addWord("abc", null, UNIGRAM_FREQ + 3);
+ assertEquals(UNIGRAM_FREQ + 3, dict.getWordFrequency("abc"));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
index 65dfd2dde..cadd0f8f3 100644
--- a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
@@ -20,7 +20,7 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import java.util.HashMap;
@@ -30,21 +30,21 @@ import java.util.HashMap;
@SmallTest
public class FusionDictionaryTests extends AndroidTestCase {
public void testFindWordInTree() {
- FusionDictionary dict = new FusionDictionary(new Node(),
+ FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
dict.add("abc", 10, null, false /* isNotAWord */);
- assertNull(FusionDictionary.findWordInTree(dict.mRoot, "aaa"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRoot, "abc"));
+ assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
+ assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
dict.add("aa", 10, null, false /* isNotAWord */);
- assertNull(FusionDictionary.findWordInTree(dict.mRoot, "aaa"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRoot, "aa"));
+ assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
+ assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aa"));
dict.add("babcd", 10, null, false /* isNotAWord */);
dict.add("bacde", 10, null, false /* isNotAWord */);
- assertNull(FusionDictionary.findWordInTree(dict.mRoot, "ba"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRoot, "babcd"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRoot, "bacde"));
+ assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "ba"));
+ assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "babcd"));
+ assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "bacde"));
}
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 91401970a..cc2569f5e 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.BaseInputConnection;
@LargeTest
public class InputLogicTests extends InputTestsBase {
@@ -133,6 +134,13 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("simple auto-correct", EXPECTED_RESULT, mEditText.getText().toString());
}
+ public void testAutoCorrectWithQuote() {
+ final String STRING_TO_TYPE = "didn' ";
+ final String EXPECTED_RESULT = "didn't ";
+ type(STRING_TO_TYPE);
+ assertEquals("auto-correct with quote", EXPECTED_RESULT, mEditText.getText().toString());
+ }
+
public void testAutoCorrectWithPeriod() {
final String STRING_TO_TYPE = "tgis.";
final String EXPECTED_RESULT = "this.";
@@ -179,7 +187,7 @@ public class InputLogicTests extends InputTestsBase {
public void testCancelDoubleSpace() {
final String STRING_TO_TYPE = "this ";
- final String EXPECTED_RESULT = "this ";
+ final String EXPECTED_RESULT = "this ";
type(STRING_TO_TYPE);
type(Constants.CODE_DELETE);
assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString());
@@ -290,5 +298,47 @@ public class InputLogicTests extends InputTestsBase {
}
assertEquals("delete whole composing word", "", mEditText.getText().toString());
}
+
+ public void testResumeSuggestionOnBackspace() {
+ final String WORD_TO_TYPE = "and this ";
+ type(WORD_TO_TYPE);
+ assertEquals("resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ type(Constants.CODE_DELETE);
+ assertEquals("resume suggestion on backspace", 4,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("resume suggestion on backspace", 8,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ private void helperTestComposing(final String wordToType, final boolean shouldBeComposing) {
+ mEditText.setText("");
+ type(wordToType);
+ assertEquals("start composing inside text", shouldBeComposing ? 0 : -1,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("start composing inside text", shouldBeComposing ? wordToType.length() : -1,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ public void testStartComposing() {
+ // Should start composing on a letter
+ helperTestComposing("a", true);
+ type(" "); // To reset the composing state
+ // Should not start composing on quote
+ helperTestComposing("'", false);
+ type(" ");
+ helperTestComposing("'-", false);
+ type(" ");
+ // Should not start composing on dash
+ helperTestComposing("-", false);
+ type(" ");
+ helperTestComposing("-'", false);
+ type(" ");
+ helperTestComposing("a-", true);
+ type(" ");
+ helperTestComposing("a'", true);
+ }
// TODO: Add some tests for non-BMP characters
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
new file mode 100644
index 000000000..0f0ebafb9
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.BaseInputConnection;
+
+import com.android.inputmethod.latin.suggestions.SuggestionStripView;
+
+@LargeTest
+public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
+ public void testAutoCorrectForLanguageWithoutSpaces() {
+ final String STRING_TO_TYPE = "tgis is";
+ final String EXPECTED_RESULT = "thisis";
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(STRING_TO_TYPE);
+ assertEquals("simple auto-correct for language without spaces", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testRevertAutoCorrectForLanguageWithoutSpaces() {
+ final String STRING_TO_TYPE = "tgis ";
+ final String EXPECTED_INTERMEDIATE_RESULT = "this";
+ final String EXPECTED_FINAL_RESULT = "tgis";
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(STRING_TO_TYPE);
+ assertEquals("simple auto-correct for language without spaces",
+ EXPECTED_INTERMEDIATE_RESULT, mEditText.getText().toString());
+ type(Constants.CODE_DELETE);
+ assertEquals("simple auto-correct for language without spaces",
+ EXPECTED_FINAL_RESULT, mEditText.getText().toString());
+ // Check we are back to composing the word
+ assertEquals("don't resume suggestion on backspace", 0,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("don't resume suggestion on backspace", 4,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ public void testDontResumeSuggestionOnBackspace() {
+ final String WORD_TO_TYPE = "and this ";
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(WORD_TO_TYPE);
+ assertEquals("don't resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("don't resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ type(" ");
+ type(Constants.CODE_DELETE);
+ assertEquals("don't resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("don't resume suggestion on backspace", -1,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ public void testStartComposingInsideText() {
+ final String WORD_TO_TYPE = "abcdefgh ";
+ final int typedLength = WORD_TO_TYPE.length() - 1; // -1 because space gets eaten
+ final int CURSOR_POS = 4;
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(WORD_TO_TYPE);
+ mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+ mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
+ mLatinIME.onUpdateSelection(typedLength, typedLength,
+ CURSOR_POS, CURSOR_POS, -1, -1);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ runMessages();
+ assertEquals("start composing inside text", -1,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("start composing inside text", -1,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ type("xxxx");
+ assertEquals("start composing inside text", 4,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("start composing inside text", 8,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ public void testPredictions() {
+ final String WORD_TO_TYPE = "Barack ";
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(WORD_TO_TYPE);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ runMessages();
+ // Make sure there is no space
+ assertEquals("predictions in lang without spaces", "Barack",
+ mEditText.getText().toString());
+ // Test the first prediction is displayed
+ assertEquals("predictions in lang without spaces", "Obama",
+ mLatinIME.getFirstSuggestedWord());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
index 301582979..5095f9606 100644
--- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
@@ -19,6 +19,8 @@ package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.inputmethod.latin.utils.ResizableIntArray;
+
import java.util.Arrays;
@SmallTest
@@ -242,4 +244,20 @@ public class InputPointersTests extends AndroidTestCase {
expecteds[i + expectedPos], actuals[i + actualPos]);
}
}
+
+ public void testShift() {
+ final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+ final int limit = 100;
+ final int shiftAmount = 20;
+ for (int i = 0; i < limit; i++) {
+ src.addPointer(i, i * 2, i * 3, i * 4);
+ }
+ src.shift(shiftAmount);
+ for (int i = 0; i < limit - shiftAmount; ++i) {
+ assertEquals("xCoordinates at " + i, i + shiftAmount, src.getXCoordinates()[i]);
+ assertEquals("yCoordinates at " + i, (i + shiftAmount) * 2, src.getYCoordinates()[i]);
+ assertEquals("pointerIds at " + i, (i + shiftAmount) * 3, src.getPointerIds()[i]);
+ assertEquals("times at " + i, (i + shiftAmount) * 4, src.getTimes()[i]);
+ }
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index aec4aaca1..234bb1b31 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -36,6 +36,7 @@ import android.widget.FrameLayout;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.utils.LocaleUtils;
import java.util.Locale;
@@ -43,8 +44,10 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
private static final String PREF_DEBUG_MODE = "debug_mode";
- // The message that sets the underline is posted with a 100 ms delay
+ // The message that sets the underline is posted with a 200 ms delay
protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200;
+ // The message that sets predictions is posted with a 200 ms delay
+ protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
protected LatinIME mLatinIME;
protected Keyboard mKeyboard;
@@ -203,17 +206,16 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// view and only delegates to the parts of the code that care. So we don't include them here
// to keep these tests as pinpoint as possible and avoid bringing it too many dependencies,
// but keep them in mind if something breaks. Commenting them out as is should work.
- //mLatinIME.onPressKey(codePoint);
- for (final Key key : mKeyboard.mKeys) {
- if (key.mCode == codePoint) {
- final int x = key.mX + key.mWidth / 2;
- final int y = key.mY + key.mHeight / 2;
- mLatinIME.onCodeInput(codePoint, x, y);
- return;
- }
+ //mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
+ final Key key = mKeyboard.getKey(codePoint);
+ if (key != null) {
+ final int x = key.getX() + key.getWidth() / 2;
+ final int y = key.getY() + key.getHeight() / 2;
+ mLatinIME.onCodeInput(codePoint, x, y);
+ return;
}
mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
- //mLatinIME.onReleaseKey(codePoint, false);
+ //mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
}
protected void type(final String stringToType) {
@@ -224,7 +226,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
protected void waitForDictionaryToBeLoaded() {
int remainingAttempts = 300;
- while (remainingAttempts > 0 && mLatinIME.mSuggest.isCurrentlyWaitingForMainDictionary()) {
+ while (remainingAttempts > 0 && mLatinIME.isCurrentlyWaitingForMainDictionary()) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
@@ -233,22 +235,32 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
--remainingAttempts;
}
}
- if (!mLatinIME.mSuggest.hasMainDictionary()) {
- throw new RuntimeException("Can't initialize the main dictionary");
- }
}
protected void changeLanguage(final String locale) {
mEditText.mCurrentLocale = LocaleUtils.constructLocaleFromString(locale);
SubtypeSwitcher.getInstance().forceLocale(mEditText.mCurrentLocale);
mLatinIME.loadKeyboard();
+ runMessages();
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
waitForDictionaryToBeLoaded();
}
+ protected void changeKeyboardLocaleAndDictLocale(final String keyboardLocale,
+ final String dictLocale) {
+ changeLanguage(keyboardLocale);
+ if (!keyboardLocale.equals(dictLocale)) {
+ mLatinIME.replaceMainDictionaryForTest(
+ LocaleUtils.constructLocaleFromString(dictLocale));
+ }
+ waitForDictionaryToBeLoaded();
+ }
+
protected void pickSuggestionManually(final int index, final String suggestion) {
mLatinIME.pickSuggestionManually(index, new SuggestedWordInfo(suggestion, 1,
- SuggestedWordInfo.KIND_CORRECTION, "main"));
+ SuggestedWordInfo.KIND_CORRECTION, null /* sourceDict */,
+ SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+ SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
// Helper to avoid writing the try{}catch block each time
diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
index aacd60f4d..c0dd9933c 100644
--- a/tests/src/com/android/inputmethod/latin/RichInputConnectionTests.java
+++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
@@ -16,19 +16,26 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.utils.TextRange;
+
import android.inputmethodservice.InputMethodService;
+import android.os.Parcel;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableString;
+import android.text.Spanned;
import android.text.TextUtils;
+import android.text.style.SuggestionSpan;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
-import com.android.inputmethod.latin.RichInputConnection.Range;
+import java.util.Locale;
@SmallTest
-public class RichInputConnectionTests extends AndroidTestCase {
+public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
// The following is meant to be a reasonable default for
// the "word_separators" resource.
@@ -40,10 +47,30 @@ public class RichInputConnectionTests extends AndroidTestCase {
}
private class MockConnection extends InputConnectionWrapper {
- final String mTextBefore;
- final String mTextAfter;
+ final CharSequence mTextBefore;
+ final CharSequence mTextAfter;
final ExtractedText mExtractedText;
+ public MockConnection(final CharSequence text, final int cursorPosition) {
+ super(null, false);
+ // Interaction of spans with Parcels is completely non-trivial, but in the actual case
+ // the CharSequences do go through Parcels because they go through IPC. There
+ // are some significant differences between the behavior of Spanned objects that
+ // have and that have not gone through parceling, so it's much easier to simulate
+ // the environment with Parcels than try to emulate things by hand.
+ final Parcel p = Parcel.obtain();
+ TextUtils.writeToParcel(text.subSequence(0, cursorPosition), p, 0 /* flags */);
+ TextUtils.writeToParcel(text.subSequence(cursorPosition, text.length()), p,
+ 0 /* flags */);
+ final byte[] marshalled = p.marshall();
+ p.unmarshall(marshalled, 0, marshalled.length);
+ p.setDataPosition(0);
+ mTextBefore = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ mTextAfter = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ mExtractedText = null;
+ p.recycle();
+ }
+
public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) {
super(null, false);
mTextBefore = textBefore;
@@ -142,7 +169,7 @@ public class RichInputConnectionTests extends AndroidTestCase {
mockInputMethodService.setInputConnection(new MockConnection("word wo", "rd", et));
et.startOffset = 0;
et.selectionStart = 7;
- Range r;
+ TextRange r;
ic.beginBatchEdit();
// basic case
@@ -191,4 +218,95 @@ public class RichInputConnectionTests extends AndroidTestCase {
ic.endBatchEdit();
assertTrue(TextUtils.equals("word", r.mWord));
}
+
+ /**
+ * Test logic in getting the word range at the cursor.
+ */
+ public void testGetSuggestionSpansAtWord() {
+ helpTestGetSuggestionSpansAtWord(10);
+ helpTestGetSuggestionSpansAtWord(12);
+ helpTestGetSuggestionSpansAtWord(15);
+ helpTestGetSuggestionSpansAtWord(16);
+ }
+
+ private void helpTestGetSuggestionSpansAtWord(final int cursorPos) {
+ final MockInputMethodService mockInputMethodService = new MockInputMethodService();
+ final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
+
+ final String[] SUGGESTIONS1 = { "swing", "strong" };
+ final String[] SUGGESTIONS2 = { "storing", "strung" };
+
+ // Test the usual case.
+ SpannableString text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ TextRange r;
+ SuggestionSpan[] suggestions;
+
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 1);
+ MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
+
+ // Test the case with 2 suggestion spans in the same place.
+ text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 2);
+ MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
+ MoreAsserts.assertEquals(suggestions[1].getSuggestions(), SUGGESTIONS2);
+
+ // Test a case with overlapping spans, 2nd extending past the start of the word
+ text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
+ 5 /* start */, 16 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 1);
+ MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
+
+ // Test a case with overlapping spans, 2nd extending past the end of the word
+ text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
+ 10 /* start */, 20 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 1);
+ MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
+
+ // Test a case with overlapping spans, 2nd extending past both ends of the word
+ text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 10 /* start */, 16 /* end */, 0 /* flags */);
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
+ 5 /* start */, 20 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 1);
+ MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
+
+ // Test a case with overlapping spans, none right on the word
+ text = new SpannableString("This is a string for test");
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */),
+ 5 /* start */, 16 /* end */, 0 /* flags */);
+ text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
+ 5 /* start */, 20 /* end */, 0 /* flags */);
+ mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
+ r = ic.getWordRangeAtCursor(" ", 0);
+ suggestions = r.getSuggestionSpansAtWord();
+ assertEquals(suggestions.length, 0);
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
deleted file mode 100644
index abfaf3062..000000000
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * 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 android.content.Context;
-import android.content.res.Resources;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SmallTest
-public class SubtypeLocaleTests extends AndroidTestCase {
- // Locale to subtypes list.
- private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList();
-
- private RichInputMethodManager mRichImm;
- private Resources mRes;
-
- InputMethodSubtype EN_US;
- InputMethodSubtype EN_GB;
- InputMethodSubtype ES_US;
- InputMethodSubtype FR;
- InputMethodSubtype FR_CA;
- InputMethodSubtype DE;
- InputMethodSubtype ZZ;
- InputMethodSubtype DE_QWERTY;
- InputMethodSubtype FR_QWERTZ;
- InputMethodSubtype EN_US_AZERTY;
- InputMethodSubtype EN_UK_DVORAK;
- InputMethodSubtype ES_US_COLEMAK;
- InputMethodSubtype ZZ_PC;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- final Context context = getContext();
- RichInputMethodManager.init(context);
- mRichImm = RichInputMethodManager.getInstance();
- mRes = context.getResources();
- SubtypeLocale.init(context);
-
- EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.US.toString(), "qwerty");
- EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.UK.toString(), "qwerty");
- ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- "es_US", "spanish");
- FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.FRENCH.toString(), "azerty");
- FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.CANADA_FRENCH.toString(), "qwerty");
- DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.GERMAN.toString(), "qwertz");
- ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- SubtypeLocale.NO_LANGUAGE, "qwerty");
- DE_QWERTY = AdditionalSubtype.createAdditionalSubtype(
- Locale.GERMAN.toString(), "qwerty", null);
- FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
- Locale.FRENCH.toString(), "qwertz", null);
- EN_US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
- Locale.US.toString(), "azerty", null);
- EN_UK_DVORAK = AdditionalSubtype.createAdditionalSubtype(
- Locale.UK.toString(), "dvorak", null);
- ES_US_COLEMAK = AdditionalSubtype.createAdditionalSubtype(
- "es_US", "colemak", null);
- ZZ_PC = AdditionalSubtype.createAdditionalSubtype(
- SubtypeLocale.NO_LANGUAGE, "pcqwerty", null);
-
- }
-
- public void testAllFullDisplayName() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocale.getSubtypeDisplayName(subtype);
- if (SubtypeLocale.isNoLanguage(subtype)) {
- final String noLanguage = mRes.getString(R.string.subtype_no_language);
- assertTrue(subtypeName, subtypeName.contains(noLanguage));
- } else {
- final String languageName =
- SubtypeLocale.getSubtypeLocaleDisplayName(subtype.getLocale());
- assertTrue(subtypeName, subtypeName.contains(languageName));
- }
- }
- }
-
- // InputMethodSubtype's display name in its locale.
- // isAdditionalSubtype (T=true, F=false)
- // locale layout | display name
- // ------ ------- - ----------------------
- // en_US qwerty F English (US) exception
- // en_GB qwerty F English (UK) exception
- // es_US spanish F Español (EE.UU.) exception
- // fr azerty F Français
- // fr_CA qwerty F Français (Canada)
- // de qwertz F Deutsch
- // zz qwerty F No language (QWERTY) in system locale
- // fr qwertz T Français (QWERTZ)
- // de qwerty T Deutsch (QWERTY)
- // en_US azerty T English (US) (AZERTY) exception
- // en_UK dvorak T English (UK) (Dvorak) exception
- // es_US colemak T Español (EE.UU.) (Colemak) exception
- // zz pc T No language (PC) in system locale
-
- public void testPredefinedSubtypesInEnglish() {
- assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
- assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
- assertEquals("es_US", "spanish", SubtypeLocale.getKeyboardLayoutSetName(ES_US));
- assertEquals("fr ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR));
- assertEquals("fr_CA", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(FR_CA));
- assertEquals("de ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
- assertEquals("zz ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
-
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("en_US", "English (US)",
- SubtypeLocale.getSubtypeDisplayName(EN_US));
- assertEquals("en_GB", "English (UK)",
- SubtypeLocale.getSubtypeDisplayName(EN_GB));
- assertEquals("es_US", "Español (EE.UU.)",
- SubtypeLocale.getSubtypeDisplayName(ES_US));
- assertEquals("fr ", "Français",
- SubtypeLocale.getSubtypeDisplayName(FR));
- assertEquals("fr_CA", "Français (Canada)",
- SubtypeLocale.getSubtypeDisplayName(FR_CA));
- assertEquals("de ", "Deutsch",
- SubtypeLocale.getSubtypeDisplayName(DE));
- assertEquals("zz ", "No language (QWERTY)",
- SubtypeLocale.getSubtypeDisplayName(ZZ));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testAdditionalSubtypesInEnglish() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("fr qwertz", "Français (QWERTZ)",
- SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch (QWERTY)",
- SubtypeLocale.getSubtypeDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English (US) (AZERTY)",
- SubtypeLocale.getSubtypeDisplayName(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
- SubtypeLocale.getSubtypeDisplayName(EN_UK_DVORAK));
- assertEquals("es_US colemak","Español (EE.UU.) (Colemak)",
- SubtypeLocale.getSubtypeDisplayName(ES_US_COLEMAK));
- assertEquals("zz pc", "No language (PC)",
- SubtypeLocale.getSubtypeDisplayName(ZZ_PC));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testPredefinedSubtypesInFrench() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("en_US", "English (US)",
- SubtypeLocale.getSubtypeDisplayName(EN_US));
- assertEquals("en_GB", "English (UK)",
- SubtypeLocale.getSubtypeDisplayName(EN_GB));
- assertEquals("es_US", "Español (EE.UU.)",
- SubtypeLocale.getSubtypeDisplayName(ES_US));
- assertEquals("fr ", "Français",
- SubtypeLocale.getSubtypeDisplayName(FR));
- assertEquals("fr_CA", "Français (Canada)",
- SubtypeLocale.getSubtypeDisplayName(FR_CA));
- assertEquals("de ", "Deutsch",
- SubtypeLocale.getSubtypeDisplayName(DE));
- assertEquals("zz ", "Aucune langue (QWERTY)",
- SubtypeLocale.getSubtypeDisplayName(ZZ));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.FRENCH);
- }
-
- public void testAdditionalSubtypesInFrench() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("fr qwertz", "Français (QWERTZ)",
- SubtypeLocale.getSubtypeDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch (QWERTY)",
- SubtypeLocale.getSubtypeDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English (US) (AZERTY)",
- SubtypeLocale.getSubtypeDisplayName(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
- SubtypeLocale.getSubtypeDisplayName(EN_UK_DVORAK));
- assertEquals("es_US colemak","Español (EE.UU.) (Colemak)",
- SubtypeLocale.getSubtypeDisplayName(ES_US_COLEMAK));
- assertEquals("zz azerty", "Aucune langue (PC)",
- SubtypeLocale.getSubtypeDisplayName(ZZ_PC));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.FRENCH);
- }
-
- // InputMethodSubtype's display name in system locale (en_US).
- // isAdditionalSubtype (T=true, F=false)
- // locale layout | display name
- // ------ ------- - ----------------------
- // en_US qwerty F English (US) exception
- // en_GB qwerty F English (UK) exception
- // es_US spanish F Spanish (US) exception
- // fr azerty F French
- // fr_CA qwerty F French (Canada)
- // de qwertz F German
- // zz qwerty F No language (QWERTY)
- // fr qwertz T French (QWERTZ)
- // de qwerty T German (QWERTY)
- // en_US azerty T English (US) (AZERTY) exception
- // en_UK dvorak T English (UK) (Dvorak) exception
- // es_US colemak T Spanish (US) (Colemak) exception
- // zz pc T No language (PC)
-
- public void testPredefinedSubtypesInEnglishSystemLocale() {
- assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US));
- assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB));
- assertEquals("es_US", "spanish", SubtypeLocale.getKeyboardLayoutSetName(ES_US));
- assertEquals("fr ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR));
- assertEquals("fr_CA", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(FR_CA));
- assertEquals("de ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE));
- assertEquals("zz ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ));
-
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("en_US", "English (US)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_US));
- assertEquals("en_GB", "English (UK)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_GB));
- assertEquals("es_US", "Spanish (US)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ES_US));
- assertEquals("fr ", "French",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR));
- assertEquals("fr_CA", "French (Canada)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR_CA));
- assertEquals("de ", "German",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(DE));
- assertEquals("zz ", "No language (QWERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ZZ));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testAdditionalSubtypesInEnglishSystemLocale() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("fr qwertz", "French (QWERTZ)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
- assertEquals("de qwerty", "German (QWERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
- assertEquals("en_US azerty", "English (US) (AZERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
- assertEquals("es_US colemak","Spanish (US) (Colemak)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
- assertEquals("zz azerty", "No language (PC)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.ENGLISH);
- }
-
- // InputMethodSubtype's display name in system locale (fr).
- // isAdditionalSubtype (T=true, F=false)
- // locale layout | display name
- // ------ ------- - ----------------------
- // en_US qwerty F Anglais (États-Unis) exception
- // en_GB qwerty F Anglais (Royaume-Uni) exception
- // es_US spanish F Espagnol (États-Unis) exception
- // fr azerty F Français
- // fr_CA qwerty F Français (Canada)
- // de qwertz F Allemand
- // zz qwerty F Aucune langue (QWERTY)
- // fr qwertz T Français (QWERTZ)
- // de qwerty T Allemand (QWERTY)
- // en_US azerty T Anglais (États-Unis) (AZERTY) exception
- // en_UK dvorak T Anglais (Royaume-Uni) (Dvorak) exception
- // es_US colemak T Espagnol (États-Unis) (Colemak) exception
- // zz pc T Aucune langue (PC)
-
- public void testPredefinedSubtypesInFrenchSystemLocale() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("en_US", "Anglais (États-Unis)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_US));
- assertEquals("en_GB", "Anglais (Royaume-Uni)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_GB));
- assertEquals("es_US", "Espagnol (États-Unis)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ES_US));
- assertEquals("fr ", "Français",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR));
- assertEquals("fr_CA", "Français (Canada)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR_CA));
- assertEquals("de ", "Allemand",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(DE));
- assertEquals("zz ", "Aucune langue (QWERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ZZ));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.FRENCH);
- }
-
- public void testAdditionalSubtypesInFrenchSystemLocale() {
- final RunInLocale<Void> tests = new RunInLocale<Void>() {
- @Override
- protected Void job(Resources res) {
- assertEquals("fr qwertz", "Français (QWERTZ)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
- assertEquals("de qwerty", "Allemand (QWERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
- assertEquals("en_US azerty", "Anglais (États-Unis) (AZERTY)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "Anglais (Royaume-Uni) (Dvorak)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
- assertEquals("es_US colemak","Espagnol (États-Unis) (Colemak)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
- assertEquals("zz azerty", "Aucune langue (PC)",
- SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
- return null;
- }
- };
- tests.runInLocale(mRes, Locale.FRENCH);
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 916252292..a594baf0b 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -21,6 +21,8 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
import java.util.ArrayList;
import java.util.Locale;
@@ -32,9 +34,14 @@ public class SuggestedWordsTests extends AndroidTestCase {
final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
final ArrayList<SuggestedWordInfo> list = CollectionUtils.newArrayList();
list.add(new SuggestedWordInfo(TYPED_WORD, TYPED_WORD_FREQ,
- SuggestedWordInfo.KIND_TYPED, ""));
+ SuggestedWordInfo.KIND_TYPED, null /* sourceDict */,
+ SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+ SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
- list.add(new SuggestedWordInfo("" + i, 1, SuggestedWordInfo.KIND_CORRECTION, ""));
+ list.add(new SuggestedWordInfo("" + i, 1, SuggestedWordInfo.KIND_CORRECTION,
+ null /* sourceDict */,
+ SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+ SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
final SuggestedWords words = new SuggestedWords(
@@ -57,4 +64,37 @@ public class SuggestedWordsTests extends AndroidTestCase {
assertEquals("0", wordsWithoutTyped.getWord(0));
assertEquals(SuggestedWordInfo.KIND_CORRECTION, wordsWithoutTyped.getInfo(0).mKind);
}
+
+ // Helper for testGetTransformedWordInfo
+ private SuggestedWordInfo createWordInfo(final String s) {
+ // Use 100 as the frequency because the numerical value does not matter as
+ // long as it's > 1 and < INT_MAX.
+ return new SuggestedWordInfo(s, 100,
+ SuggestedWordInfo.KIND_TYPED, null /* sourceDict */,
+ SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+ SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
+ }
+
+ // Helper for testGetTransformedWordInfo
+ private SuggestedWordInfo transformWordInfo(final String info,
+ final int trailingSingleQuotesCount) {
+ return Suggest.getTransformedSuggestedWordInfo(createWordInfo(info),
+ Locale.ENGLISH, false /* isAllUpperCase */, false /* isFirstCharCapitalized */,
+ trailingSingleQuotesCount);
+ }
+
+ public void testGetTransformedSuggestedWordInfo() {
+ SuggestedWordInfo result = transformWordInfo("word", 0);
+ assertEquals(result.mWord, "word");
+ result = transformWordInfo("word", 1);
+ assertEquals(result.mWord, "word'");
+ result = transformWordInfo("word", 3);
+ assertEquals(result.mWord, "word'''");
+ result = transformWordInfo("didn't", 0);
+ assertEquals(result.mWord, "didn't");
+ result = transformWordInfo("didn't", 1);
+ assertEquals(result.mWord, "didn't");
+ result = transformWordInfo("didn't", 3);
+ assertEquals(result.mWord, "didn't''");
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java
deleted file mode 100644
index 594ba0e7b..000000000
--- a/tests/src/com/android/inputmethod/latin/UserHistoryDictionaryTests.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2012 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.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * Unit tests for UserHistoryDictionary
- */
-@LargeTest
-public class UserHistoryDictionaryTests extends AndroidTestCase {
- private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
- private SharedPreferences mPrefs;
-
- private static final String[] CHARACTERS = {
- "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
- "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
- };
-
- @Override
- public void setUp() {
- mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
- }
-
- /**
- * Generates a random word.
- */
- private String generateWord(final int value) {
- final int lengthOfChars = CHARACTERS.length;
- StringBuilder builder = new StringBuilder();
- long lvalue = Math.abs((long)value);
- while (lvalue > 0) {
- builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
- lvalue /= lengthOfChars;
- }
- return builder.toString();
- }
-
- private List<String> generateWords(final int number, final Random random) {
- final Set<String> wordSet = CollectionUtils.newHashSet();
- while (wordSet.size() < number) {
- wordSet.add(generateWord(random.nextInt()));
- }
- return new ArrayList<String>(wordSet);
- }
-
- private void addToDict(final UserHistoryDictionary dict, final List<String> words) {
- String prevWord = null;
- for (String word : words) {
- dict.forceAddWordForTest(prevWord, word, true);
- prevWord = word;
- }
- }
-
- public void testRandomWords() {
- File dictFile = null;
- try {
- Log.d(TAG, "This test can be used for profiling.");
- Log.d(TAG, "Usage: please set UserHisotoryDictionary.PROFILE_SAVE_RESTORE to true.");
- final int numberOfWords = 1000;
- final Random random = new Random(123456);
- List<String> words = generateWords(numberOfWords, random);
-
- final String locale = "testRandomWords";
- final String fileName = "UserHistoryDictionary." + locale + ".dict";
- dictFile = new File(getContext().getFilesDir(), fileName);
- final UserHistoryDictionary dict = UserHistoryDictionary.getInstance(getContext(),
- locale, mPrefs);
- dict.isTest = true;
-
- addToDict(dict, words);
-
- try {
- Log.d(TAG, "waiting for adding the word ...");
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- Log.d(TAG, "InterruptedException: " + e);
- }
-
- // write to file
- dict.close();
-
- try {
- Log.d(TAG, "waiting for writing ...");
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- Log.d(TAG, "InterruptedException: " + e);
- }
- } finally {
- if (dictFile != null) {
- dictFile.delete();
- }
- }
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/WordComposerTests.java b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
new file mode 100644
index 000000000..1434c6b63
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 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 android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Unit tests for WordComposer.
+ */
+@SmallTest
+public class WordComposerTests extends AndroidTestCase {
+ public void testMoveCursor() {
+ final WordComposer wc = new WordComposer();
+ final String STR_WITHIN_BMP = "abcdef";
+ wc.setComposingWord(STR_WITHIN_BMP, null);
+ assertEquals(wc.size(),
+ STR_WITHIN_BMP.codePointCount(0, STR_WITHIN_BMP.length()));
+ assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
+ wc.setCursorPositionWithinWord(2);
+ assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
+ // Move the cursor to after the 'd'
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(2));
+ assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
+ // Move the cursor to after the 'e'
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
+ assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
+ assertEquals(wc.size(), 6);
+ // Move the cursor to after the 'f'
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
+ assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
+ // Move the cursor past the end of the word
+ assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(1));
+ assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(15));
+
+ // \uD861\uDED7 is 𨛗, a character outside the BMP
+ final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh";
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ assertEquals(wc.size(), STR_WITH_SUPPLEMENTARY_CHAR.codePointCount(0,
+ STR_WITH_SUPPLEMENTARY_CHAR.length()));
+ assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
+ wc.setCursorPositionWithinWord(3);
+ assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(6));
+ assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
+ assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ wc.setCursorPositionWithinWord(3);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(7));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ wc.setCursorPositionWithinWord(3);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(7));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ wc.setCursorPositionWithinWord(3);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(-3));
+ assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-1));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ wc.setCursorPositionWithinWord(3);
+ assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-9));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(-10));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-11));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(0));
+
+ wc.setComposingWord(STR_WITH_SUPPLEMENTARY_CHAR, null);
+ wc.setCursorPositionWithinWord(2);
+ assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(0));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
new file mode 100644
index 000000000..a4d94262f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -0,0 +1,684 @@
+/*
+ * Copyright (C) 2012 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.makedict;
+
+import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
+import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.utils.ByteArrayDictBuffer;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Unit tests for BinaryDictDecoderUtils and BinaryDictEncoderUtils.
+ */
+@LargeTest
+public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
+ private static final String TAG = BinaryDictDecoderEncoderTests.class.getSimpleName();
+ private static final int DEFAULT_MAX_UNIGRAMS = 100;
+ private static final int DEFAULT_CODE_POINT_SET_SIZE = 50;
+ private static final int UNIGRAM_FREQ = 10;
+ private static final int BIGRAM_FREQ = 50;
+ private static final int TOLERANCE_OF_BIGRAM_FREQ = 5;
+ private static final int NUM_OF_NODES_HAVING_SHORTCUTS = 50;
+ private static final int NUM_OF_SHORTCUTS = 5;
+
+ private static final int USE_BYTE_ARRAY = 1;
+ private static final int USE_BYTE_BUFFER = 2;
+
+ private static final ArrayList<String> sWords = CollectionUtils.newArrayList();
+ private static final SparseArray<List<Integer>> sEmptyBigrams =
+ CollectionUtils.newSparseArray();
+ private static final SparseArray<List<Integer>> sStarBigrams = CollectionUtils.newSparseArray();
+ private static final SparseArray<List<Integer>> sChainBigrams =
+ CollectionUtils.newSparseArray();
+ private static final HashMap<String, List<String>> sShortcuts = CollectionUtils.newHashMap();
+
+ private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
+ private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
+ private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
+ private static final FormatSpec.FormatOptions VERSION4_WITHOUT_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(4, false /* supportsDynamicUpdate */);
+ private static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */);
+
+ private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
+
+ public BinaryDictDecoderEncoderTests() {
+ this(System.currentTimeMillis(), DEFAULT_MAX_UNIGRAMS);
+ }
+
+ public BinaryDictDecoderEncoderTests(final long seed, final int maxUnigrams) {
+ super();
+ Log.e(TAG, "Testing dictionary: seed is " + seed);
+ final Random random = new Random(seed);
+ sWords.clear();
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
+ random);
+ generateWords(maxUnigrams, random, codePointSet);
+
+ for (int i = 0; i < sWords.size(); ++i) {
+ sChainBigrams.put(i, new ArrayList<Integer>());
+ if (i > 0) {
+ sChainBigrams.get(i - 1).add(i);
+ }
+ }
+
+ sStarBigrams.put(0, new ArrayList<Integer>());
+ for (int i = 1; i < sWords.size(); ++i) {
+ sStarBigrams.get(0).add(i);
+ }
+
+ sShortcuts.clear();
+ for (int i = 0; i < NUM_OF_NODES_HAVING_SHORTCUTS; ++i) {
+ final int from = Math.abs(random.nextInt()) % sWords.size();
+ sShortcuts.put(sWords.get(from), new ArrayList<String>());
+ for (int j = 0; j < NUM_OF_SHORTCUTS; ++j) {
+ final int to = Math.abs(random.nextInt()) % sWords.size();
+ sShortcuts.get(sWords.get(from)).add(sWords.get(to));
+ }
+ }
+ }
+
+ private DictEncoder getDictEncoder(final File file, final FormatOptions formatOptions) {
+ if (formatOptions.mVersion == FormatSpec.VERSION4) {
+ return new Ver4DictEncoder(getContext().getCacheDir());
+ } else if (formatOptions.mVersion == 3 || formatOptions.mVersion == 2) {
+ return new Ver3DictEncoder(file);
+ } else {
+ throw new RuntimeException("The format option has a wrong version : "
+ + formatOptions.mVersion);
+ }
+ }
+
+ private void generateWords(final int number, final Random random, final int[] codePointSet) {
+ final Set<String> wordSet = CollectionUtils.newHashSet();
+ while (wordSet.size() < number) {
+ wordSet.add(CodePointUtils.generateWord(random, codePointSet));
+ }
+ sWords.addAll(wordSet);
+ }
+
+ /**
+ * Adds unigrams to the dictionary.
+ */
+ private void addUnigrams(final int number, final FusionDictionary dict,
+ final List<String> words, final HashMap<String, List<String>> shortcutMap) {
+ for (int i = 0; i < number; ++i) {
+ final String word = words.get(i);
+ final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList();
+ if (shortcutMap != null && shortcutMap.containsKey(word)) {
+ for (final String shortcut : shortcutMap.get(word)) {
+ shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
+ }
+ }
+ dict.add(word, UNIGRAM_FREQ, (shortcutMap == null) ? null : shortcuts,
+ false /* isNotAWord */);
+ }
+ }
+
+ private void addBigrams(final FusionDictionary dict,
+ final List<String> words,
+ final SparseArray<List<Integer>> bigrams) {
+ for (int i = 0; i < bigrams.size(); ++i) {
+ final int w1 = bigrams.keyAt(i);
+ for (int w2 : bigrams.valueAt(i)) {
+ dict.setBigram(words.get(w1), words.get(w2), BIGRAM_FREQ);
+ }
+ }
+ }
+
+// The following is useful to dump the dictionary into a textual file, but it can't compile
+// on-device, so it's commented out.
+// private void dumpToCombinedFileForDebug(final FusionDictionary dict, final String filename)
+// throws IOException {
+// com.android.inputmethod.latin.dicttool.CombinedInputOutput.writeDictionaryCombined(
+// new java.io.FileWriter(new File(filename)), dict);
+// }
+
+ private long timeWritingDictToFile(final File file, final FusionDictionary dict,
+ final FormatSpec.FormatOptions formatOptions) {
+
+ long now = -1, diff = -1;
+
+ try {
+ final DictEncoder dictEncoder = getDictEncoder(file, formatOptions);
+
+ now = System.currentTimeMillis();
+ // If you need to dump the dict to a textual file, uncomment the line below and the
+ // function above
+ // dumpToCombinedFileForDebug(file, "/tmp/foo");
+ dictEncoder.writeDictionary(dict, formatOptions);
+ diff = System.currentTimeMillis() - now;
+ } catch (IOException e) {
+ Log.e(TAG, "IO exception while writing file", e);
+ } catch (UnsupportedFormatException e) {
+ Log.e(TAG, "UnsupportedFormatException", e);
+ }
+
+ return diff;
+ }
+
+ private void checkDictionary(final FusionDictionary dict, final List<String> words,
+ final SparseArray<List<Integer>> bigrams,
+ final HashMap<String, List<String>> shortcutMap) {
+ assertNotNull(dict);
+
+ // check unigram
+ for (final String word : words) {
+ final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
+ assertNotNull(ptNode);
+ }
+
+ // check bigram
+ for (int i = 0; i < bigrams.size(); ++i) {
+ final int w1 = bigrams.keyAt(i);
+ for (final int w2 : bigrams.valueAt(i)) {
+ final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
+ words.get(w1));
+ assertNotNull(words.get(w1) + "," + words.get(w2), ptNode.getBigram(words.get(w2)));
+ }
+ }
+
+ // check shortcut
+ if (shortcutMap != null) {
+ for (final Entry<String, List<String>> entry : shortcutMap.entrySet()) {
+ assertTrue(words.contains(entry.getKey()));
+ final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
+ entry.getKey());
+ for (final String word : entry.getValue()) {
+ assertNotNull("shortcut not found: " + entry.getKey() + ", " + word,
+ ptNode.getShortcut(word));
+ }
+ }
+ }
+ }
+
+ private String outputOptions(final int bufferType,
+ final FormatSpec.FormatOptions formatOptions) {
+ String result = " : buffer type = "
+ + ((bufferType == USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
+ result += " : version = " + formatOptions.mVersion;
+ return result + ", supportsDynamicUpdate = " + formatOptions.mSupportsDynamicUpdate;
+ }
+
+ private DictionaryOptions getDictionaryOptions(final String id, final String version) {
+ final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>(),
+ false, false);
+ options.mAttributes.put("version", version);
+ options.mAttributes.put("dictionary", id);
+ return options;
+ }
+
+ private File setUpDictionaryFile(final String name, final String version) {
+ File file = null;
+ try {
+ file = new File(getContext().getCacheDir(), name + "." + version
+ + TEST_DICT_FILE_EXTENSION);
+ file.createNewFile();
+ } catch (IOException e) {
+ // do nothing
+ }
+ assertTrue("Failed to create the dictionary file.", file.exists());
+ return file;
+ }
+
+ private DictDecoder getDictDecoder(final File file, final int bufferType,
+ final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
+ if (formatOptions.mVersion == FormatSpec.VERSION4) {
+ final FileHeader header = new FileHeader(0, dictOptions, formatOptions);
+ return FormatSpec.getDictDecoder(new File(getContext().getCacheDir(),
+ header.getId() + "." + header.getVersion()), bufferType);
+ } else {
+ return FormatSpec.getDictDecoder(file, bufferType);
+ }
+ }
+ // Tests for readDictionaryBinary and writeDictionaryBinary
+
+ private long timeReadingAndCheckDict(final File file, final List<String> words,
+ final SparseArray<List<Integer>> bigrams,
+ final HashMap<String, List<String>> shortcutMap, final int bufferType,
+ final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
+ long now, diff = -1;
+
+ FusionDictionary dict = null;
+ try {
+ final DictDecoder dictDecoder = getDictDecoder(file, bufferType, formatOptions,
+ dictOptions);
+ now = System.currentTimeMillis();
+ dict = dictDecoder.readDictionaryBinary(null, false /* deleteDictIfBroken */);
+ diff = System.currentTimeMillis() - now;
+ } catch (IOException e) {
+ Log.e(TAG, "IOException while reading dictionary", e);
+ } catch (UnsupportedFormatException e) {
+ Log.e(TAG, "Unsupported format", e);
+ }
+
+ checkDictionary(dict, words, bigrams, shortcutMap);
+ return diff;
+ }
+
+ // Tests for readDictionaryBinary and writeDictionaryBinary
+ private String runReadAndWrite(final List<String> words,
+ final SparseArray<List<Integer>> bigrams, final HashMap<String, List<String>> shortcuts,
+ final int bufferType, final FormatSpec.FormatOptions formatOptions,
+ final String message) {
+
+ final String dictName = "runReadAndWrite";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+ final File file = setUpDictionaryFile(dictName, dictVersion);
+
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
+ getDictionaryOptions(dictName, dictVersion));
+ addUnigrams(words.size(), dict, words, shortcuts);
+ addBigrams(dict, words, bigrams);
+ checkDictionary(dict, words, bigrams, shortcuts);
+
+ final long write = timeWritingDictToFile(file, dict, formatOptions);
+ final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType,
+ formatOptions, dict.mOptions);
+
+ return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
+ + " : " + outputOptions(bufferType, formatOptions);
+ }
+
+ private void runReadAndWriteTests(final List<String> results, final int bufferType,
+ final FormatSpec.FormatOptions formatOptions) {
+ results.add(runReadAndWrite(sWords, sEmptyBigrams, null /* shortcuts */, bufferType,
+ formatOptions, "unigram"));
+ results.add(runReadAndWrite(sWords, sChainBigrams, null /* shortcuts */, bufferType,
+ formatOptions, "chain"));
+ results.add(runReadAndWrite(sWords, sStarBigrams, null /* shortcuts */, bufferType,
+ formatOptions, "star"));
+ results.add(runReadAndWrite(sWords, sEmptyBigrams, sShortcuts, bufferType, formatOptions,
+ "unigram with shortcuts"));
+ results.add(runReadAndWrite(sWords, sChainBigrams, sShortcuts, bufferType, formatOptions,
+ "chain with shortcuts"));
+ results.add(runReadAndWrite(sWords, sStarBigrams, sShortcuts, bufferType, formatOptions,
+ "star with shortcuts"));
+ }
+
+ // Unit test for CharEncoding.readString and CharEncoding.writeString.
+ public void testCharEncoding() {
+ // the max length of a word in sWords is less than 50.
+ // See generateWords.
+ final byte[] buffer = new byte[50 * 3];
+ final DictBuffer dictBuffer = new ByteArrayDictBuffer(buffer);
+ for (final String word : sWords) {
+ Log.d("testReadAndWriteString", "write : " + word);
+ Arrays.fill(buffer, (byte)0);
+ CharEncoding.writeString(buffer, 0, word);
+ dictBuffer.position(0);
+ final String str = CharEncoding.readString(dictBuffer);
+ assertEquals(word, str);
+ }
+ }
+
+ public void testReadAndWriteWithByteBuffer() {
+ final List<String> results = CollectionUtils.newArrayList();
+
+ runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION2);
+ runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ for (final String result : results) {
+ Log.d(TAG, result);
+ }
+ }
+
+ public void testReadAndWriteWithByteArray() {
+ final List<String> results = CollectionUtils.newArrayList();
+
+ runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION2);
+ runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ for (final String result : results) {
+ Log.d(TAG, result);
+ }
+ }
+
+ // Tests for readUnigramsAndBigramsBinary
+
+ private void checkWordMap(final List<String> expectedWords,
+ final SparseArray<List<Integer>> expectedBigrams,
+ final TreeMap<Integer, String> resultWords,
+ final TreeMap<Integer, Integer> resultFrequencies,
+ final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams) {
+ // check unigrams
+ final Set<String> actualWordsSet = new HashSet<String>(resultWords.values());
+ final Set<String> expectedWordsSet = new HashSet<String>(expectedWords);
+ assertEquals(actualWordsSet, expectedWordsSet);
+
+ for (int freq : resultFrequencies.values()) {
+ assertEquals(freq, UNIGRAM_FREQ);
+ }
+
+ // check bigrams
+ final HashMap<String, List<String>> expBigrams = new HashMap<String, List<String>>();
+ for (int i = 0; i < expectedBigrams.size(); ++i) {
+ final String word1 = expectedWords.get(expectedBigrams.keyAt(i));
+ for (int w2 : expectedBigrams.valueAt(i)) {
+ if (expBigrams.get(word1) == null) {
+ expBigrams.put(word1, new ArrayList<String>());
+ }
+ expBigrams.get(word1).add(expectedWords.get(w2));
+ }
+ }
+
+ final HashMap<String, List<String>> actBigrams = new HashMap<String, List<String>>();
+ for (Entry<Integer, ArrayList<PendingAttribute>> entry : resultBigrams.entrySet()) {
+ final String word1 = resultWords.get(entry.getKey());
+ final int unigramFreq = resultFrequencies.get(entry.getKey());
+ for (PendingAttribute attr : entry.getValue()) {
+ final String word2 = resultWords.get(attr.mAddress);
+ if (actBigrams.get(word1) == null) {
+ actBigrams.put(word1, new ArrayList<String>());
+ }
+ actBigrams.get(word1).add(word2);
+
+ final int bigramFreq = BinaryDictIOUtils.reconstructBigramFrequency(
+ unigramFreq, attr.mFrequency);
+ assertTrue(Math.abs(bigramFreq - BIGRAM_FREQ) < TOLERANCE_OF_BIGRAM_FREQ);
+ }
+ }
+
+ assertEquals(actBigrams, expBigrams);
+ }
+
+ private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
+ final SparseArray<List<Integer>> bigrams, final int bufferType,
+ final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
+ FileInputStream inStream = null;
+
+ final TreeMap<Integer, String> resultWords = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams =
+ CollectionUtils.newTreeMap();
+ final TreeMap<Integer, Integer> resultFreqs = CollectionUtils.newTreeMap();
+
+ long now = -1, diff = -1;
+ try {
+ final DictDecoder dictDecoder = getDictDecoder(file, bufferType, formatOptions,
+ dictOptions);
+ now = System.currentTimeMillis();
+ dictDecoder.readUnigramsAndBigramsBinary(resultWords, resultFreqs, resultBigrams);
+ diff = System.currentTimeMillis() - now;
+ } catch (IOException e) {
+ Log.e(TAG, "IOException", e);
+ } catch (UnsupportedFormatException e) {
+ Log.e(TAG, "UnsupportedFormatException", e);
+ } finally {
+ if (inStream != null) {
+ try {
+ inStream.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+
+ checkWordMap(words, bigrams, resultWords, resultFreqs, resultBigrams);
+ return diff;
+ }
+
+ private String runReadUnigramsAndBigramsBinary(final ArrayList<String> words,
+ final SparseArray<List<Integer>> bigrams, final int bufferType,
+ final FormatSpec.FormatOptions formatOptions, final String message) {
+ final String dictName = "runReadUnigrams";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+ final File file = setUpDictionaryFile(dictName, dictVersion);
+
+ // making the dictionary from lists of words.
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
+ getDictionaryOptions(dictName, dictVersion));
+ addUnigrams(words.size(), dict, words, null /* shortcutMap */);
+ addBigrams(dict, words, bigrams);
+
+ timeWritingDictToFile(file, dict, formatOptions);
+
+ long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType,
+ formatOptions, dict.mOptions);
+ long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
+ bufferType, formatOptions, dict.mOptions);
+
+ return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
+ + " : " + message + " : " + outputOptions(bufferType, formatOptions);
+ }
+
+ private void runReadUnigramsAndBigramsTests(final ArrayList<String> results,
+ final int bufferType, final FormatSpec.FormatOptions formatOptions) {
+ results.add(runReadUnigramsAndBigramsBinary(sWords, sEmptyBigrams, bufferType,
+ formatOptions, "unigram"));
+ results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
+ formatOptions, "chain"));
+ results.add(runReadUnigramsAndBigramsBinary(sWords, sStarBigrams, bufferType,
+ formatOptions, "star"));
+ }
+
+ public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
+ final ArrayList<String> results = CollectionUtils.newArrayList();
+
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ for (final String result : results) {
+ Log.d(TAG, result);
+ }
+ }
+
+ public void testReadUnigramsAndBigramsBinaryWithByteArray() {
+ final ArrayList<String> results = CollectionUtils.newArrayList();
+
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ for (final String result : results) {
+ Log.d(TAG, result);
+ }
+ }
+
+ // Tests for getTerminalPosition
+ private String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
+ if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
+
+ FileHeader fileHeader = null;
+ try {
+ fileHeader = dictDecoder.readHeader();
+ } catch (IOException e) {
+ return null;
+ } catch (UnsupportedFormatException e) {
+ return null;
+ }
+ if (fileHeader == null) return null;
+ return BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mHeaderSize,
+ address, fileHeader.mFormatOptions).mWord;
+ }
+
+ private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
+ int index, boolean contained) {
+ final int expectedFrequency = (UNIGRAM_FREQ + index) % 255;
+ long diff = -1;
+ int position = -1;
+ try {
+ final long now = System.nanoTime();
+ position = dictDecoder.getTerminalPosition(word);
+ diff = System.nanoTime() - now;
+ } catch (IOException e) {
+ Log.e(TAG, "IOException while getTerminalPosition", e);
+ } catch (UnsupportedFormatException e) {
+ Log.e(TAG, "UnsupportedFormatException while getTerminalPosition", e);
+ }
+
+ assertEquals(FormatSpec.NOT_VALID_WORD != position, contained);
+ if (contained) assertEquals(getWordFromBinary(dictDecoder, position), word);
+ return diff;
+ }
+
+ private void runGetTerminalPosition(final ArrayList<String> words,
+ final SparseArray<List<Integer>> bigrams, final int bufferType,
+ final FormatOptions formatOptions, final String message) {
+ final String dictName = "testGetTerminalPosition";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+ final File file = setUpDictionaryFile(dictName, dictVersion);
+
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
+ getDictionaryOptions(dictName, dictVersion));
+ addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
+ addBigrams(dict, words, bigrams);
+ timeWritingDictToFile(file, dict, formatOptions);
+
+ final DictDecoder dictDecoder = getDictDecoder(file, DictDecoder.USE_BYTEARRAY,
+ formatOptions, dict.mOptions);
+ try {
+ dictDecoder.openDictBuffer();
+ } catch (IOException e) {
+ // ignore
+ Log.e(TAG, "IOException while opening the buffer", e);
+ }
+ assertTrue("Can't get the buffer", dictDecoder.isDictBufferOpen());
+
+ try {
+ // too long word
+ final String longWord = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(longWord));
+
+ // null
+ assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(null));
+
+ // empty string
+ assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(""));
+ } catch (IOException e) {
+ } catch (UnsupportedFormatException e) {
+ }
+
+ // Test a word that is contained within the dictionary.
+ long sum = 0;
+ for (int i = 0; i < sWords.size(); ++i) {
+ final long time = checkGetTerminalPosition(dictDecoder, sWords.get(i), i, true);
+ sum += time == -1 ? 0 : time;
+ }
+ Log.d(TAG, "per search : " + (((double)sum) / sWords.size() / 1000000) + " : " + message
+ + " : " + outputOptions(bufferType, formatOptions));
+
+ // Test a word that isn't contained within the dictionary.
+ final Random random = new Random((int)System.currentTimeMillis());
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
+ random);
+ for (int i = 0; i < 1000; ++i) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ if (sWords.indexOf(word) != -1) continue;
+ checkGetTerminalPosition(dictDecoder, word, i, false);
+ }
+ }
+
+ private void runGetTerminalPositionTests(final ArrayList<String> results, final int bufferType,
+ final FormatOptions formatOptions) {
+ runGetTerminalPosition(sWords, sEmptyBigrams, bufferType, formatOptions, "unigram");
+ }
+
+ public void testGetTerminalPosition() {
+ final ArrayList<String> results = CollectionUtils.newArrayList();
+
+ runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION2);
+ runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION2);
+ runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+
+ for (final String result : results) {
+ Log.d(TAG, result);
+ }
+ }
+
+ public void testDeleteWord() {
+ final String dictName = "testDeleteWord";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+ final File file = setUpDictionaryFile(dictName, dictVersion);
+
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
+ new FusionDictionary.DictionaryOptions(
+ new HashMap<String, String>(), false, false));
+ addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
+ timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE);
+
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file, DictDecoder.USE_BYTEARRAY);
+ try {
+ dictDecoder.openDictBuffer();
+ } catch (IOException e) {
+ // ignore
+ Log.e(TAG, "IOException while opening the buffer", e);
+ }
+ assertTrue("Can't get the buffer", dictDecoder.isDictBufferOpen());
+
+ try {
+ MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
+ dictDecoder.getTerminalPosition(sWords.get(0)));
+ DynamicBinaryDictIOUtils.deleteWord(dictDecoder, sWords.get(0));
+ assertEquals(FormatSpec.NOT_VALID_WORD,
+ dictDecoder.getTerminalPosition(sWords.get(0)));
+
+ MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
+ dictDecoder.getTerminalPosition(sWords.get(5)));
+ DynamicBinaryDictIOUtils.deleteWord(dictDecoder, sWords.get(5));
+ assertEquals(FormatSpec.NOT_VALID_WORD,
+ dictDecoder.getTerminalPosition(sWords.get(5)));
+ } catch (IOException e) {
+ } catch (UnsupportedFormatException e) {
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
deleted file mode 100644
index b704d08b3..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright (C) 2012 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.makedict;
-
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.UserHistoryDictIOUtils;
-import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
-import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
-import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
-import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
-import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * Unit tests for BinaryDictInputOutput
- */
-@LargeTest
-public class BinaryDictIOTests extends AndroidTestCase {
- private static final String TAG = BinaryDictIOTests.class.getSimpleName();
- private static final int MAX_UNIGRAMS = 100;
- private static final int UNIGRAM_FREQ = 10;
- private static final int BIGRAM_FREQ = 50;
- private static final int TOLERANCE_OF_BIGRAM_FREQ = 5;
-
- private static final int USE_BYTE_ARRAY = 1;
- private static final int USE_BYTE_BUFFER = 2;
-
- private static final List<String> sWords = CollectionUtils.newArrayList();
- private static final SparseArray<List<Integer>> sEmptyBigrams =
- CollectionUtils.newSparseArray();
- private static final SparseArray<List<Integer>> sStarBigrams = CollectionUtils.newSparseArray();
- private static final SparseArray<List<Integer>> sChainBigrams =
- CollectionUtils.newSparseArray();
-
- private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
- private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
- private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
-
- public BinaryDictIOTests() {
- super();
-
- final long time = System.currentTimeMillis();
- Log.e(TAG, "Testing dictionary: seed is " + time);
- final Random random = new Random(time);
- sWords.clear();
- generateWords(MAX_UNIGRAMS, random);
-
- for (int i = 0; i < sWords.size(); ++i) {
- sChainBigrams.put(i, new ArrayList<Integer>());
- if (i > 0) {
- sChainBigrams.get(i - 1).add(i);
- }
- }
-
- sStarBigrams.put(0, new ArrayList<Integer>());
- for (int i = 1; i < sWords.size(); ++i) {
- sStarBigrams.get(0).add(i);
- }
- }
-
- // Utilities for test
-
- /**
- * Makes new buffer according to BUFFER_TYPE.
- */
- private FusionDictionaryBufferInterface getBuffer(final File file, final int bufferType) {
- FileInputStream inStream = null;
- try {
- inStream = new FileInputStream(file);
- if (bufferType == USE_BYTE_ARRAY) {
- final byte[] array = new byte[(int)file.length()];
- inStream.read(array);
- return new UserHistoryDictIOUtils.ByteArrayWrapper(array);
- } else if (bufferType == USE_BYTE_BUFFER){
- final ByteBuffer buffer = inStream.getChannel().map(
- FileChannel.MapMode.READ_ONLY, 0, file.length());
- return new BinaryDictInputOutput.ByteBufferWrapper(buffer);
- }
- } catch (IOException e) {
- Log.e(TAG, "IOException while making buffer", e);
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- Log.e(TAG, "IOException while closing stream", e);
- }
- }
- }
- return null;
- }
-
- /**
- * Generates a random word.
- */
- private String generateWord(final Random random) {
- StringBuilder builder = new StringBuilder("a");
- int count = random.nextInt() % 30; // Arbitrarily 30 chars max
- while (count > 0) {
- final long r = Math.abs(random.nextInt());
- if (r < 0) continue;
- // Don't insert 0~0x20, but insert any other code point.
- // Code points are in the range 0~0x10FFFF.
- final int candidateCodePoint = (int)(0x20 + r % (Character.MAX_CODE_POINT - 0x20));
- // Code points between MIN_ and MAX_SURROGATE are not valid on their own.
- if (candidateCodePoint >= Character.MIN_SURROGATE
- && candidateCodePoint <= Character.MAX_SURROGATE) continue;
- builder.appendCodePoint(candidateCodePoint);
- --count;
- }
- return builder.toString();
- }
-
- private void generateWords(final int number, final Random random) {
- final Set<String> wordSet = CollectionUtils.newHashSet();
- while (wordSet.size() < number) {
- wordSet.add(generateWord(random));
- }
- sWords.addAll(wordSet);
- }
-
- /**
- * Adds unigrams to the dictionary.
- */
- private void addUnigrams(final int number, final FusionDictionary dict,
- final List<String> words, final Map<String, List<String>> shortcutMap) {
- for (int i = 0; i < number; ++i) {
- final String word = words.get(i);
- final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList();
- if (shortcutMap != null && shortcutMap.containsKey(word)) {
- for (final String shortcut : shortcutMap.get(word)) {
- shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
- }
- }
- dict.add(word, UNIGRAM_FREQ, (shortcutMap == null) ? null : shortcuts,
- false /* isNotAWord */);
- }
- }
-
- private void addBigrams(final FusionDictionary dict,
- final List<String> words,
- final SparseArray<List<Integer>> bigrams) {
- for (int i = 0; i < bigrams.size(); ++i) {
- final int w1 = bigrams.keyAt(i);
- for (int w2 : bigrams.valueAt(i)) {
- dict.setBigram(words.get(w1), words.get(w2), BIGRAM_FREQ);
- }
- }
- }
-
- private long timeWritingDictToFile(final File file, final FusionDictionary dict,
- final FormatSpec.FormatOptions formatOptions) {
-
- long now = -1, diff = -1;
-
- try {
- final FileOutputStream out = new FileOutputStream(file);
-
- now = System.currentTimeMillis();
- BinaryDictInputOutput.writeDictionaryBinary(out, dict, formatOptions);
- diff = System.currentTimeMillis() - now;
-
- out.flush();
- out.close();
- } catch (IOException e) {
- Log.e(TAG, "IO exception while writing file", e);
- } catch (UnsupportedFormatException e) {
- Log.e(TAG, "UnsupportedFormatException", e);
- }
-
- return diff;
- }
-
- private void checkDictionary(final FusionDictionary dict, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap) {
- assertNotNull(dict);
-
- // check unigram
- for (final String word : words) {
- final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, word);
- assertNotNull(cg);
- }
-
- // check bigram
- for (int i = 0; i < bigrams.size(); ++i) {
- final int w1 = bigrams.keyAt(i);
- for (final int w2 : bigrams.valueAt(i)) {
- final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, words.get(w1));
- assertNotNull(words.get(w1) + "," + words.get(w2), cg.getBigram(words.get(w2)));
- }
- }
-
- // check shortcut
- if (shortcutMap != null) {
- for (final Map.Entry<String, List<String>> entry : shortcutMap.entrySet()) {
- final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, entry.getKey());
- for (final String word : entry.getValue()) {
- assertNotNull("shortcut not found: " + entry.getKey() + ", " + word,
- group.getShortcut(word));
- }
- }
- }
- }
-
- private String outputOptions(final int bufferType,
- final FormatSpec.FormatOptions formatOptions) {
- String result = " : buffer type = "
- + ((bufferType == USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
- result += " : version = " + formatOptions.mVersion;
- return result + ", supportsDynamicUpdate = " + formatOptions.mSupportsDynamicUpdate;
- }
-
- // Tests for readDictionaryBinary and writeDictionaryBinary
-
- private long timeReadingAndCheckDict(final File file, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap,
- final int bufferType) {
- long now, diff = -1;
- final FusionDictionaryBufferInterface buffer = getBuffer(file, bufferType);
- assertNotNull(buffer);
-
- FusionDictionary dict = null;
- try {
- now = System.currentTimeMillis();
- dict = BinaryDictInputOutput.readDictionaryBinary(buffer, null);
- diff = System.currentTimeMillis() - now;
- } catch (IOException e) {
- Log.e(TAG, "IOException while reading dictionary", e);
- } catch (UnsupportedFormatException e) {
- Log.e(TAG, "Unsupported format", e);
- }
-
- checkDictionary(dict, words, bigrams, shortcutMap);
- return diff;
- }
-
- // Tests for readDictionaryBinary and writeDictionaryBinary
- private String runReadAndWrite(final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcuts,
- final int bufferType, final FormatSpec.FormatOptions formatOptions,
- final String message) {
- File file = null;
- try {
- file = File.createTempFile("runReadAndWrite", ".dict", getContext().getCacheDir());
- } catch (IOException e) {
- Log.e(TAG, "IOException", e);
- }
- assertNotNull(file);
-
- final FusionDictionary dict = new FusionDictionary(new Node(),
- new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
- addUnigrams(words.size(), dict, words, shortcuts);
- addBigrams(dict, words, bigrams);
- checkDictionary(dict, words, bigrams, shortcuts);
-
- final long write = timeWritingDictToFile(file, dict, formatOptions);
- final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType);
-
- return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
- + " : " + outputOptions(bufferType, formatOptions);
- }
-
- private void runReadAndWriteTests(final List<String> results, final int bufferType,
- final FormatSpec.FormatOptions formatOptions) {
- results.add(runReadAndWrite(sWords, sEmptyBigrams, null /* shortcuts */, bufferType,
- formatOptions, "unigram"));
- results.add(runReadAndWrite(sWords, sChainBigrams, null /* shortcuts */, bufferType,
- formatOptions, "chain"));
- results.add(runReadAndWrite(sWords, sStarBigrams, null /* shortcuts */, bufferType,
- formatOptions, "star"));
- }
-
- public void testReadAndWriteWithByteBuffer() {
- final List<String> results = CollectionUtils.newArrayList();
-
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION2);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- public void testReadAndWriteWithByteArray() {
- final List<String> results = CollectionUtils.newArrayList();
-
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION2);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- // Tests for readUnigramsAndBigramsBinary
-
- private void checkWordMap(final List<String> expectedWords,
- final SparseArray<List<Integer>> expectedBigrams,
- final Map<Integer, String> resultWords,
- final Map<Integer, Integer> resultFrequencies,
- final Map<Integer, ArrayList<PendingAttribute>> resultBigrams) {
- // check unigrams
- final Set<String> actualWordsSet = new HashSet<String>(resultWords.values());
- final Set<String> expectedWordsSet = new HashSet<String>(expectedWords);
- assertEquals(actualWordsSet, expectedWordsSet);
-
- for (int freq : resultFrequencies.values()) {
- assertEquals(freq, UNIGRAM_FREQ);
- }
-
- // check bigrams
- final Map<String, List<String>> expBigrams = new HashMap<String, List<String>>();
- for (int i = 0; i < expectedBigrams.size(); ++i) {
- final String word1 = expectedWords.get(expectedBigrams.keyAt(i));
- for (int w2 : expectedBigrams.valueAt(i)) {
- if (expBigrams.get(word1) == null) {
- expBigrams.put(word1, new ArrayList<String>());
- }
- expBigrams.get(word1).add(expectedWords.get(w2));
- }
- }
-
- final Map<String, List<String>> actBigrams = new HashMap<String, List<String>>();
- for (Entry<Integer, ArrayList<PendingAttribute>> entry : resultBigrams.entrySet()) {
- final String word1 = resultWords.get(entry.getKey());
- final int unigramFreq = resultFrequencies.get(entry.getKey());
- for (PendingAttribute attr : entry.getValue()) {
- final String word2 = resultWords.get(attr.mAddress);
- if (actBigrams.get(word1) == null) {
- actBigrams.put(word1, new ArrayList<String>());
- }
- actBigrams.get(word1).add(word2);
-
- final int bigramFreq = BinaryDictInputOutput.reconstructBigramFrequency(
- unigramFreq, attr.mFrequency);
- assertTrue(Math.abs(bigramFreq - BIGRAM_FREQ) < TOLERANCE_OF_BIGRAM_FREQ);
- }
- }
-
- assertEquals(actBigrams, expBigrams);
- }
-
- private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final int bufferType) {
- FileInputStream inStream = null;
-
- final Map<Integer, String> resultWords = CollectionUtils.newTreeMap();
- final Map<Integer, ArrayList<PendingAttribute>> resultBigrams =
- CollectionUtils.newTreeMap();
- final Map<Integer, Integer> resultFreqs = CollectionUtils.newTreeMap();
-
- long now = -1, diff = -1;
- final FusionDictionaryBufferInterface buffer = getBuffer(file, bufferType);
- assertNotNull("Can't get buffer.", buffer);
- try {
- now = System.currentTimeMillis();
- BinaryDictIOUtils.readUnigramsAndBigramsBinary(buffer, resultWords, resultFreqs,
- resultBigrams);
- diff = System.currentTimeMillis() - now;
- } catch (IOException e) {
- Log.e(TAG, "IOException", e);
- } catch (UnsupportedFormatException e) {
- Log.e(TAG, "UnsupportedFormatException", e);
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
- }
-
- checkWordMap(words, bigrams, resultWords, resultFreqs, resultBigrams);
- return diff;
- }
-
- private String runReadUnigramsAndBigramsBinary(final List<String> words,
- final SparseArray<List<Integer>> bigrams, final int bufferType,
- final FormatSpec.FormatOptions formatOptions, final String message) {
- File file = null;
- try {
- file = File.createTempFile("runReadUnigrams", ".dict", getContext().getCacheDir());
- } catch (IOException e) {
- Log.e(TAG, "IOException", e);
- }
- assertNotNull(file);
-
- // making the dictionary from lists of words.
- final FusionDictionary dict = new FusionDictionary(new Node(),
- new FusionDictionary.DictionaryOptions(
- new HashMap<String, String>(), false, false));
- addUnigrams(words.size(), dict, words, null /* shortcutMap */);
- addBigrams(dict, words, bigrams);
-
- timeWritingDictToFile(file, dict, formatOptions);
-
- long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType);
- long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
- bufferType);
-
- return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
- + " : " + message + " : " + outputOptions(bufferType, formatOptions);
- }
-
- private void runReadUnigramsAndBigramsTests(final List<String> results, final int bufferType,
- final FormatSpec.FormatOptions formatOptions) {
- results.add(runReadUnigramsAndBigramsBinary(sWords, sEmptyBigrams, bufferType,
- formatOptions, "unigram"));
- results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
- formatOptions, "chain"));
- results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
- formatOptions, "star"));
- }
-
- public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
- final List<String> results = CollectionUtils.newArrayList();
-
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- public void testReadUnigramsAndBigramsBinaryWithByteArray() {
- final List<String> results = CollectionUtils.newArrayList();
-
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- // Tests for getTerminalPosition
- private String getWordFromBinary(final FusionDictionaryBufferInterface buffer,
- final int address) {
- if (buffer.position() != 0) buffer.position(0);
-
- FileHeader header = null;
- try {
- header = BinaryDictInputOutput.readHeader(buffer);
- } catch (IOException e) {
- return null;
- } catch (UnsupportedFormatException e) {
- return null;
- }
- if (header == null) return null;
- return BinaryDictInputOutput.getWordAtAddress(buffer, header.mHeaderSize,
- address - header.mHeaderSize, header.mFormatOptions).mWord;
- }
-
- private long runGetTerminalPosition(final FusionDictionaryBufferInterface buffer,
- final String word, int index, boolean contained) {
- final int expectedFrequency = (UNIGRAM_FREQ + index) % 255;
- long diff = -1;
- int position = -1;
- try {
- final long now = System.nanoTime();
- position = BinaryDictIOUtils.getTerminalPosition(buffer, word);
- diff = System.nanoTime() - now;
- } catch (IOException e) {
- Log.e(TAG, "IOException while getTerminalPosition", e);
- } catch (UnsupportedFormatException e) {
- Log.e(TAG, "UnsupportedFormatException while getTerminalPosition", e);
- }
-
- assertEquals(FormatSpec.NOT_VALID_WORD != position, contained);
- if (contained) assertEquals(getWordFromBinary(buffer, position), word);
- return diff;
- }
-
- public void testGetTerminalPosition() {
- File file = null;
- try {
- file = File.createTempFile("testGetTerminalPosition", ".dict",
- getContext().getCacheDir());
- } catch (IOException e) {
- // do nothing
- }
- assertNotNull(file);
-
- final FusionDictionary dict = new FusionDictionary(new Node(),
- new FusionDictionary.DictionaryOptions(
- new HashMap<String, String>(), false, false));
- addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
- timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE);
-
- final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY);
-
- try {
- // too long word
- final String longWord = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
- assertEquals(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, longWord));
-
- // null
- assertEquals(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, null));
-
- // empty string
- assertEquals(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, ""));
- } catch (IOException e) {
- } catch (UnsupportedFormatException e) {
- }
-
- // Test a word that is contained within the dictionary.
- long sum = 0;
- for (int i = 0; i < sWords.size(); ++i) {
- final long time = runGetTerminalPosition(buffer, sWords.get(i), i, true);
- sum += time == -1 ? 0 : time;
- }
- Log.d(TAG, "per a search : " + (((double)sum) / sWords.size() / 1000000));
-
- // Test a word that isn't contained within the dictionary.
- final Random random = new Random((int)System.currentTimeMillis());
- for (int i = 0; i < 1000; ++i) {
- final String word = generateWord(random);
- if (sWords.indexOf(word) != -1) continue;
- runGetTerminalPosition(buffer, word, i, false);
- }
- }
-
- public void testDeleteWord() {
- File file = null;
- try {
- file = File.createTempFile("testDeleteWord", ".dict", getContext().getCacheDir());
- } catch (IOException e) {
- // do nothing
- }
- assertNotNull(file);
-
- final FusionDictionary dict = new FusionDictionary(new Node(),
- new FusionDictionary.DictionaryOptions(
- new HashMap<String, String>(), false, false));
- addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
- timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE);
-
- final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY);
-
- try {
- MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0)));
- BinaryDictIOUtils.deleteWord(buffer, sWords.get(0));
- assertEquals(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0)));
-
- MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5)));
- BinaryDictIOUtils.deleteWord(buffer, sWords.get(5));
- assertEquals(FormatSpec.NOT_VALID_WORD,
- BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5)));
- } catch (IOException e) {
- } catch (UnsupportedFormatException e) {
- }
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
index 47885f023..a83749499 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
@@ -21,46 +21,52 @@ import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
-import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.ByteBufferWrapper;
-import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
-import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
@LargeTest
-public class BinaryDictIOUtilsTests extends AndroidTestCase {
+public class BinaryDictIOUtilsTests extends AndroidTestCase {
private static final String TAG = BinaryDictIOUtilsTests.class.getSimpleName();
private static final FormatSpec.FormatOptions FORMAT_OPTIONS =
new FormatSpec.FormatOptions(3, true);
- private static final int MAX_UNIGRAMS = 1500;
private static final ArrayList<String> sWords = CollectionUtils.newArrayList();
+ public static final int DEFAULT_MAX_UNIGRAMS = 1500;
+ private final int mMaxUnigrams;
+
+ private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
private static final String[] CHARACTERS = {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"\u00FC" /* ü */, "\u00E2" /* â */, "\u00F1" /* ñ */, // accented characters
"\u4E9C" /* 亜 */, "\u4F0A" /* 伊 */, "\u5B87" /* 宇 */, // kanji
- "\uD841\uDE28" /* 𠘨 */, "\uD840\uDC0B" /* 𠀋 */, "\uD861\uDeD7" /* 𨛗 */ // surrogate pair
+ "\uD841\uDE28" /* 𠘨 */, "\uD840\uDC0B" /* 𠀋 */, "\uD861\uDED7" /* 𨛗 */ // surrogate pair
};
public BinaryDictIOUtilsTests() {
+ // 1500 is the default max unigrams
+ this(System.currentTimeMillis(), DEFAULT_MAX_UNIGRAMS);
+ }
+
+ public BinaryDictIOUtilsTests(final long seed, final int maxUnigrams) {
super();
- final Random random = new Random(123456);
+ Log.d(TAG, "Seed for test is " + seed + ", maxUnigrams is " + maxUnigrams);
+ mMaxUnigrams = maxUnigrams;
+ final Random random = new Random(seed);
sWords.clear();
- for (int i = 0; i < MAX_UNIGRAMS; ++i) {
+ for (int i = 0; i < maxUnigrams; ++i) {
sWords.add(generateWord(random.nextInt()));
}
}
@@ -78,8 +84,8 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
return builder.toString();
}
- private static void printCharGroup(final CharGroupInfo info) {
- Log.d(TAG, " CharGroup at " + info.mOriginalAddress);
+ private static void printPtNode(final PtNodeInfo info) {
+ Log.d(TAG, " PtNode at " + info.mOriginalAddress);
Log.d(TAG, " flags = " + info.mFlags);
Log.d(TAG, " parentAddress = " + info.mParentAddress);
Log.d(TAG, " characters = " + new String(info.mCharacters, 0,
@@ -103,70 +109,75 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
Log.d(TAG, " end address = " + info.mEndAddress);
}
- private static void printNode(final FusionDictionaryBufferInterface buffer,
+ private static void printNode(final Ver3DictDecoder dictDecoder,
final FormatSpec.FormatOptions formatOptions) {
- Log.d(TAG, "Node at " + buffer.position());
- final int count = BinaryDictInputOutput.readCharGroupCount(buffer);
- Log.d(TAG, " charGroupCount = " + count);
+ final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
+ Log.d(TAG, "Node at " + dictBuffer.position());
+ final int count = BinaryDictDecoderUtils.readPtNodeCount(dictBuffer);
+ Log.d(TAG, " ptNodeCount = " + count);
for (int i = 0; i < count; ++i) {
- final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer,
- buffer.position(), formatOptions);
- printCharGroup(currentInfo);
+ final PtNodeInfo currentInfo = dictDecoder.readPtNode(dictBuffer.position(),
+ formatOptions);
+ printPtNode(currentInfo);
}
if (formatOptions.mSupportsDynamicUpdate) {
- final int forwardLinkAddress = buffer.readUnsignedInt24();
+ final int forwardLinkAddress = dictBuffer.readUnsignedInt24();
Log.d(TAG, " forwardLinkAddress = " + forwardLinkAddress);
}
}
- private static void printBinaryFile(final FusionDictionaryBufferInterface buffer)
+ @SuppressWarnings("unused")
+ private static void printBinaryFile(final Ver3DictDecoder dictDecoder)
throws IOException, UnsupportedFormatException {
- FileHeader header = BinaryDictInputOutput.readHeader(buffer);
- while (buffer.position() < buffer.limit()) {
- printNode(buffer, header.mFormatOptions);
+ final FileHeader fileHeader = dictDecoder.readHeader();
+ final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
+ while (dictBuffer.position() < dictBuffer.limit()) {
+ printNode(dictDecoder, fileHeader.mFormatOptions);
}
}
private int getWordPosition(final File file, final String word) {
int position = FormatSpec.NOT_VALID_WORD;
- FileInputStream inStream = null;
+
try {
- inStream = new FileInputStream(file);
- final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper(
- inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()));
- position = BinaryDictIOUtils.getTerminalPosition(buffer, word);
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file,
+ DictDecoder.USE_READONLY_BYTEBUFFER);
+ position = dictDecoder.getTerminalPosition(word);
} catch (IOException e) {
} catch (UnsupportedFormatException e) {
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
return position;
}
- private CharGroupInfo findWordFromFile(final File file, final String word) {
- FileInputStream inStream = null;
- CharGroupInfo info = null;
+ /**
+ * Find a word using the DictDecoder.
+ *
+ * @param dictDecoder the dict decoder
+ * @param word the word searched
+ * @return the found ptNodeInfo
+ * @throws IOException
+ * @throws UnsupportedFormatException
+ */
+ private static PtNodeInfo findWordByBinaryDictReader(final DictDecoder dictDecoder,
+ final String word) throws IOException, UnsupportedFormatException {
+ int position = dictDecoder.getTerminalPosition(word);
+ if (position != FormatSpec.NOT_VALID_WORD) {
+ dictDecoder.setPosition(0);
+ final FileHeader header = dictDecoder.readHeader();
+ dictDecoder.setPosition(position);
+ return dictDecoder.readPtNode(position, header.mFormatOptions);
+ }
+ return null;
+ }
+
+ private PtNodeInfo findWordFromFile(final File file, final String word) {
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file);
+ PtNodeInfo info = null;
try {
- inStream = new FileInputStream(file);
- final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper(
- inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()));
- info = BinaryDictIOUtils.findWordFromBuffer(buffer, word);
+ dictDecoder.openDictBuffer();
+ info = findWordByBinaryDictReader(dictDecoder, word);
} catch (IOException e) {
} catch (UnsupportedFormatException e) {
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
return info;
}
@@ -175,42 +186,34 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
private long insertAndCheckWord(final File file, final String word, final int frequency,
final boolean exist, final ArrayList<WeightedString> bigrams,
final ArrayList<WeightedString> shortcuts) {
- RandomAccessFile raFile = null;
BufferedOutputStream outStream = null;
- FusionDictionaryBufferInterface buffer = null;
long amountOfTime = -1;
try {
- raFile = new RandomAccessFile(file, "rw");
- buffer = new ByteBufferWrapper(raFile.getChannel().map(
- FileChannel.MapMode.READ_WRITE, 0, file.length()));
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file,
+ DictDecoder.USE_WRITABLE_BYTEBUFFER);
+ dictDecoder.openDictBuffer();
outStream = new BufferedOutputStream(new FileOutputStream(file, true));
if (!exist) {
assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word));
}
final long now = System.nanoTime();
- BinaryDictIOUtils.insertWord(buffer, outStream, word, frequency, bigrams, shortcuts,
- false, false);
+ DynamicBinaryDictIOUtils.insertWord(dictDecoder, outStream, word, frequency, bigrams,
+ shortcuts, false, false);
amountOfTime = System.nanoTime() - now;
outStream.flush();
MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word));
outStream.close();
- raFile.close();
} catch (IOException e) {
+ Log.e(TAG, "Raised an IOException while inserting a word", e);
} catch (UnsupportedFormatException e) {
+ Log.e(TAG, "Raised an UnsupportedFormatException error while inserting a word", e);
} finally {
if (outStream != null) {
try {
outStream.close();
} catch (IOException e) {
- // do nothing
- }
- }
- if (raFile != null) {
- try {
- raFile.close();
- } catch (IOException e) {
- // do nothing
+ Log.e(TAG, "Failed to close the output stream", e);
}
}
}
@@ -218,65 +221,48 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
}
private void deleteWord(final File file, final String word) {
- RandomAccessFile raFile = null;
- FusionDictionaryBufferInterface buffer = null;
try {
- raFile = new RandomAccessFile(file, "rw");
- buffer = new ByteBufferWrapper(raFile.getChannel().map(
- FileChannel.MapMode.READ_WRITE, 0, file.length()));
- BinaryDictIOUtils.deleteWord(buffer, word);
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file,
+ DictDecoder.USE_WRITABLE_BYTEBUFFER);
+ dictDecoder.openDictBuffer();
+ DynamicBinaryDictIOUtils.deleteWord(dictDecoder, word);
} catch (IOException e) {
} catch (UnsupportedFormatException e) {
- } finally {
- if (raFile != null) {
- try {
- raFile.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
}
private void checkReverseLookup(final File file, final String word, final int position) {
- FileInputStream inStream = null;
+
try {
- inStream = new FileInputStream(file);
- final FusionDictionaryBufferInterface buffer = new ByteBufferWrapper(
- inStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()));
- final FileHeader header = BinaryDictInputOutput.readHeader(buffer);
- assertEquals(word, BinaryDictInputOutput.getWordAtAddress(buffer, header.mHeaderSize,
- position - header.mHeaderSize, header.mFormatOptions).mWord);
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file);
+ final FileHeader fileHeader = dictDecoder.readHeader();
+ assertEquals(word,
+ BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mHeaderSize,
+ position, fileHeader.mFormatOptions).mWord);
} catch (IOException e) {
+ Log.e(TAG, "Raised an IOException while looking up a word", e);
} catch (UnsupportedFormatException e) {
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
+ Log.e(TAG, "Raised an UnsupportedFormatException error while looking up a word", e);
}
}
public void testInsertWord() {
File file = null;
try {
- file = File.createTempFile("testInsertWord", ".dict", getContext().getCacheDir());
+ file = File.createTempFile("testInsertWord", TEST_DICT_FILE_EXTENSION,
+ getContext().getCacheDir());
} catch (IOException e) {
fail("IOException while creating temporary file: " + e);
}
// set an initial dictionary.
- final FusionDictionary dict = new FusionDictionary(new Node(),
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
dict.add("abcd", 10, null, false);
try {
- final FileOutputStream out = new FileOutputStream(file);
- BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS);
- out.close();
+ final DictEncoder dictEncoder = new Ver3DictEncoder(file);
+ dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
} catch (IOException e) {
fail("IOException while writing an initial dictionary : " + e);
} catch (UnsupportedFormatException e) {
@@ -313,22 +299,21 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
public void testInsertWordWithBigrams() {
File file = null;
try {
- file = File.createTempFile("testInsertWordWithBigrams", ".dict",
+ file = File.createTempFile("testInsertWordWithBigrams", TEST_DICT_FILE_EXTENSION,
getContext().getCacheDir());
} catch (IOException e) {
fail("IOException while creating temporary file: " + e);
}
// set an initial dictionary.
- final FusionDictionary dict = new FusionDictionary(new Node(),
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
dict.add("abcd", 10, null, false);
dict.add("efgh", 15, null, false);
try {
- final FileOutputStream out = new FileOutputStream(file);
- BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS);
- out.close();
+ final DictEncoder dictEncoder = new Ver3DictEncoder(file);
+ dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
} catch (IOException e) {
fail("IOException while writing an initial dictionary : " + e);
} catch (UnsupportedFormatException e) {
@@ -341,7 +326,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
insertAndCheckWord(file, "banana", 0, false, null, null);
insertAndCheckWord(file, "recursive", 60, true, banana, null);
- final CharGroupInfo info = findWordFromFile(file, "recursive");
+ final PtNodeInfo info = findWordFromFile(file, "recursive");
int bananaPos = getWordPosition(file, "banana");
assertNotNull(info.mBigrams);
assertEquals(info.mBigrams.size(), 1);
@@ -351,21 +336,21 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
public void testRandomWords() {
File file = null;
try {
- file = File.createTempFile("testRandomWord", ".dict", getContext().getCacheDir());
+ file = File.createTempFile("testRandomWord", TEST_DICT_FILE_EXTENSION,
+ getContext().getCacheDir());
} catch (IOException e) {
}
assertNotNull(file);
// set an initial dictionary.
- final FusionDictionary dict = new FusionDictionary(new Node(),
+ final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new FusionDictionary.DictionaryOptions(new HashMap<String, String>(), false,
false));
dict.add("initial", 10, null, false);
try {
- final FileOutputStream out = new FileOutputStream(file);
- BinaryDictInputOutput.writeDictionaryBinary(out, dict, FORMAT_OPTIONS);
- out.close();
+ final DictEncoder dictEncoder = new Ver3DictEncoder(file);
+ dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
} catch (IOException e) {
assertTrue(false);
} catch (UnsupportedFormatException e) {
@@ -390,6 +375,6 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
Log.d(TAG, "max = " + ((double)maxTimeToInsert/1000000) + " ms.");
Log.d(TAG, "min = " + ((double)minTimeToInsert/1000000) + " ms.");
- Log.d(TAG, "avg = " + ((double)sum/MAX_UNIGRAMS/1000000) + " ms.");
+ Log.d(TAG, "avg = " + ((double)sum/mMaxUnigrams/1000000) + " ms.");
}
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java b/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
new file mode 100644
index 000000000..36b958af8
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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.makedict;
+
+import java.util.Random;
+
+// Utility methods related with code points used for tests.
+public class CodePointUtils {
+ private CodePointUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static int[] generateCodePointSet(final int codePointSetSize, final Random random) {
+ final int[] codePointSet = new int[codePointSetSize];
+ for (int i = codePointSet.length - 1; i >= 0; ) {
+ final int r = Math.abs(random.nextInt());
+ if (r < 0) continue;
+ // Don't insert 0~0x20, but insert any other code point.
+ // Code points are in the range 0~0x10FFFF.
+ final int candidateCodePoint = 0x20 + r % (Character.MAX_CODE_POINT - 0x20);
+ // Code points between MIN_ and MAX_SURROGATE are not valid on their own.
+ if (candidateCodePoint >= Character.MIN_SURROGATE
+ && candidateCodePoint <= Character.MAX_SURROGATE) continue;
+ codePointSet[i] = candidateCodePoint;
+ --i;
+ }
+ return codePointSet;
+ }
+
+ /**
+ * Generates a random word.
+ */
+ public static String generateWord(final Random random, final int[] codePointSet) {
+ StringBuilder builder = new StringBuilder();
+ // 8 * 4 = 32 chars max, but we do it the following way so as to bias the random toward
+ // longer words. This should be closer to natural language, and more importantly, it will
+ // exercise the algorithms in dicttool much more.
+ final int count = 1 + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5)
+ + (Math.abs(random.nextInt()) % 5);
+ while (builder.length() < count) {
+ builder.appendCodePoint(codePointSet[Math.abs(random.nextInt()) % codePointSet.length]);
+ }
+ return builder.toString();
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java b/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java
new file mode 100644
index 000000000..132483d5e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2013 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.makedict;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * Unit tests for SparseTable.
+ */
+@LargeTest
+public class SparseTableTests extends AndroidTestCase {
+ private static final String TAG = SparseTableTests.class.getSimpleName();
+
+ private static final int[] SMALL_INDEX = { SparseTable.NOT_EXIST, 0 };
+ private static final int[] BIG_INDEX = { SparseTable.NOT_EXIST, 1, 2, 3, 4, 5, 6, 7};
+
+ private final Random mRandom;
+ private final ArrayList<Integer> mRandomIndex;
+
+ private static final int DEFAULT_SIZE = 10000;
+ private static final int BLOCK_SIZE = 8;
+
+ public SparseTableTests() {
+ this(System.currentTimeMillis(), DEFAULT_SIZE);
+ }
+
+ public SparseTableTests(final long seed, final int tableSize) {
+ super();
+ Log.d(TAG, "Seed for test is " + seed + ", size is " + tableSize);
+ mRandom = new Random(seed);
+ mRandomIndex = new ArrayList<Integer>(tableSize);
+ for (int i = 0; i < tableSize; ++i) {
+ mRandomIndex.add(SparseTable.NOT_EXIST);
+ }
+ }
+
+ public void testInitializeWithArray() {
+ final SparseTable table = new SparseTable(SMALL_INDEX, BIG_INDEX, BLOCK_SIZE);
+ for (int i = 0; i < 8; ++i) {
+ assertEquals(SparseTable.NOT_EXIST, table.get(i));
+ }
+ assertEquals(SparseTable.NOT_EXIST, table.get(8));
+ for (int i = 9; i < 16; ++i) {
+ assertEquals(i - 8, table.get(i));
+ }
+ }
+
+ public void testSet() {
+ final SparseTable table = new SparseTable(16, BLOCK_SIZE);
+ table.set(3, 6);
+ table.set(8, 16);
+ for (int i = 0; i < 16; ++i) {
+ if (i == 3 || i == 8) {
+ assertEquals(i * 2, table.get(i));
+ } else {
+ assertEquals(SparseTable.NOT_EXIST, table.get(i));
+ }
+ }
+ }
+
+ private void generateRandomIndex(final int size, final int prop) {
+ for (int i = 0; i < DEFAULT_SIZE; ++i) {
+ if (mRandom.nextInt(100) < prop) {
+ mRandomIndex.set(i, mRandom.nextInt());
+ } else {
+ mRandomIndex.set(i, SparseTable.NOT_EXIST);
+ }
+ }
+ }
+
+ private void runTestRandomSet() {
+ final SparseTable table = new SparseTable(DEFAULT_SIZE, BLOCK_SIZE);
+ int elementCount = 0;
+ for (int i = 0; i < DEFAULT_SIZE; ++i) {
+ if (mRandomIndex.get(i) != SparseTable.NOT_EXIST) {
+ table.set(i, mRandomIndex.get(i));
+ elementCount++;
+ }
+ }
+
+ Log.d(TAG, "table size = " + table.getLookupTableSize() + " + "
+ + table.getContentTableSize());
+ Log.d(TAG, "the table has " + elementCount + " elements");
+ for (int i = 0; i < DEFAULT_SIZE; ++i) {
+ assertEquals(table.get(i), (int)mRandomIndex.get(i));
+ }
+
+ // flush and reload
+ OutputStream lookupOutStream = null;
+ OutputStream contentOutStream = null;
+ InputStream lookupInStream = null;
+ InputStream contentInStream = null;
+ try {
+ final File lookupIndexFile = File.createTempFile("testRandomSet", ".small");
+ final File contentFile = File.createTempFile("testRandomSet", ".big");
+ lookupOutStream = new FileOutputStream(lookupIndexFile);
+ contentOutStream = new FileOutputStream(contentFile);
+ table.write(lookupOutStream, contentOutStream);
+ lookupInStream = new FileInputStream(lookupIndexFile);
+ contentInStream = new FileInputStream(contentFile);
+ final byte[] lookupArray = new byte[(int) lookupIndexFile.length()];
+ final byte[] contentArray = new byte[(int) contentFile.length()];
+ lookupInStream.read(lookupArray);
+ contentInStream.read(contentArray);
+ final SparseTable newTable = new SparseTable(lookupArray, contentArray, BLOCK_SIZE);
+ for (int i = 0; i < DEFAULT_SIZE; ++i) {
+ assertEquals(table.get(i), newTable.get(i));
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "IOException while flushing and realoding", e);
+ } finally {
+ if (lookupOutStream != null) {
+ try {
+ lookupOutStream.close();
+ } catch (IOException e) {
+ Log.d(TAG, "IOException while closing the stream", e);
+ }
+ }
+ if (contentOutStream != null) {
+ try {
+ contentOutStream.close();
+ } catch (IOException e) {
+ Log.d(TAG, "IOException while closing contentStream.", e);
+ }
+ }
+ }
+ }
+
+ public void testRandomSet() {
+ for (int i = 0; i <= 100; i += 10) {
+ generateRandomIndex(DEFAULT_SIZE, i);
+ runTestRandomSet();
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver3DictDecoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver3DictDecoderTests.java
new file mode 100644
index 000000000..9611599b9
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver3DictDecoderTests.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 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.makedict;
+
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
+import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
+import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFromByteArrayFactory;
+import com.android.inputmethod.latin.makedict.DictDecoder.
+ DictionaryBufferFromReadOnlyByteBufferFactory;
+import com.android.inputmethod.latin.makedict.DictDecoder.
+ DictionaryBufferFromWritableByteBufferFactory;
+
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Unit tests for Ver3DictDecoder
+ */
+public class Ver3DictDecoderTests extends AndroidTestCase {
+ private static final String TAG = Ver3DictDecoderTests.class.getSimpleName();
+
+ private final byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ // Utilities for testing
+ public void writeDataToFile(final File file) {
+ FileOutputStream outStream = null;
+ try {
+ outStream = new FileOutputStream(file);
+ outStream.write(data);
+ } catch (IOException e) {
+ fail ("Can't write data to the test file");
+ } finally {
+ if (outStream != null) {
+ try {
+ outStream.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to close the output stream", e);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("null")
+ public void runTestOpenBuffer(final String testName, final DictionaryBufferFactory factory) {
+ File testFile = null;
+ try {
+ testFile = File.createTempFile(testName, ".tmp", getContext().getCacheDir());
+ } catch (IOException e) {
+ Log.e(TAG, "IOException while the creating temporary file", e);
+ }
+
+ assertNotNull(testFile);
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(testFile, factory);
+ try {
+ dictDecoder.openDictBuffer();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to open the buffer", e);
+ }
+
+ writeDataToFile(testFile);
+
+ try {
+ dictDecoder.openDictBuffer();
+ } catch (Exception e) {
+ Log.e(TAG, "Raised the exception while opening buffer", e);
+ }
+
+ assertEquals(testFile.length(), dictDecoder.getDictBuffer().capacity());
+ }
+
+ public void testOpenBufferWithByteBuffer() {
+ runTestOpenBuffer("testOpenBufferWithByteBuffer",
+ new DictionaryBufferFromReadOnlyByteBufferFactory());
+ }
+
+ public void testOpenBufferWithByteArray() {
+ runTestOpenBuffer("testOpenBufferWithByteArray",
+ new DictionaryBufferFromByteArrayFactory());
+ }
+
+ public void testOpenBufferWithWritableByteBuffer() {
+ runTestOpenBuffer("testOpenBufferWithWritableByteBuffer",
+ new DictionaryBufferFromWritableByteBufferFactory());
+ }
+
+ @SuppressWarnings("null")
+ public void runTestGetBuffer(final String testName, final DictionaryBufferFactory factory) {
+ File testFile = null;
+ try {
+ testFile = File.createTempFile(testName, ".tmp", getContext().getCacheDir());
+ } catch (IOException e) {
+ Log.e(TAG, "IOException while the creating temporary file", e);
+ }
+
+ final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(testFile, factory);
+
+ // the default return value of getBuffer() must be null.
+ assertNull("the default return value of getBuffer() is not null",
+ dictDecoder.getDictBuffer());
+
+ writeDataToFile(testFile);
+ assertTrue(testFile.exists());
+ Log.d(TAG, "file length = " + testFile.length());
+
+ DictBuffer dictBuffer = null;
+ try {
+ dictBuffer = dictDecoder.openAndGetDictBuffer();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to open and get the buffer", e);
+ }
+ assertNotNull("the buffer must not be null", dictBuffer);
+
+ for (int i = 0; i < data.length; ++i) {
+ assertEquals(data[i], dictBuffer.readUnsignedByte());
+ }
+ }
+
+ public void testGetBufferWithByteBuffer() {
+ runTestGetBuffer("testGetBufferWithByteBuffer",
+ new DictionaryBufferFromReadOnlyByteBufferFactory());
+ }
+
+ public void testGetBufferWithByteArray() {
+ runTestGetBuffer("testGetBufferWithByteArray",
+ new DictionaryBufferFromByteArrayFactory());
+ }
+
+ public void testGetBufferWithWritableByteBuffer() {
+ runTestGetBuffer("testGetBufferWithWritableByteBuffer",
+ new DictionaryBufferFromWritableByteBufferFactory());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
new file mode 100644
index 000000000..d605cdb84
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 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.personalization;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import com.android.inputmethod.latin.ExpandableBinaryDictionary;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for UserHistoryDictionary
+ */
+@LargeTest
+public class UserHistoryDictionaryTests extends AndroidTestCase {
+ private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
+ private SharedPreferences mPrefs;
+
+ private static final String[] CHARACTERS = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
+ "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
+ };
+
+ private static final int MIN_USER_HISTORY_DICTIONARY_FILE_SIZE = 1000;
+ private static final int WAIT_TERMINATING_IN_MILLISECONDS = 100;
+
+ @Override
+ public void setUp() {
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ }
+
+ /**
+ * Generates a random word.
+ */
+ private String generateWord(final int value) {
+ final int lengthOfChars = CHARACTERS.length;
+ StringBuilder builder = new StringBuilder();
+ long lvalue = Math.abs((long)value);
+ while (lvalue > 0) {
+ builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
+ lvalue /= lengthOfChars;
+ }
+ return builder.toString();
+ }
+
+ private List<String> generateWords(final int number, final Random random) {
+ final Set<String> wordSet = CollectionUtils.newHashSet();
+ while (wordSet.size() < number) {
+ wordSet.add(generateWord(random.nextInt()));
+ }
+ return new ArrayList<String>(wordSet);
+ }
+
+ private void addToDict(final UserHistoryPredictionDictionary dict, final List<String> words) {
+ String prevWord = null;
+ for (String word : words) {
+ dict.addToPersonalizationPredictionDictionary(prevWord, word, true);
+ prevWord = word;
+ }
+ }
+
+ /**
+ * @param checksContents if true, checks whether written words are actually in the dictionary
+ * or not.
+ */
+ private void addAndWriteRandomWords(final String testFilenameSuffix, final int numberOfWords,
+ final Random random, final boolean checksContents) {
+ final List<String> words = generateWords(numberOfWords, random);
+ final UserHistoryPredictionDictionary dict =
+ PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
+ testFilenameSuffix /* locale */, mPrefs);
+ // Add random words to the user history dictionary.
+ addToDict(dict, words);
+ if (checksContents) {
+ try {
+ Thread.sleep(TimeUnit.MILLISECONDS.convert(5L, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ }
+ // Limit word count to check when using a Java on memory dictionary.
+ final int wordCountToCheck =
+ ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ?
+ numberOfWords : 10;
+ for (int i = 0; i < wordCountToCheck; ++i) {
+ final String word = words.get(i);
+ // This may fail as long as we use tryLock on inserting the bigram words
+ assertTrue(dict.isInDictionaryForTests(word));
+ }
+ }
+ // write to file.
+ dict.close();
+ }
+
+ public void testRandomWords() {
+ File dictFile = null;
+ Log.d(TAG, "This test can be used for profiling.");
+ Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
+ final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis();
+ final int numberOfWords = 1000;
+ final Random random = new Random(123456);
+
+ try {
+ addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random,
+ true /* checksContents */);
+ } finally {
+ try {
+ final UserHistoryPredictionDictionary dict =
+ PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
+ testFilenameSuffix, mPrefs);
+ Log.d(TAG, "waiting for writing ...");
+ dict.shutdownExecutorForTests();
+ while (!dict.isTerminatedForTests()) {
+ Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
+ }
+ } catch (InterruptedException e) {
+ Log.d(TAG, "InterruptedException: " + e);
+ }
+
+ final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix
+ + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
+ dictFile = new File(getContext().getFilesDir(), fileName);
+
+ if (dictFile != null) {
+ assertTrue(dictFile.exists());
+ assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
+ dictFile.delete();
+ }
+ }
+ }
+
+ public void testStressTestForSwitchingLanguagesAndAddingWords() {
+ final int numberOfLanguages = 2;
+ final int numberOfLanguageSwitching = 80;
+ final int numberOfWordsInsertedForEachLanguageSwitch = 100;
+
+ final File dictFiles[] = new File[numberOfLanguages];
+ final String testFilenameSuffixes[] = new String[numberOfLanguages];
+ try {
+ final Random random = new Random(123456);
+
+ // Create filename suffixes for this test.
+ for (int i = 0; i < numberOfLanguages; i++) {
+ testFilenameSuffixes[i] = "testSwitchingLanguages" + i;
+ final String fileName = UserHistoryPredictionDictionary.NAME + "." +
+ testFilenameSuffixes[i] + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
+ dictFiles[i] = new File(getContext().getFilesDir(), fileName);
+ }
+
+ final long start = System.currentTimeMillis();
+
+ for (int i = 0; i < numberOfLanguageSwitching; i++) {
+ final int index = i % numberOfLanguages;
+ // Switch languages to testFilenameSuffixes[index].
+ addAndWriteRandomWords(testFilenameSuffixes[index],
+ numberOfWordsInsertedForEachLanguageSwitch, random,
+ false /* checksContents */);
+ }
+
+ final long end = System.currentTimeMillis();
+ Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
+ + (end - start) + " ms");
+ } finally {
+ try {
+ Log.d(TAG, "waiting for writing ...");
+ for (int i = 0; i < numberOfLanguages; i++) {
+ final UserHistoryPredictionDictionary dict =
+ PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
+ testFilenameSuffixes[i], mPrefs);
+ dict.shutdownExecutorForTests();
+ while (!dict.isTerminatedForTests()) {
+ Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
+ }
+ }
+ } catch (InterruptedException e) {
+ Log.d(TAG, "InterruptedException: " + e);
+ }
+ for (final File file : dictFiles) {
+ if (file != null) {
+ assertTrue(file.exists());
+ assertTrue(file.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
+ file.delete();
+ }
+ }
+ }
+ }
+
+ public void testAddManyWords() {
+ File dictFile = null;
+ final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis();
+ final int numberOfWords =
+ ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ?
+ 10000 : 1000;
+ final Random random = new Random(123456);
+
+ UserHistoryPredictionDictionary dict =
+ PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
+ testFilenameSuffix, mPrefs);
+ try {
+ addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random,
+ true /* checksContents */);
+ dict.close();
+ } finally {
+ try {
+ Log.d(TAG, "waiting for writing ...");
+ dict.shutdownExecutorForTests();
+ while (!dict.isTerminatedForTests()) {
+ Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
+ }
+ } catch (InterruptedException e) {
+ Log.d(TAG, "InterruptedException: ", e);
+ }
+ final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix
+ + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
+ dictFile = new File(getContext().getFilesDir(), fileName);
+ if (dictFile != null) {
+ assertTrue(dictFile.exists());
+ assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
+ dictFile.delete();
+ }
+ }
+ }
+
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
new file mode 100644
index 000000000..7fd167977
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
+
+@MediumTest
+public class AsyncResultHolderTests extends AndroidTestCase {
+ private static final String TAG = AsyncResultHolderTests.class.getSimpleName();
+
+ private static final int TIMEOUT_IN_MILLISECONDS = 500;
+ private static final int MARGIN_IN_MILLISECONDS = 250;
+ private static final int DEFAULT_VALUE = 2;
+ private static final int SET_VALUE = 1;
+
+ private <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
+ final long time) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Exception while sleeping", e);
+ }
+ holder.set(value);
+ }
+ }).start();
+ }
+
+ public void testGetWithoutSet() {
+ final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>();
+ final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS);
+ assertEquals(DEFAULT_VALUE, resultValue);
+ }
+
+ public void testGetBeforeSet() {
+ final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>();
+ setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS + MARGIN_IN_MILLISECONDS);
+ final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS);
+ assertEquals(DEFAULT_VALUE, resultValue);
+ }
+
+ public void testGetAfterSet() {
+ final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>();
+ holder.set(SET_VALUE);
+ final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS);
+ assertEquals(SET_VALUE, resultValue);
+ }
+
+ public void testGetBeforeTimeout() {
+ final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>();
+ setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS - MARGIN_IN_MILLISECONDS);
+ final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS);
+ assertEquals(SET_VALUE, resultValue);
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/Base64ReaderTests.java b/tests/src/com/android/inputmethod/latin/utils/Base64ReaderTests.java
new file mode 100644
index 000000000..b311f5d37
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/Base64ReaderTests.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.StringReader;
+
+@SmallTest
+public class Base64ReaderTests extends AndroidTestCase {
+ private static final String EMPTY_STRING = "";
+ private static final String INCOMPLETE_CHAR1 = "Q";
+ // Encode 'A'.
+ private static final String INCOMPLETE_CHAR2 = "QQ";
+ // Encode 'A', 'B'
+ private static final String INCOMPLETE_CHAR3 = "QUI";
+ // Encode 'A', 'B', 'C'
+ private static final String COMPLETE_CHAR4 = "QUJD";
+ private static final String ALL_BYTE_PATTERN =
+ "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj\n"
+ + "JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH\n"
+ + "SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr\n"
+ + "bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P\n"
+ + "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz\n"
+ + "tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX\n"
+ + "2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7\n"
+ + "/P3+/w==";
+
+ public void test0CharInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(EMPTY_STRING)));
+ try {
+ reader.readUint8();
+ fail("0 char");
+ } catch (final EOFException e) {
+ assertEquals("0 char", 0, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test1CharInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR1)));
+ try {
+ reader.readUint8();
+ fail("1 char");
+ } catch (final EOFException e) {
+ assertEquals("1 char", 0, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test2CharsInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR2)));
+ try {
+ final int v1 = reader.readUint8();
+ assertEquals("2 chars pos 0", 'A', v1);
+ reader.readUint8();
+ fail("2 chars");
+ } catch (final EOFException e) {
+ assertEquals("2 chars", 1, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test3CharsInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR3)));
+ try {
+ final int v1 = reader.readUint8();
+ assertEquals("3 chars pos 0", 'A', v1);
+ final int v2 = reader.readUint8();
+ assertEquals("3 chars pos 1", 'B', v2);
+ reader.readUint8();
+ fail("3 chars");
+ } catch (final EOFException e) {
+ assertEquals("3 chars", 2, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test4CharsInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(COMPLETE_CHAR4)));
+ try {
+ final int v1 = reader.readUint8();
+ assertEquals("4 chars pos 0", 'A', v1);
+ final int v2 = reader.readUint8();
+ assertEquals("4 chars pos 1", 'B', v2);
+ final int v3 = reader.readUint8();
+ assertEquals("4 chars pos 2", 'C', v3);
+ reader.readUint8();
+ fail("4 chars");
+ } catch (final EOFException e) {
+ assertEquals("4 chars", 3, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void testAllBytePatternInt8() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(ALL_BYTE_PATTERN)));
+ try {
+ for (int i = 0; i <= 0xff; i++) {
+ final int v = reader.readUint8();
+ assertEquals("value: all byte pattern: pos " + i, i, v);
+ assertEquals("count: all byte pattern: pos " + i, i + 1, reader.getByteCount());
+ }
+ } catch (final EOFException e) {
+ assertEquals("all byte pattern", 256, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test0CharInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(EMPTY_STRING)));
+ try {
+ reader.readInt16();
+ fail("0 char");
+ } catch (final EOFException e) {
+ assertEquals("0 char", 0, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test1CharInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR1)));
+ try {
+ reader.readInt16();
+ fail("1 char");
+ } catch (final EOFException e) {
+ assertEquals("1 char", 0, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test2CharsInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR2)));
+ try {
+ reader.readInt16();
+ fail("2 chars");
+ } catch (final EOFException e) {
+ assertEquals("2 chars", 1, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test3CharsInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(INCOMPLETE_CHAR3)));
+ try {
+ final short v1 = reader.readInt16();
+ assertEquals("3 chars pos 0", 'A' << 8 | 'B', v1);
+ reader.readInt16();
+ fail("3 chars");
+ } catch (final EOFException e) {
+ assertEquals("3 chars", 2, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void test4CharsInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(COMPLETE_CHAR4)));
+ try {
+ final short v1 = reader.readInt16();
+ assertEquals("4 chars pos 0", 'A' << 8 | 'B', v1);
+ reader.readInt16();
+ fail("4 chars");
+ } catch (final EOFException e) {
+ assertEquals("4 chars", 3, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+
+ public void testAllBytePatternInt16() {
+ final Base64Reader reader = new Base64Reader(
+ new LineNumberReader(new StringReader(ALL_BYTE_PATTERN)));
+ try {
+ for (int i = 0; i <= 0xff; i += 2) {
+ final short v = reader.readInt16();
+ final short expected = (short)(i << 8 | (i + 1));
+ assertEquals("value: all byte pattern: pos " + i, expected, v);
+ assertEquals("count: all byte pattern: pos " + i, i + 2, reader.getByteCount());
+ }
+ } catch (final EOFException e) {
+ assertEquals("all byte pattern", 256, reader.getByteCount());
+ } catch (final IOException e) {
+ fail("IOException: " + e);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/CapsModeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
index 339791d57..cf3bdd680 100644
--- a/tests/src/com/android/inputmethod/latin/CapsModeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
diff --git a/tests/src/com/android/inputmethod/latin/utils/CsvUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CsvUtilsTests.java
new file mode 100644
index 000000000..a0fa8fe4b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/CsvUtilsTests.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.utils.CsvUtils.CsvParseException;
+
+import java.util.Arrays;
+
+@SmallTest
+public class CsvUtilsTests extends AndroidTestCase {
+ public void testUnescape() {
+ assertEquals("", CsvUtils.unescapeField(""));
+ assertEquals("text", CsvUtils.unescapeField("text")); // text
+ assertEquals("", CsvUtils.unescapeField("\"\"")); // ""
+ assertEquals("\"", CsvUtils.unescapeField("\"\"\"\"")); // """" -> "
+ assertEquals("text", CsvUtils.unescapeField("\"text\"")); // "text" -> text
+ assertEquals("\"text", CsvUtils.unescapeField("\"\"\"text\"")); // """text" -> "text
+ assertEquals("text\"", CsvUtils.unescapeField("\"text\"\"\"")); // "text""" -> text"
+ assertEquals("te\"xt", CsvUtils.unescapeField("\"te\"\"xt\"")); // "te""xt" -> te"xt
+ assertEquals("\"text\"",
+ CsvUtils.unescapeField("\"\"\"text\"\"\"")); // """text""" -> "text"
+ assertEquals("t\"e\"x\"t",
+ CsvUtils.unescapeField("\"t\"\"e\"\"x\"\"t\"")); // "t""e""x""t" -> t"e"x"t
+ }
+
+ public void testUnescapeException() {
+ try {
+ final String text = CsvUtils.unescapeField("\""); // "
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"\"\""); // """
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"\"\"\"\""); // """""
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"text"); // "text
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("text\""); // text"
+ fail("Raw quote in text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("te\"xt"); // te"xt
+ fail("Raw quote in text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"\"text"); // ""text
+ fail("Raw quote in quoted text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("text\"\""); // text""
+ fail("Escaped quote in text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Escaped quote in text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("te\"\"xt"); // te""xt
+ fail("Escaped quote in text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Escaped quote in text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"\"text\""); // ""text"
+ fail("Raw quote in quoted text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"text\"\""); // "text""
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"te\"xt\""); // "te"xt"
+ fail("Raw quote in quoted text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\"b,c"); // "b,c
+ fail("Unterminated quote: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String text = CsvUtils.unescapeField("\",\"a\""); // ","a"
+ fail("Raw quote in quoted text: text=" + text);
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ }
+
+ private static <T> void assertArrayEquals(final T[] expected, final T[] actual) {
+ if (expected == actual) {
+ return;
+ }
+ if (expected == null || actual == null) {
+ assertEquals(Arrays.toString(expected), Arrays.toString(actual));
+ return;
+ }
+ if (expected.length != actual.length) {
+ assertEquals("[length]", Arrays.toString(expected), Arrays.toString(actual));
+ return;
+ }
+ for (int i = 0; i < expected.length; i++) {
+ final T e = expected[i];
+ final T a = actual[i];
+ if (e == a) {
+ continue;
+ }
+ assertEquals("["+i+"]", expected[i], actual[i]);
+ }
+ }
+
+ public void testSplit() {
+ assertArrayEquals(new String[]{""}, CsvUtils.split(""));
+ assertArrayEquals(new String[]{" "}, CsvUtils.split(" "));
+ assertArrayEquals(new String[]{"text"}, CsvUtils.split("text"));
+ assertArrayEquals(new String[]{" a b "}, CsvUtils.split(" a b "));
+
+ assertArrayEquals(new String[]{"", ""}, CsvUtils.split(","));
+ assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(",,"));
+ assertArrayEquals(new String[]{" ", " "}, CsvUtils.split(" , "));
+ assertArrayEquals(new String[]{" ", " ", " "}, CsvUtils.split(" , , "));
+ assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split("a,b"));
+ assertArrayEquals(new String[]{" a ", " b "}, CsvUtils.split(" a , b "));
+
+ assertArrayEquals(new String[]{"text"},
+ CsvUtils.split("\"text\"")); // "text"
+ assertArrayEquals(new String[]{" text "},
+ CsvUtils.split("\" text \"")); // "_text_"
+
+ assertArrayEquals(new String[]{""},
+ CsvUtils.split("\"\"")); // ""
+ assertArrayEquals(new String[]{"\""},
+ CsvUtils.split("\"\"\"\"")); // """"
+ assertArrayEquals(new String[]{"", ""},
+ CsvUtils.split("\"\",\"\"")); // "",""
+ assertArrayEquals(new String[]{"\",\""},
+ CsvUtils.split("\"\"\",\"\"\"")); // ""","""
+ assertArrayEquals(new String[]{"\"", "\""},
+ CsvUtils.split("\"\"\"\",\"\"\"\"")); // """",""""
+ assertArrayEquals(new String[]{"\"", "\",\""},
+ CsvUtils.split("\"\"\"\",\"\"\",\"\"\"")); // """",""","""
+ assertArrayEquals(new String[]{"\",\"", "\""},
+ CsvUtils.split("\"\"\",\"\"\",\"\"\"\"")); // """,""",""""
+
+ assertArrayEquals(new String[]{" a ", " b , c "},
+ CsvUtils.split(" a ,\" b , c \"")); // _a_,"_b_,_c_"
+ assertArrayEquals(new String[]{" a ", " b , c ", " d "},
+ CsvUtils.split(" a ,\" b , c \", d ")); // _a_,"_b_,_c_",_d_
+ }
+
+ public void testSplitException() {
+ try {
+ final String[] fields = CsvUtils.split(" \"text\" "); // _"text"_
+ fail("Raw quote in text: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in text", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split(" \" text \" "); // _"_text_"_
+ fail("Raw quote in text: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in text", success.getMessage());
+ }
+
+ try {
+ final String[] fields = CsvUtils.split("a,\"b,"); // a,",b
+ fail("Unterminated quote: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split("a,\"\"\",b"); // a,""",b
+ fail("Unterminated quote: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split("a,\"\"\"\"\",b"); // a,""""",b
+ fail("Unterminated quote: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split("a,\"b,c"); // a,"b,c
+ fail("Unterminated quote: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Unterminated quote", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split("a,\",\"b,c"); // a,","b,c
+ fail("Raw quote in quoted text: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ try {
+ final String[] fields = CsvUtils.split("a,\",\"b\",\",c"); // a,","b",",c
+ fail("Raw quote in quoted text: fields=" + Arrays.toString(fields));
+ } catch (final CsvParseException success) {
+ assertEquals("Raw quote in quoted text", success.getMessage());
+ }
+ }
+
+ public void testSplitWithTrimSpaces() {
+ final int trimSpaces = CsvUtils.SPLIT_FLAGS_TRIM_SPACES;
+ assertArrayEquals(new String[]{""}, CsvUtils.split(trimSpaces, ""));
+ assertArrayEquals(new String[]{""}, CsvUtils.split(trimSpaces, " "));
+ assertArrayEquals(new String[]{"text"}, CsvUtils.split(trimSpaces, "text"));
+ assertArrayEquals(new String[]{"a b"}, CsvUtils.split(trimSpaces, " a b "));
+
+ assertArrayEquals(new String[]{"", ""}, CsvUtils.split(trimSpaces, ","));
+ assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(trimSpaces, ",,"));
+ assertArrayEquals(new String[]{"", ""}, CsvUtils.split(trimSpaces, " , "));
+ assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(trimSpaces, " , , "));
+ assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split(trimSpaces, "a,b"));
+ assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split(trimSpaces, " a , b "));
+
+ assertArrayEquals(new String[]{"text"},
+ CsvUtils.split(trimSpaces, "\"text\"")); // "text"
+ assertArrayEquals(new String[]{"text"},
+ CsvUtils.split(trimSpaces, " \"text\" ")); // _"text"_
+ assertArrayEquals(new String[]{" text "},
+ CsvUtils.split(trimSpaces, "\" text \"")); // "_text_"
+ assertArrayEquals(new String[]{" text "},
+ CsvUtils.split(trimSpaces, " \" text \" ")); // _"_text_"_
+ assertArrayEquals(new String[]{"a", "b"},
+ CsvUtils.split(trimSpaces, " \"a\" , \"b\" ")); // _"a"_,_"b"_
+
+ assertArrayEquals(new String[]{""},
+ CsvUtils.split(trimSpaces, " \"\" ")); // _""_
+ assertArrayEquals(new String[]{"\""},
+ CsvUtils.split(trimSpaces, " \"\"\"\" ")); // _""""_
+ assertArrayEquals(new String[]{"", ""},
+ CsvUtils.split(trimSpaces, " \"\" , \"\" ")); // _""_,_""_
+ assertArrayEquals(new String[]{"\" , \""},
+ CsvUtils.split(trimSpaces, " \"\"\" , \"\"\" ")); // _"""_,_"""_
+ assertArrayEquals(new String[]{"\"", "\""},
+ CsvUtils.split(trimSpaces, " \"\"\"\" , \"\"\"\" ")); // _""""_,_""""_
+ assertArrayEquals(new String[]{"\"", "\" , \""},
+ CsvUtils.split(trimSpaces, " \"\"\"\" , \"\"\" , \"\"\" ")); // _""""_,_"""_,_"""_
+ assertArrayEquals(new String[]{"\" , \"", "\""},
+ CsvUtils.split(trimSpaces, " \"\"\" , \"\"\" , \"\"\"\" ")); // _"""_,_"""_,_""""_
+
+ assertArrayEquals(new String[]{"a", " b , c "},
+ CsvUtils.split(trimSpaces, " a , \" b , c \" ")); // _a_,_"_b_,_c_"_
+ assertArrayEquals(new String[]{"a", " b , c ", "d"},
+ CsvUtils.split(trimSpaces, " a, \" b , c \" , d ")); // _a,_"_b_,_c_"_,_d_
+ }
+
+ public void testEscape() {
+ assertEquals("", CsvUtils.escapeField("", false));
+ assertEquals("plain", CsvUtils.escapeField("plain", false));
+ assertEquals(" ", CsvUtils.escapeField(" ", false));
+ assertEquals(" ", CsvUtils.escapeField(" ", false));
+ assertEquals("a space", CsvUtils.escapeField("a space", false));
+ assertEquals(" space-at-start", CsvUtils.escapeField(" space-at-start", false));
+ assertEquals("space-at-end ", CsvUtils.escapeField("space-at-end ", false));
+ assertEquals("a lot of spaces", CsvUtils.escapeField("a lot of spaces", false));
+ assertEquals("\",\"", CsvUtils.escapeField(",", false));
+ assertEquals("\",,\"", CsvUtils.escapeField(",,", false));
+ assertEquals("\"a,comma\"", CsvUtils.escapeField("a,comma", false));
+ assertEquals("\",comma-at-begin\"", CsvUtils.escapeField(",comma-at-begin", false));
+ assertEquals("\"comma-at-end,\"", CsvUtils.escapeField("comma-at-end,", false));
+ assertEquals("\",,a,lot,,,of,commas,,\"",
+ CsvUtils.escapeField(",,a,lot,,,of,commas,,", false));
+ assertEquals("\"a comma,and a space\"", CsvUtils.escapeField("a comma,and a space", false));
+ assertEquals("\"\"\"\"", CsvUtils.escapeField("\"", false)); // " -> """"
+ assertEquals("\"\"\"\"\"\"", CsvUtils.escapeField("\"\"", false)); // "" -> """"""
+ assertEquals("\"\"\"\"\"\"\"\"", CsvUtils.escapeField("\"\"\"", false)); // """ -> """"""""
+ assertEquals("\"\"\"text\"\"\"",
+ CsvUtils.escapeField("\"text\"", false)); // "text" -> """text"""
+ assertEquals("\"text has \"\" in middle\"",
+ CsvUtils.escapeField("text has \" in middle", false));
+ assertEquals("\"\"\"quote,at begin\"", CsvUtils.escapeField("\"quote,at begin", false));
+ assertEquals("\"quote at,end\"\"\"", CsvUtils.escapeField("quote at,end\"", false));
+ assertEquals("\"\"\"quote at begin\"", CsvUtils.escapeField("\"quote at begin", false));
+ assertEquals("\"quote at end\"\"\"", CsvUtils.escapeField("quote at end\"", false));
+ }
+
+ public void testEscapeWithAlwaysQuoted() {
+ assertEquals("\"\"", CsvUtils.escapeField("", true));
+ assertEquals("\"plain\"", CsvUtils.escapeField("plain", true));
+ assertEquals("\" \"", CsvUtils.escapeField(" ", true));
+ assertEquals("\" \"", CsvUtils.escapeField(" ", true));
+ assertEquals("\"a space\"", CsvUtils.escapeField("a space", true));
+ assertEquals("\" space-at-start\"", CsvUtils.escapeField(" space-at-start", true));
+ assertEquals("\"space-at-end \"", CsvUtils.escapeField("space-at-end ", true));
+ assertEquals("\"a lot of spaces\"", CsvUtils.escapeField("a lot of spaces", true));
+ assertEquals("\",\"", CsvUtils.escapeField(",", true));
+ assertEquals("\",,\"", CsvUtils.escapeField(",,", true));
+ assertEquals("\"a,comma\"", CsvUtils.escapeField("a,comma", true));
+ assertEquals("\",comma-at-begin\"", CsvUtils.escapeField(",comma-at-begin", true));
+ assertEquals("\"comma-at-end,\"", CsvUtils.escapeField("comma-at-end,", true));
+ assertEquals("\",,a,lot,,,of,commas,,\"",
+ CsvUtils.escapeField(",,a,lot,,,of,commas,,", true));
+ assertEquals("\"a comma,and a space\"", CsvUtils.escapeField("a comma,and a space", true));
+ assertEquals("\"\"\"\"", CsvUtils.escapeField("\"", true)); // " -> """"
+ assertEquals("\"\"\"\"\"\"", CsvUtils.escapeField("\"\"", true)); // "" -> """"""
+ assertEquals("\"\"\"\"\"\"\"\"", CsvUtils.escapeField("\"\"\"", true)); // """ -> """"""""
+ assertEquals("\"\"\"text\"\"\"",
+ CsvUtils.escapeField("\"text\"", true)); // "text" -> """text"""
+ assertEquals("\"text has \"\" in middle\"",
+ CsvUtils.escapeField("text has \" in middle", true));
+ assertEquals("\"\"\"quote,at begin\"", CsvUtils.escapeField("\"quote,at begin", true));
+ assertEquals("\"quote at,end\"\"\"", CsvUtils.escapeField("quote at,end\"", true));
+ assertEquals("\"\"\"quote at begin\"", CsvUtils.escapeField("\"quote at begin", true));
+ assertEquals("\"quote at end\"\"\"", CsvUtils.escapeField("quote at end\"", true));
+ }
+
+ public void testJoinWithoutColumnPositions() {
+ assertEquals("", CsvUtils.join());
+ assertEquals("", CsvUtils.join(""));
+ assertEquals(",", CsvUtils.join("", ""));
+
+ assertEquals("text, text,text ",
+ CsvUtils.join("text", " text", "text "));
+ assertEquals("\"\"\"\",\"\"\"\"\"\",\"\"\"text\"\"\"",
+ CsvUtils.join("\"", "\"\"", "\"text\""));
+ assertEquals("a b,\"c,d\",\"e\"\"f\"",
+ CsvUtils.join("a b", "c,d", "e\"f"));
+ }
+
+ public void testJoinWithoutColumnPositionsWithExtraSpace() {
+ final int extraSpace = CsvUtils.JOIN_FLAGS_EXTRA_SPACE;
+ assertEquals("", CsvUtils.join(extraSpace));
+ assertEquals("", CsvUtils.join(extraSpace, ""));
+ assertEquals(", ", CsvUtils.join(extraSpace, "", ""));
+
+ assertEquals("text, text, text ",
+ CsvUtils.join(extraSpace, "text", " text", "text "));
+ // ","","text" -> """","""""","""text"""
+ assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"",
+ CsvUtils.join(extraSpace, "\"", "\"\"", "\"text\""));
+ assertEquals("a b, \"c,d\", \"e\"\"f\"",
+ CsvUtils.join(extraSpace, "a b", "c,d", "e\"f"));
+ }
+
+ public void testJoinWithoutColumnPositionsWithExtraSpaceAndAlwaysQuoted() {
+ final int extrSpaceAndQuoted =
+ CsvUtils.JOIN_FLAGS_EXTRA_SPACE | CsvUtils.JOIN_FLAGS_ALWAYS_QUOTED;
+ assertEquals("", CsvUtils.join(extrSpaceAndQuoted));
+ assertEquals("\"\"", CsvUtils.join(extrSpaceAndQuoted, ""));
+ assertEquals("\"\", \"\"", CsvUtils.join(extrSpaceAndQuoted, "", ""));
+
+ assertEquals("\"text\", \" text\", \"text \"",
+ CsvUtils.join(extrSpaceAndQuoted, "text", " text", "text "));
+ // ","","text" -> """", """""", """text"""
+ assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"",
+ CsvUtils.join(extrSpaceAndQuoted, "\"", "\"\"", "\"text\""));
+ assertEquals("\"a b\", \"c,d\", \"e\"\"f\"",
+ CsvUtils.join(extrSpaceAndQuoted, "a b", "c,d", "e\"f"));
+ }
+
+ public void testJoinWithColumnPositions() {
+ final int noFlags = CsvUtils.JOIN_FLAGS_NONE;
+ assertEquals("", CsvUtils.join(noFlags, new int[]{}));
+ assertEquals(" ", CsvUtils.join(noFlags, new int[]{3}, ""));
+ assertEquals(" ,", CsvUtils.join(noFlags, new int[]{1}, "", ""));
+ assertEquals(", ", CsvUtils.join(noFlags, new int[]{0, 3}, "", ""));
+
+ assertEquals("text, text, text ",
+ CsvUtils.join(noFlags, new int[]{0, 8, 15}, "text", " text", "text "));
+ // ","","text" -> """", """""","""text"""
+ assertEquals("\"\"\"\", \"\"\"\"\"\",\"\"\"text\"\"\"",
+ CsvUtils.join(noFlags, new int[]{0, 8, 15}, "\"", "\"\"", "\"text\""));
+ assertEquals("a b, \"c,d\", \"e\"\"f\"",
+ CsvUtils.join(noFlags, new int[]{0, 8, 15}, "a b", "c,d", "e\"f"));
+ }
+
+ public void testJoinWithColumnPositionsWithExtraSpace() {
+ final int extraSpace = CsvUtils.JOIN_FLAGS_EXTRA_SPACE;
+ assertEquals("", CsvUtils.join(extraSpace, new int[]{}));
+ assertEquals(" ", CsvUtils.join(extraSpace, new int[]{3}, ""));
+ assertEquals(" , ", CsvUtils.join(extraSpace, new int[]{1}, "", ""));
+ assertEquals(", ", CsvUtils.join(extraSpace, new int[]{0, 3}, "", ""));
+
+ assertEquals("text, text, text ",
+ CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "text", " text", "text "));
+ // ","","text" -> """", """""", """text"""
+ assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"",
+ CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "\"", "\"\"", "\"text\""));
+ assertEquals("a b, \"c,d\", \"e\"\"f\"",
+ CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "a b", "c,d", "e\"f"));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ForgettingCurveTests.java b/tests/src/com/android/inputmethod/latin/utils/ForgettingCurveTests.java
index 3259312df..823bd5d7d 100644
--- a/tests/src/com/android/inputmethod/latin/ForgettingCurveTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ForgettingCurveTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
diff --git a/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java b/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java
new file mode 100644
index 000000000..e0755483c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Unit tests for PrioritizedSerialExecutor.
+ * TODO: Add more detailed tests to make use of priorities, etc.
+ */
+@MediumTest
+public class PrioritizedSerialExecutorTests extends AndroidTestCase {
+ private static final String TAG = PrioritizedSerialExecutorTests.class.getSimpleName();
+
+ private static final int NUM_OF_TASKS = 10;
+ private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500;
+
+ public void testExecute() {
+ final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor();
+ final AtomicInteger v = new AtomicInteger(0);
+ for (int i = 0; i < NUM_OF_TASKS; ++i) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ v.incrementAndGet();
+ }
+ });
+ }
+ try {
+ Thread.sleep(DELAY_FOR_WAITING_TASKS_MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Exception while sleeping.", e);
+ }
+
+ assertEquals(NUM_OF_TASKS, v.get());
+ }
+
+ public void testExecutePrioritized() {
+ final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor();
+ final AtomicInteger v = new AtomicInteger(0);
+ for (int i = 0; i < NUM_OF_TASKS; ++i) {
+ executor.executePrioritized(new Runnable() {
+ @Override
+ public void run() {
+ v.incrementAndGet();
+ }
+ });
+ }
+ try {
+ Thread.sleep(DELAY_FOR_WAITING_TASKS_MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Exception while sleeping.", e);
+ }
+
+ assertEquals(NUM_OF_TASKS, v.get());
+ }
+
+ public void testExecuteCombined() {
+ final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor();
+ final AtomicInteger v = new AtomicInteger(0);
+ for (int i = 0; i < NUM_OF_TASKS; ++i) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ v.incrementAndGet();
+ }
+ });
+ }
+
+ for (int i = 0; i < NUM_OF_TASKS; ++i) {
+ executor.executePrioritized(new Runnable() {
+ @Override
+ public void run() {
+ v.incrementAndGet();
+ }
+ });
+ }
+
+ try {
+ Thread.sleep(DELAY_FOR_WAITING_TASKS_MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Exception while sleeping.", e);
+ }
+
+ assertEquals(2 * NUM_OF_TASKS, v.get());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
index 9d7203e5a..a52041264 100644
--- a/tests/src/com/android/inputmethod/latin/RecapitalizeStatusTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
diff --git a/tests/src/com/android/inputmethod/latin/ResizableIntArrayTests.java b/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
index b9fee950e..cad80d5ce 100644
--- a/tests/src/com/android/inputmethod/latin/ResizableIntArrayTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -340,4 +340,18 @@ public class ResizableIntArrayTests extends AndroidTestCase {
expecteds[i + expectedPos], actuals[i + actualPos]);
}
}
+
+ public void testShift() {
+ final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+ final int limit = DEFAULT_CAPACITY * 10;
+ final int shiftAmount = 20;
+ for (int i = 0; i < limit; ++i) {
+ src.add(i, i);
+ assertEquals("length after add at " + i, i + 1, src.getLength());
+ }
+ src.shift(shiftAmount);
+ for (int i = 0; i < limit - shiftAmount; ++i) {
+ assertEquals("value at " + i, i + shiftAmount, src.get(i));
+ }
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ResourceUtilsTests.java
index c915522ee..1ae22e307 100644
--- a/tests/src/com/android/inputmethod/latin/ResourceUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ResourceUtilsTests.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.inputmethod.latin.ResourceUtils.DeviceOverridePatternSyntaxError;
+import com.android.inputmethod.latin.utils.ResourceUtils.DeviceOverridePatternSyntaxError;
import java.util.HashMap;
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
new file mode 100644
index 000000000..fa6ad16c1
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.style.SuggestionSpan;
+import android.text.style.URLSpan;
+import android.text.SpannableStringBuilder;
+import android.text.Spannable;
+import android.text.Spanned;
+
+@SmallTest
+public class SpannableStringUtilsTests extends AndroidTestCase {
+ public void testConcatWithSuggestionSpansOnly() {
+ SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n"
+ + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n"
+ + "test string\ntest string\n");
+ final int N = 10;
+ for (int i = 0; i < N; ++i) {
+ // Put a PARAGRAPH-flagged span that should not be found in the result.
+ s.setSpan(new SuggestionSpan(getContext(),
+ new String[] {"" + i}, Spannable.SPAN_PARAGRAPH),
+ i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH);
+ // Put a normal suggestion span that should be found in the result.
+ s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0);
+ // Put a URL span than should not be found in the result.
+ s.setSpan(new URLSpan("http://a"), i, i * 2, 0);
+ }
+
+ final CharSequence a = s.subSequence(0, 15);
+ final CharSequence b = s.subSequence(15, s.length());
+ final Spanned result =
+ (Spanned)SpannableStringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b);
+
+ Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class);
+ for (int i = 0; i < spans.length; i++) {
+ final int flags = result.getSpanFlags(spans[i]);
+ assertEquals("Should not find a span with PARAGRAPH flag",
+ flags & Spannable.SPAN_PARAGRAPH, 0);
+ assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
index 4f260987b..4e396a1cf 100644
--- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
@@ -14,11 +14,15 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
+
+import com.android.inputmethod.latin.settings.SettingsValues;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
@SmallTest
@@ -183,6 +187,18 @@ public class StringUtilsTests extends AndroidTestCase {
assertTrue(StringUtils.isIdenticalAfterDowncase(""));
}
+ public void testLooksValidForDictionaryInsertion() {
+ final SettingsValues settings =
+ SettingsValues.makeDummySettingsValuesForTest(Locale.ENGLISH);
+ assertTrue(StringUtils.looksValidForDictionaryInsertion("aochaueo", settings));
+ assertFalse(StringUtils.looksValidForDictionaryInsertion("", settings));
+ assertTrue(StringUtils.looksValidForDictionaryInsertion("ao-ch'aueo", settings));
+ assertFalse(StringUtils.looksValidForDictionaryInsertion("2908743256", settings));
+ assertTrue(StringUtils.looksValidForDictionaryInsertion("31aochaueo", settings));
+ assertFalse(StringUtils.looksValidForDictionaryInsertion("akeo raeoch oerch .", settings));
+ assertFalse(StringUtils.looksValidForDictionaryInsertion("!!!", settings));
+ }
+
private static void checkCapitalize(final String src, final String dst, final String separators,
final Locale locale) {
assertEquals(dst, StringUtils.capitalizeEachWord(src, separators, locale));
@@ -242,4 +258,26 @@ public class StringUtilsTests extends AndroidTestCase {
// code for now True is acceptable.
assertTrue(StringUtils.lastPartLooksLikeURL(".abc/def"));
}
+
+ public void testHexStringUtils() {
+ final byte[] bytes = new byte[] { (byte)0x01, (byte)0x11, (byte)0x22, (byte)0x33,
+ (byte)0x55, (byte)0x88, (byte)0xEE };
+ final String bytesStr = StringUtils.byteArrayToHexString(bytes);
+ final byte[] bytes2 = StringUtils.hexStringToByteArray(bytesStr);
+ for (int i = 0; i < bytes.length; ++i) {
+ assertTrue(bytes[i] == bytes2[i]);
+ }
+ final String bytesStr2 = StringUtils.byteArrayToHexString(bytes2);
+ assertTrue(bytesStr.equals(bytesStr2));
+ }
+
+ public void testJsonStringUtils() {
+ final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
+ final List<Object> objArray = Arrays.asList(objs);
+ final String str = StringUtils.listToJsonStr(objArray);
+ final List<Object> newObjArray = StringUtils.jsonStrToList(str);
+ for (int i = 0; i < objs.length; ++i) {
+ assertEquals(objs[i], newObjArray.get(i));
+ }
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
new file mode 100644
index 000000000..856b2dbda
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -0,0 +1,387 @@
+/*
+ * 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.utils;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+@SmallTest
+public class SubtypeLocaleUtilsTests extends AndroidTestCase {
+ // Locale to subtypes list.
+ private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList();
+
+ private RichInputMethodManager mRichImm;
+ private Resources mRes;
+
+ InputMethodSubtype EN_US;
+ InputMethodSubtype EN_GB;
+ InputMethodSubtype ES_US;
+ InputMethodSubtype FR;
+ InputMethodSubtype FR_CA;
+ InputMethodSubtype DE;
+ InputMethodSubtype ZZ;
+ InputMethodSubtype DE_QWERTY;
+ InputMethodSubtype FR_QWERTZ;
+ InputMethodSubtype EN_US_AZERTY;
+ InputMethodSubtype EN_UK_DVORAK;
+ InputMethodSubtype ES_US_COLEMAK;
+ InputMethodSubtype ZZ_AZERTY;
+ InputMethodSubtype ZZ_PC;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Context context = getContext();
+ RichInputMethodManager.init(context);
+ mRichImm = RichInputMethodManager.getInstance();
+ mRes = context.getResources();
+ SubtypeLocaleUtils.init(context);
+
+ EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.US.toString(), "qwerty");
+ EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.UK.toString(), "qwerty");
+ ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "es_US", "spanish");
+ FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.FRENCH.toString(), "azerty");
+ FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.CANADA_FRENCH.toString(), "qwerty");
+ DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.GERMAN.toString(), "qwertz");
+ ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
+ DE_QWERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.GERMAN.toString(), "qwerty", null);
+ FR_QWERTZ = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.FRENCH.toString(), "qwertz", null);
+ EN_US_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.US.toString(), "azerty", null);
+ EN_UK_DVORAK = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.UK.toString(), "dvorak", null);
+ ES_US_COLEMAK = AdditionalSubtypeUtils.createAdditionalSubtype(
+ "es_US", "colemak", null);
+ ZZ_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "azerty", null);
+ ZZ_PC = AdditionalSubtypeUtils.createAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty", null);
+
+ }
+
+ public void testAllFullDisplayName() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName =
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ final String noLanguage = mRes.getString(R.string.subtype_no_language);
+ assertTrue(subtypeName, subtypeName.contains(noLanguage));
+ } else {
+ final String languageName =
+ SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale());
+ assertTrue(subtypeName, subtypeName.contains(languageName));
+ }
+ }
+ }
+
+ public void testKeyboardLayoutSetName() {
+ assertEquals("en_US", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US));
+ assertEquals("en_GB", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_GB));
+ assertEquals("es_US", "spanish", SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US));
+ assertEquals("fr ", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR));
+ assertEquals("fr_CA", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CA));
+ assertEquals("de ", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
+ assertEquals("zz ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
+ }
+
+ // InputMethodSubtype's display name in system locale (en_US).
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | display name
+ // ------ ------- - ----------------------
+ // en_US qwerty F English (US) exception
+ // en_GB qwerty F English (UK) exception
+ // es_US spanish F Spanish (US) exception
+ // fr azerty F French
+ // fr_CA qwerty F French (Canada)
+ // de qwertz F German
+ // zz qwerty F Alphabet (QWERTY)
+ // fr qwertz T French (QWERTZ)
+ // de qwerty T German (QWERTY)
+ // en_US azerty T English (US) (AZERTY) exception
+ // en_UK dvorak T English (UK) (Dvorak) exception
+ // es_US colemak T Spanish (US) (Colemak) exception
+ // zz pc T Alphabet (PC)
+
+ public void testPredefinedSubtypesInEnglishSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("en_US", "English (US)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US));
+ assertEquals("en_GB", "English (UK)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB));
+ assertEquals("es_US", "Spanish (US)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US));
+ assertEquals("fr ", "French",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
+ assertEquals("fr_CA", "French (Canada)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
+ assertEquals("de ", "German",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
+ assertEquals("zz ", "Alphabet (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ public void testAdditionalSubtypesInEnglishSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("fr qwertz", "French (QWERTZ)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
+ assertEquals("de qwerty", "German (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
+ assertEquals("en_US azerty", "English (US) (AZERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
+ assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
+ assertEquals("es_US colemak","Spanish (US) (Colemak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
+ assertEquals("zz pc", "Alphabet (PC)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ // InputMethodSubtype's display name in system locale (fr).
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | display name
+ // ------ ------- - ----------------------
+ // en_US qwerty F Anglais (États-Unis) exception
+ // en_GB qwerty F Anglais (Royaume-Uni) exception
+ // es_US spanish F Espagnol (États-Unis) exception
+ // fr azerty F Français
+ // fr_CA qwerty F Français (Canada)
+ // de qwertz F Allemand
+ // zz qwerty F Aucune langue (QWERTY)
+ // fr qwertz T Français (QWERTZ)
+ // de qwerty T Allemand (QWERTY)
+ // en_US azerty T Anglais (États-Unis) (AZERTY) exception
+ // en_UK dvorak T Anglais (Royaume-Uni) (Dvorak) exception
+ // es_US colemak T Espagnol (États-Unis) (Colemak) exception
+ // zz pc T Alphabet (PC)
+
+ public void testPredefinedSubtypesInFrenchSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("en_US", "Anglais (États-Unis)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US));
+ assertEquals("en_GB", "Anglais (Royaume-Uni)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB));
+ assertEquals("es_US", "Espagnol (États-Unis)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US));
+ assertEquals("fr ", "Français",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
+ assertEquals("fr_CA", "Français (Canada)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
+ assertEquals("de ", "Allemand",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
+ assertEquals("zz ", "Alphabet latin (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, Locale.FRENCH);
+ }
+
+ public void testAdditionalSubtypesInFrenchSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("fr qwertz", "Français (QWERTZ)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
+ assertEquals("de qwerty", "Allemand (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
+ assertEquals("en_US azerty", "Anglais (États-Unis) (AZERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
+ assertEquals("en_UK dvorak", "Anglais (Royaume-Uni) (Dvorak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
+ assertEquals("es_US colemak","Espagnol (États-Unis) (Colemak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
+ assertEquals("zz pc", "Alphabet latin (PC)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, Locale.FRENCH);
+ }
+
+ public void testAllFullDisplayNameForSpacebar() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName =
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
+ final String spacebarText = SubtypeLocaleUtils.getFullDisplayName(subtype);
+ final String languageName =
+ SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale());
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ assertFalse(subtypeName, spacebarText.contains(languageName));
+ } else {
+ assertTrue(subtypeName, spacebarText.contains(languageName));
+ }
+ }
+ }
+
+ public void testAllMiddleDisplayNameForSpacebar() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName =
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
+ final String spacebarText = SubtypeLocaleUtils.getMiddleDisplayName(subtype);
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ assertEquals(subtypeName,
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype), spacebarText);
+ } else {
+ assertEquals(subtypeName,
+ SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale()),
+ spacebarText);
+ }
+ }
+ }
+
+ public void testAllShortDisplayNameForSpacebar() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName =
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
+ final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
+ final String spacebarText = SubtypeLocaleUtils.getShortDisplayName(subtype);
+ final String languageCode = StringUtils.capitalizeFirstCodePoint(
+ locale.getLanguage(), locale);
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ assertEquals(subtypeName, "", spacebarText);
+ } else {
+ assertEquals(subtypeName, languageCode, spacebarText);
+ }
+ }
+ }
+
+ // InputMethodSubtype's display name for spacebar text in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | Short Middle Full
+ // ------ ------- - ---- --------- ----------------------
+ // en_US qwerty F En English English (US) exception
+ // en_GB qwerty F En English English (UK) exception
+ // es_US spanish F Es Español Español (EE.UU.) exception
+ // fr azerty F Fr Français Français
+ // fr_CA qwerty F Fr Français Français (Canada)
+ // de qwertz F De Deutsch Deutsch
+ // zz qwerty F QWERTY QWERTY
+ // fr qwertz T Fr Français Français
+ // de qwerty T De Deutsch Deutsch
+ // en_US azerty T En English English (US)
+ // zz azerty T AZERTY AZERTY
+
+ private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("en_US", "English (US)", SubtypeLocaleUtils.getFullDisplayName(EN_US));
+ assertEquals("en_GB", "English (UK)", SubtypeLocaleUtils.getFullDisplayName(EN_GB));
+ assertEquals("es_US", "Español (EE.UU.)",
+ SubtypeLocaleUtils.getFullDisplayName(ES_US));
+ assertEquals("fr ", "Français", SubtypeLocaleUtils.getFullDisplayName(FR));
+ assertEquals("fr_CA", "Français (Canada)",
+ SubtypeLocaleUtils.getFullDisplayName(FR_CA));
+ assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getFullDisplayName(DE));
+ assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getFullDisplayName(ZZ));
+
+ assertEquals("en_US", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_US));
+ assertEquals("en_GB", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_GB));
+ assertEquals("es_US", "Español", SubtypeLocaleUtils.getMiddleDisplayName(ES_US));
+ assertEquals("fr ", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR));
+ assertEquals("fr_CA", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CA));
+ assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE));
+ assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ));
+
+ assertEquals("en_US", "En", SubtypeLocaleUtils.getShortDisplayName(EN_US));
+ assertEquals("en_GB", "En", SubtypeLocaleUtils.getShortDisplayName(EN_GB));
+ assertEquals("es_US", "Es", SubtypeLocaleUtils.getShortDisplayName(ES_US));
+ assertEquals("fr ", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR));
+ assertEquals("fr_CA", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_CA));
+ assertEquals("de ", "De", SubtypeLocaleUtils.getShortDisplayName(DE));
+ assertEquals("zz ", "", SubtypeLocaleUtils.getShortDisplayName(ZZ));
+ return null;
+ }
+ };
+
+ private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("fr qwertz", "Français",
+ SubtypeLocaleUtils.getFullDisplayName(FR_QWERTZ));
+ assertEquals("de qwerty", "Deutsch",
+ SubtypeLocaleUtils.getFullDisplayName(DE_QWERTY));
+ assertEquals("en_US azerty", "English (US)",
+ SubtypeLocaleUtils.getFullDisplayName(EN_US_AZERTY));
+ assertEquals("zz azerty", "AZERTY",
+ SubtypeLocaleUtils.getFullDisplayName(ZZ_AZERTY));
+
+ assertEquals("fr qwertz", "Français",
+ SubtypeLocaleUtils.getMiddleDisplayName(FR_QWERTZ));
+ assertEquals("de qwerty", "Deutsch",
+ SubtypeLocaleUtils.getMiddleDisplayName(DE_QWERTY));
+ assertEquals("en_US azerty", "English",
+ SubtypeLocaleUtils.getMiddleDisplayName(EN_US_AZERTY));
+ assertEquals("zz azerty", "AZERTY",
+ SubtypeLocaleUtils.getMiddleDisplayName(ZZ_AZERTY));
+
+ assertEquals("fr qwertz", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_QWERTZ));
+ assertEquals("de qwerty", "De", SubtypeLocaleUtils.getShortDisplayName(DE_QWERTY));
+ assertEquals("en_US azerty", "En",
+ SubtypeLocaleUtils.getShortDisplayName(EN_US_AZERTY));
+ assertEquals("zz azerty", "", SubtypeLocaleUtils.getShortDisplayName(ZZ_AZERTY));
+ return null;
+ }
+ };
+
+ public void testPredefinedSubtypesForSpacebarInEnglish() {
+ testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ public void testAdditionalSubtypeForSpacebarInEnglish() {
+ testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ public void testPredefinedSubtypesForSpacebarInFrench() {
+ testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+ }
+
+ public void testAdditionalSubtypeForSpacebarInFrench() {
+ testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java
index 211d012d2..3eabe2b3c 100644
--- a/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java
@@ -14,23 +14,26 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import android.content.Context;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
-import com.android.inputmethod.latin.UserHistoryDictIOUtils.BigramDictionaryInterface;
-import com.android.inputmethod.latin.UserHistoryDictIOUtils.OnAddWordListener;
+import com.android.inputmethod.latin.makedict.DictDecoder;
+import com.android.inputmethod.latin.makedict.DictEncoder;
import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
+import com.android.inputmethod.latin.makedict.Ver3DictDecoder;
+import com.android.inputmethod.latin.makedict.Ver3DictEncoder;
+import com.android.inputmethod.latin.personalization.UserHistoryDictionaryBigramList;
+import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.BigramDictionaryInterface;
+import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.OnAddWordListener;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -48,6 +51,7 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
private static final int BIGRAM_FREQUENCY = 100;
private static final ArrayList<String> NOT_HAVE_BIGRAM = new ArrayList<String>();
private static final FormatSpec.FormatOptions FORMAT_OPTIONS = new FormatSpec.FormatOptions(2);
+ private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
/**
* Return same frequency for all words and bigrams
@@ -85,12 +89,12 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
private void checkWordInFusionDict(final FusionDictionary dict, final String word,
final ArrayList<String> expectedBigrams) {
- final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, word);
- assertNotNull(group);
- assertTrue(group.isTerminal());
+ final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
+ assertNotNull(ptNode);
+ assertTrue(ptNode.isTerminal());
for (final String bigram : expectedBigrams) {
- assertNotNull(group.getBigram(bigram));
+ assertNotNull(ptNode.getBigram(bigram));
}
}
@@ -134,39 +138,20 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
private void writeDictToFile(final File file,
final UserHistoryDictionaryBigramList bigramList) {
- try {
- final FileOutputStream out = new FileOutputStream(file);
- UserHistoryDictIOUtils.writeDictionaryBinary(out, this, bigramList, FORMAT_OPTIONS);
- out.flush();
- out.close();
- } catch (IOException e) {
- Log.e(TAG, "IO exception while writing file", e);
- }
+ final DictEncoder dictEncoder = new Ver3DictEncoder(file);
+ UserHistoryDictIOUtils.writeDictionary(dictEncoder, this, bigramList, FORMAT_OPTIONS);
}
private void readDictFromFile(final File file, final OnAddWordListener listener) {
- FileInputStream inStream = null;
-
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, DictDecoder.USE_BYTEARRAY);
try {
- inStream = new FileInputStream(file);
- final byte[] buffer = new byte[(int)file.length()];
- inStream.read(buffer);
-
- UserHistoryDictIOUtils.readDictionaryBinary(
- new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener);
+ dictDecoder.openDictBuffer();
} catch (FileNotFoundException e) {
Log.e(TAG, "file not found", e);
} catch (IOException e) {
Log.e(TAG, "IOException", e);
- } finally {
- if (inStream != null) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
+ UserHistoryDictIOUtils.readDictionaryBinary(dictDecoder, listener);
}
public void testGenerateFusionDictionary() {
@@ -189,7 +174,8 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
File file = null;
try {
- file = File.createTempFile("testReadAndWrite", ".dict", getContext().getCacheDir());
+ file = File.createTempFile("testReadAndWrite", TEST_DICT_FILE_EXTENSION,
+ getContext().getCacheDir());
} catch (IOException e) {
Log.d(TAG, "IOException while creating a temporary file", e);
}