aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/com/android/inputmethod/latin')
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java692
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java1014
-rw-r--r--tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java29
-rw-r--r--tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java94
-rw-r--r--tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java61
-rw-r--r--tests/src/com/android/inputmethod/latin/ContactsManagerTest.java127
-rw-r--r--tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java42
-rw-r--r--tests/src/com/android/inputmethod/latin/DistracterFilterTest.java197
-rw-r--r--tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java52
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java359
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java216
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java34
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java124
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java237
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java146
-rw-r--r--tests/src/com/android/inputmethod/latin/LatinIMEForTests.java12
-rw-r--r--tests/src/com/android/inputmethod/latin/LatinImeStressTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/LatinImeTests.java40
-rw-r--r--tests/src/com/android/inputmethod/latin/NgramContextTests.java145
-rw-r--r--tests/src/com/android/inputmethod/latin/PunctuationTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java102
-rw-r--r--tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java318
-rw-r--r--tests/src/com/android/inputmethod/latin/ShiftModeTests.java6
-rw-r--r--tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java94
-rw-r--r--tests/src/com/android/inputmethod/latin/WordComposerTests.java5
-rw-r--r--tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java112
-rw-r--r--tests/src/com/android/inputmethod/latin/common/InputPointersTests.java (renamed from tests/src/com/android/inputmethod/latin/InputPointersTests.java)4
-rw-r--r--tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java (renamed from tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java)8
-rw-r--r--tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java (renamed from tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java)352
-rw-r--r--tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java36
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java696
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java107
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java249
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java24
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java78
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java101
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java5
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java182
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java321
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java150
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java240
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java24
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java150
-rw-r--r--tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java168
-rw-r--r--tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java154
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java75
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java117
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java264
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java144
-rw-r--r--tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java171
-rw-r--r--tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java11
-rw-r--r--tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java10
-rw-r--r--tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java279
-rw-r--r--tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java47
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java25
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java4
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java92
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java26
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java87
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java18
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java99
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java6
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java72
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java36
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java215
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java251
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java176
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java192
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java261
70 files changed, 4271 insertions, 5720 deletions
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
deleted file mode 100644
index ae184268c..000000000
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * 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.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
-import com.android.inputmethod.latin.makedict.DictDecoder;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.makedict.FormatSpec;
-import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-
-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;
-import java.util.concurrent.TimeUnit;
-
-@LargeTest
-public class BinaryDictionaryDecayingTests extends AndroidTestCase {
- private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
- private static final String TEST_LOCALE = "test";
- private static final int DUMMY_PROBABILITY = 0;
- private static final int[] DICT_FORMAT_VERSIONS =
- new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
-
- private int mCurrentTime = 0;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mCurrentTime = 0;
- }
-
- @Override
- protected void tearDown() throws Exception {
- stopTestModeInNativeCode();
- super.tearDown();
- }
-
- private static boolean supportsBeginningOfSentence(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
- }
-
- private void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
- final int probability) {
- binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
- BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
- false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, mCurrentTime /* timestamp */);
- }
-
- private void addBigramWords(final BinaryDictionary binaryDictionary, final String word0,
- final String word1, final int probability) {
- binaryDictionary.addNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1, probability,
- mCurrentTime /* timestamp */);
- }
-
- private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
- final String word0, final String word1) {
- return binaryDictionary.isValidNgram(new PrevWordsInfo(new WordInfo(word0)), word1);
- }
-
- private void forcePassingShortTime(final BinaryDictionary binaryDictionary) {
- // 30 days.
- final int timeToElapse = (int)TimeUnit.SECONDS.convert(30, TimeUnit.DAYS);
- mCurrentTime += timeToElapse;
- setCurrentTimeForTestMode(mCurrentTime);
- binaryDictionary.flushWithGC();
- }
-
- private void forcePassingLongTime(final BinaryDictionary binaryDictionary) {
- // 365 days.
- final int timeToElapse = (int)TimeUnit.SECONDS.convert(365, TimeUnit.DAYS);
- mCurrentTime += timeToElapse;
- setCurrentTimeForTestMode(mCurrentTime);
- binaryDictionary.flushWithGC();
- }
-
- private File createEmptyDictionaryAndGetFile(final String dictId,
- final int formatVersion) throws IOException {
- if (formatVersion == FormatSpec.VERSION4
- || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
- || formatVersion == FormatSpec.VERSION4_DEV) {
- return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
- } else {
- throw new IOException("Dictionary format version " + formatVersion
- + " is not supported.");
- }
- }
-
- private File createEmptyVer4DictionaryAndGetFile(final String dictId, final int formatVersion)
- throws IOException {
- final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
- getContext().getCacheDir());
- FileUtils.deleteRecursively(file);
- Map<String, String> attributeMap = new HashMap<>();
- attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId);
- attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
- String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
- attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
- LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
- return file;
- } else {
- throw new IOException("Empty dictionary " + file.getAbsolutePath()
- + " cannot be created. Foramt version: " + formatVersion);
- }
- }
-
- private static int setCurrentTimeForTestMode(final int currentTime) {
- return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime);
- }
-
- private static int stopTestModeInNativeCode() {
- return BinaryDictionaryUtils.setCurrentTimeForTest(-1);
- }
-
- public void testReadDictInJavaSide() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testReadDictInJavaSide(formatVersion);
- }
- }
-
- private void testReadDictInJavaSide(final int formatVersion) {
- setCurrentTimeForTestMode(mCurrentTime);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "ab", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "aaa", DUMMY_PROBABILITY);
- binaryDictionary.flushWithGC();
- binaryDictionary.close();
-
- final DictDecoder dictDecoder =
- BinaryDictIOUtils.getDictDecoder(dictFile, 0, dictFile.length());
- try {
- final FusionDictionary dict =
- dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
- PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "a");
- assertNotNull(ptNode);
- assertTrue(ptNode.isTerminal());
- assertNotNull(ptNode.getBigram("aaa"));
- ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "ab");
- assertNotNull(ptNode);
- assertTrue(ptNode.isTerminal());
- ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa");
- assertNotNull(ptNode);
- assertTrue(ptNode.isTerminal());
- } catch (IOException e) {
- fail("IOException while reading dictionary: " + e);
- } catch (UnsupportedFormatException e) {
- fail("Unsupported format: " + e);
- }
- dictFile.delete();
- }
-
- public void testControlCurrentTime() {
- final int TEST_COUNT = 1000;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
- final int startTime = stopTestModeInNativeCode();
- for (int i = 0; i < TEST_COUNT; i++) {
- final int currentTime = random.nextInt(Integer.MAX_VALUE);
- final int currentTimeInNativeCode = setCurrentTimeForTestMode(currentTime);
- assertEquals(currentTime, currentTimeInNativeCode);
- }
- final int endTime = stopTestModeInNativeCode();
- final int MAX_ALLOWED_ELAPSED_TIME = 10;
- assertTrue(startTime <= endTime && endTime <= startTime + MAX_ALLOWED_ELAPSED_TIME);
- }
-
- public void testAddValidAndInvalidWords() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddValidAndInvalidWords(formatVersion);
- }
- }
-
- private void testAddValidAndInvalidWords(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
-
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
- assertFalse(binaryDictionary.isValidWord("a"));
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("a"));
-
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("b"));
-
- addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
- assertFalse(isValidBigram(binaryDictionary, "a", "b"));
- addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "a", "b"));
-
- addUnigramWord(binaryDictionary, "c", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "c", DUMMY_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "a", "c"));
-
- // Add bigrams of not valid unigrams.
- addBigramWords(binaryDictionary, "x", "y", Dictionary.NOT_A_PROBABILITY);
- assertFalse(isValidBigram(binaryDictionary, "x", "y"));
- addBigramWords(binaryDictionary, "x", "y", DUMMY_PROBABILITY);
- assertFalse(isValidBigram(binaryDictionary, "x", "y"));
-
- binaryDictionary.close();
- dictFile.delete();
- }
-
- public void testDecayingProbability() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testDecayingProbability(formatVersion);
- }
- }
-
- private void testDecayingProbability(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
-
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("a"));
- forcePassingShortTime(binaryDictionary);
- assertFalse(binaryDictionary.isValidWord("a"));
-
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("a"));
- forcePassingShortTime(binaryDictionary);
- assertTrue(binaryDictionary.isValidWord("a"));
- forcePassingLongTime(binaryDictionary);
- assertFalse(binaryDictionary.isValidWord("a"));
-
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "a", "b"));
- forcePassingShortTime(binaryDictionary);
- assertFalse(isValidBigram(binaryDictionary, "a", "b"));
-
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "a", "b"));
- forcePassingShortTime(binaryDictionary);
- assertTrue(isValidBigram(binaryDictionary, "a", "b"));
- forcePassingLongTime(binaryDictionary);
- assertFalse(isValidBigram(binaryDictionary, "a", "b"));
-
- binaryDictionary.close();
- dictFile.delete();
- }
-
- public void testAddManyUnigramsToDecayingDict() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddManyUnigramsToDecayingDict(formatVersion);
- }
- }
-
- private void testAddManyUnigramsToDecayingDict(final int formatVersion) {
- final int unigramCount = 30000;
- final int unigramTypedCount = 100000;
- final int codePointSetSize = 50;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
- setCurrentTimeForTestMode(mCurrentTime);
-
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
- final ArrayList<String> words = new ArrayList<>();
-
- for (int i = 0; i < unigramCount; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- words.add(word);
- }
-
- final int maxUnigramCount = Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
- for (int i = 0; i < unigramTypedCount; i++) {
- final String word = words.get(random.nextInt(words.size()));
- addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
-
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- final int unigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY));
- while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- forcePassingShortTime(binaryDictionary);
- }
- final int unigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY));
- assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
- }
- }
-
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY)) > 0);
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY)) <= maxUnigramCount);
- forcePassingLongTime(binaryDictionary);
- assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY)));
- }
-
- public void testOverflowUnigrams() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testOverflowUnigrams(formatVersion);
- }
- }
-
- private void testOverflowUnigrams(final int formatVersion) {
- final int unigramCount = 20000;
- final int eachUnigramTypedCount = 2;
- final int strongUnigramTypedCount = 20;
- final int weakUnigramTypedCount = 1;
- final int codePointSetSize = 50;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
- setCurrentTimeForTestMode(mCurrentTime);
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
- final String strong = "strong";
- final String weak = "weak";
- for (int j = 0; j < strongUnigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, strong, DUMMY_PROBABILITY);
- }
- for (int j = 0; j < weakUnigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, weak, DUMMY_PROBABILITY);
- }
- assertTrue(binaryDictionary.isValidWord(strong));
- assertTrue(binaryDictionary.isValidWord(weak));
-
- for (int i = 0; i < unigramCount; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- for (int j = 0; j < eachUnigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
- }
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- final int unigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY));
- assertTrue(binaryDictionary.isValidWord(strong));
- assertTrue(binaryDictionary.isValidWord(weak));
- binaryDictionary.flushWithGC();
- final int unigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.UNIGRAM_COUNT_QUERY));
- assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
- assertFalse(binaryDictionary.isValidWord(weak));
- assertTrue(binaryDictionary.isValidWord(strong));
- break;
- }
- }
- }
-
- public void testAddManyBigramsToDecayingDict() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddManyBigramsToDecayingDict(formatVersion);
- }
- }
-
- private void testAddManyBigramsToDecayingDict(final int formatVersion) {
- final int unigramCount = 5000;
- final int bigramCount = 30000;
- final int bigramTypedCount = 100000;
- final int codePointSetSize = 50;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
- setCurrentTimeForTestMode(mCurrentTime);
-
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
- final ArrayList<String> words = new ArrayList<>();
- final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
-
- for (int i = 0; i < unigramCount; ++i) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- words.add(word);
- }
- for (int i = 0; i < bigramCount; ++i) {
- final int word0Index = random.nextInt(words.size());
- int word1Index = random.nextInt(words.size() - 1);
- if (word1Index >= word0Index) {
- word1Index += 1;
- }
- final String word0 = words.get(word0Index);
- final String word1 = words.get(word1Index);
- final Pair<String, String> bigram = new Pair<>(word0, word1);
- bigrams.add(bigram);
- }
-
- final int maxBigramCount = Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.MAX_BIGRAM_COUNT_QUERY));
- for (int i = 0; i < bigramTypedCount; ++i) {
- final Pair<String, String> bigram = bigrams.get(random.nextInt(bigrams.size()));
- addUnigramWord(binaryDictionary, bigram.first, DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, bigram.second, DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, bigram.first, bigram.second, DUMMY_PROBABILITY);
-
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- final int bigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY));
- while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- forcePassingShortTime(binaryDictionary);
- }
- final int bigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY));
- assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
- }
- }
-
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY)) > 0);
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY)) <= maxBigramCount);
- forcePassingLongTime(binaryDictionary);
- assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY)));
- }
-
- public void testOverflowBigrams() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testOverflowBigrams(formatVersion);
- }
- }
-
- private void testOverflowBigrams(final int formatVersion) {
- final int bigramCount = 20000;
- final int unigramCount = 1000;
- final int unigramTypedCount = 20;
- final int eachBigramTypedCount = 2;
- final int strongBigramTypedCount = 20;
- final int weakBigramTypedCount = 1;
- final int codePointSetSize = 50;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
- setCurrentTimeForTestMode(mCurrentTime);
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
- final ArrayList<String> words = new ArrayList<>();
- for (int i = 0; i < unigramCount; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- words.add(word);
- for (int j = 0; j < unigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
- }
- }
- final String strong = "strong";
- final String weak = "weak";
- final String target = "target";
- for (int j = 0; j < unigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, strong, DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, weak, DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, target, DUMMY_PROBABILITY);
- }
- binaryDictionary.flushWithGC();
- for (int j = 0; j < strongBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, strong, target, DUMMY_PROBABILITY);
- }
- for (int j = 0; j < weakBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, weak, target, DUMMY_PROBABILITY);
- }
- assertTrue(isValidBigram(binaryDictionary, strong, target));
- assertTrue(isValidBigram(binaryDictionary, weak, target));
-
- for (int i = 0; i < bigramCount; i++) {
- final int word0Index = random.nextInt(words.size());
- final String word0 = words.get(word0Index);
- final int index = random.nextInt(words.size() - 1);
- final int word1Index = (index >= word0Index) ? index + 1 : index;
- final String word1 = words.get(word1Index);
-
- for (int j = 0; j < eachBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, word0, word1, DUMMY_PROBABILITY);
- }
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- final int bigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY));
- binaryDictionary.flushWithGC();
- final int bigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
- BinaryDictionary.BIGRAM_COUNT_QUERY));
- assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
- assertTrue(isValidBigram(binaryDictionary, strong, target));
- assertFalse(isValidBigram(binaryDictionary, weak, target));
- break;
- }
- }
- }
-
- public void testDictMigration() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
- }
- }
-
- private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
- setCurrentTimeForTestMode(mCurrentTime);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("aaa"));
- addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
- assertFalse(binaryDictionary.isValidWord("bbb"));
- addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "abc", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "aaa", "abc", DUMMY_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "aaa", "abc"));
- addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
- assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb"));
-
- assertEquals(fromFormatVersion, binaryDictionary.getFormatVersion());
- assertTrue(binaryDictionary.migrateTo(toFormatVersion));
- assertTrue(binaryDictionary.isValidDictionary());
- assertEquals(toFormatVersion, binaryDictionary.getFormatVersion());
- assertTrue(binaryDictionary.isValidWord("aaa"));
- assertFalse(binaryDictionary.isValidWord("bbb"));
- assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc"));
- addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("bbb"));
- assertTrue(isValidBigram(binaryDictionary, "aaa", "abc"));
- assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb"));
- addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
- assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
- binaryDictionary.close();
- dictFile.delete();
- }
-
- public void testBeginningOfSentence() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- if (supportsBeginningOfSentence(formatVersion)) {
- testBeginningOfSentence(formatVersion);
- }
- }
- }
-
- private void testBeginningOfSentence(final int formatVersion) {
- setCurrentTimeForTestMode(mCurrentTime);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
- binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
- BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
- true /* isBeginningOfSentence */, true /* isNotAWord */, false /* isBlacklisted */,
- mCurrentTime);
- final PrevWordsInfo prevWordsInfoStartOfSentence = PrevWordsInfo.BEGINNING_OF_SENTENCE;
- addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
- binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
- mCurrentTime);
- assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
- binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
- mCurrentTime);
- addUnigramWord(binaryDictionary, "bbb", DUMMY_PROBABILITY);
- binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "bbb", DUMMY_PROBABILITY,
- mCurrentTime);
- assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
- assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
-
- forcePassingLongTime(binaryDictionary);
- assertFalse(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
- assertFalse(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
-
- addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
- binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
- mCurrentTime);
- addUnigramWord(binaryDictionary, "bbb", DUMMY_PROBABILITY);
- binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "bbb", DUMMY_PROBABILITY,
- mCurrentTime);
- assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
- assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
- binaryDictionary.close();
- dictFile.delete();
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 6ba18d665..e96c934cb 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -21,14 +21,14 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.util.Pair;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.CodePointUtils;
+import com.android.inputmethod.latin.common.FileUtils;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.WeightedString;
import com.android.inputmethod.latin.makedict.WordProperty;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
import java.io.File;
import java.io.IOException;
@@ -36,103 +36,100 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
-import java.util.Map;
import java.util.Random;
-// TODO Use the seed passed as an argument for makedict test.
@LargeTest
public class BinaryDictionaryTests extends AndroidTestCase {
private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
private static final String TEST_LOCALE = "test";
- private static final int[] DICT_FORMAT_VERSIONS =
- new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
+ private static final String DICTIONARY_ID = "TestBinaryDictionary";
- private static boolean canCheckBigramProbability(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
+ private HashSet<File> mDictFilesToBeDeleted = new HashSet<>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDictFilesToBeDeleted.clear();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ for (final File dictFile : mDictFilesToBeDeleted) {
+ dictFile.delete();
+ }
+ mDictFilesToBeDeleted.clear();
+ super.tearDown();
}
- private static boolean supportsBeginningOfSentence(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
+ private File createEmptyDictionaryAndGetFile(final int formatVersion) {
+ return createEmptyDictionaryWithAttributesAndGetFile(formatVersion,
+ new HashMap<String, String>());
}
- private File createEmptyDictionaryAndGetFile(final String dictId,
- final int formatVersion) throws IOException {
- if (formatVersion == FormatSpec.VERSION4
- || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
- || formatVersion == FormatSpec.VERSION4_DEV) {
- return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
- } else {
- throw new IOException("Dictionary format version " + formatVersion
- + " is not supported.");
+ private File createEmptyDictionaryWithAttributesAndGetFile(final int formatVersion,
+ final HashMap<String, String> attributeMap) {
+ try {
+ final File dictFile = createEmptyVer4DictionaryAndGetFile(formatVersion,
+ attributeMap);
+ mDictFilesToBeDeleted.add(dictFile);
+ return dictFile;
+ } catch (final IOException e) {
+ fail(e.toString());
}
+ return null;
}
- private File createEmptyVer4DictionaryAndGetFile(final String dictId,
- final int formatVersion) throws IOException {
- final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
+ private File createEmptyVer4DictionaryAndGetFile(final int formatVersion,
+ final HashMap<String, String> attributeMap) throws IOException {
+ final File file = File.createTempFile(DICTIONARY_ID, TEST_DICT_FILE_EXTENSION,
getContext().getCacheDir());
file.delete();
file.mkdir();
- Map<String, String> attributeMap = new HashMap<>();
if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
Locale.ENGLISH, attributeMap)) {
return file;
- } else {
- throw new IOException("Empty dictionary " + file.getAbsolutePath()
- + " cannot be created. Format version: " + formatVersion);
}
+ throw new IOException("Empty dictionary " + file.getAbsolutePath()
+ + " cannot be created. Format version: " + formatVersion);
}
- public void testIsValidDictionary() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testIsValidDictionary(formatVersion);
- }
+ private static BinaryDictionary getBinaryDictionary(final File dictFile) {
+ return new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
}
- private void testIsValidDictionary(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ private BinaryDictionary getEmptyBinaryDictionary(final int formatVersion) {
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ return new BinaryDictionary(dictFile.getAbsolutePath(),
0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ }
+
+ public void testIsValidDictionary() {
+ final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
assertTrue("binaryDictionary must be valid for existing valid dictionary file.",
binaryDictionary.isValidDictionary());
binaryDictionary.close();
assertFalse("binaryDictionary must be invalid after closing.",
binaryDictionary.isValidDictionary());
FileUtils.deleteRecursively(dictFile);
- binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */,
- dictFile.length(), true /* useFullEditDistance */, Locale.getDefault(),
- TEST_LOCALE, true /* isUpdatable */);
+ binaryDictionary = getBinaryDictionary(dictFile);
assertFalse("binaryDictionary must be invalid for not existing dictionary file.",
binaryDictionary.isValidDictionary());
binaryDictionary.close();
}
public void testConstructingDictionaryOnMemory() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testConstructingDictionaryOnMemory(formatVersion);
- }
- }
-
- private void testConstructingDictionaryOnMemory(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
+ final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
FileUtils.deleteRecursively(dictFile);
assertFalse(dictFile.exists());
- BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE, formatVersion,
- new HashMap<String, String>());
+ final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE,
+ FormatSpec.VERSION403, new HashMap<String, String>());
assertTrue(binaryDictionary.isValidDictionary());
- assertEquals(formatVersion, binaryDictionary.getFormatVersion());
+ assertEquals(FormatSpec.VERSION403, binaryDictionary.getFormatVersion());
final int probability = 100;
addUnigramWord(binaryDictionary, "word", probability);
assertEquals(probability, binaryDictionary.getFrequency("word"));
@@ -140,31 +137,15 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flush();
assertTrue(dictFile.exists());
assertTrue(binaryDictionary.isValidDictionary());
- assertEquals(formatVersion, binaryDictionary.getFormatVersion());
+ assertEquals(FormatSpec.VERSION403, binaryDictionary.getFormatVersion());
assertEquals(probability, binaryDictionary.getFrequency("word"));
binaryDictionary.close();
- dictFile.delete();
}
public void testAddTooLongWord() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddTooLongWord(formatVersion);
- }
- }
-
- private void testAddTooLongWord(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final StringBuffer stringBuilder = new StringBuffer();
- for (int i = 0; i < Constants.DICTIONARY_MAX_WORD_LENGTH; i++) {
+ for (int i = 0; i < BinaryDictionary.DICTIONARY_MAX_WORD_LENGTH; i++) {
stringBuilder.append('a');
}
final String validLongWord = stringBuilder.toString();
@@ -175,9 +156,8 @@ public class BinaryDictionaryTests extends AndroidTestCase {
addUnigramWord(binaryDictionary, validLongWord, probability);
addUnigramWord(binaryDictionary, invalidLongWord, probability);
// Too long short cut.
- binaryDictionary.addUnigramEntry("a", probability, invalidLongWord,
- 10 /* shortcutProbability */, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */,
+ binaryDictionary.addUnigramEntry("a", probability, false /* isBeginningOfSentence */,
+ false /* isNotAWord */, false /* isPossiblyOffensive */,
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
addUnigramWord(binaryDictionary, "abc", probability);
final int updatedProbability = 200;
@@ -188,58 +168,49 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(probability, binaryDictionary.getFrequency("aaa"));
assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
- assertEquals(BinaryDictionary.NOT_A_PROBABILITY,
- binaryDictionary.getFrequency(invalidLongWord));
+ assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency(invalidLongWord));
assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
- dictFile.delete();
}
private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
final int probability) {
- binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
- BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+ binaryDictionary.addUnigramEntry(word, probability,
false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
+ false /* isPossiblyOffensive */,
+ BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
}
private static void addBigramWords(final BinaryDictionary binaryDictionary, final String word0,
final String word1, final int probability) {
- binaryDictionary.addNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1, probability,
+ binaryDictionary.addNgramEntry(new NgramContext(new WordInfo(word0)), word1, probability,
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
}
- private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
- final String word0, final String word1) {
- return binaryDictionary.isValidNgram(new PrevWordsInfo(new WordInfo(word0)), word1);
+ private static void addTrigramEntry(final BinaryDictionary binaryDictionary, final String word0,
+ final String word1, final String word2, final int probability) {
+ binaryDictionary.addNgramEntry(
+ new NgramContext(new WordInfo(word1), new WordInfo(word0)), word2,
+ probability, BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
}
- private static void removeBigramEntry(final BinaryDictionary binaryDictionary,
+ private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
final String word0, final String word1) {
- binaryDictionary.removeNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1);
+ return binaryDictionary.isValidNgram(new NgramContext(new WordInfo(word0)), word1);
}
private static int getBigramProbability(final BinaryDictionary binaryDictionary,
final String word0, final String word1) {
- return binaryDictionary.getNgramProbability(new PrevWordsInfo(new WordInfo(word0)), word1);
+ return binaryDictionary.getNgramProbability(new NgramContext(new WordInfo(word0)), word1);
}
- public void testAddUnigramWord() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddUnigramWord(formatVersion);
- }
+ private static int getTrigramProbability(final BinaryDictionary binaryDictionary,
+ final String word0, final String word1, final String word2) {
+ return binaryDictionary.getNgramProbability(
+ new NgramContext(new WordInfo(word1), new WordInfo(word0)), word2);
}
- private void testAddUnigramWord(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
-
+ public void testAddUnigramWord() {
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final int probability = 100;
addUnigramWord(binaryDictionary, "aaa", probability);
// Reallocate and create.
@@ -263,30 +234,13 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(probability, binaryDictionary.getFrequency("aaaa"));
assertEquals(probability, binaryDictionary.getFrequency("a"));
assertEquals(updatedProbability, binaryDictionary.getFrequency("aaa"));
-
- dictFile.delete();
}
public void testRandomlyAddUnigramWord() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testRandomlyAddUnigramWord(formatVersion);
- }
- }
-
- private void testRandomlyAddUnigramWord(final int formatVersion) {
final int wordCount = 1000;
final int codePointSetSize = 50;
final long seed = System.currentTimeMillis();
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final HashMap<String, Integer> probabilityMap = new HashMap<>();
// Test a word that isn't contained within the dictionary.
@@ -302,25 +256,10 @@ public class BinaryDictionaryTests extends AndroidTestCase {
for (String word : probabilityMap.keySet()) {
assertEquals(word, (int)probabilityMap.get(word), binaryDictionary.getFrequency(word));
}
- dictFile.delete();
}
public void testAddBigramWords() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddBigramWords(formatVersion);
- }
- }
-
- private void testAddBigramWords(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final int unigramProbability = 100;
final int bigramProbability = 150;
@@ -337,18 +276,14 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertTrue(isValidBigram(binaryDictionary, "aaa", "bcc"));
assertTrue(isValidBigram(binaryDictionary, "abb", "aaa"));
assertTrue(isValidBigram(binaryDictionary, "abb", "bcc"));
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
- }
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
addBigramWords(binaryDictionary, "aaa", "abb", updatedBigramProbability);
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(updatedBigramProbability,
- getBigramProbability(binaryDictionary, "aaa", "abb"));
- }
+ assertEquals(updatedBigramProbability,
+ getBigramProbability(binaryDictionary, "aaa", "abb"));
assertFalse(isValidBigram(binaryDictionary, "bcc", "aaa"));
assertFalse(isValidBigram(binaryDictionary, "bcc", "bbc"));
@@ -368,43 +303,21 @@ public class BinaryDictionaryTests extends AndroidTestCase {
addUnigramWord(binaryDictionary, "abc", unigramProbability);
addUnigramWord(binaryDictionary, "f", unigramProbability);
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability,
- getBigramProbability(binaryDictionary, "abcde", "fghij"));
- }
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abcde", "fghij"));
assertEquals(Dictionary.NOT_A_PROBABILITY,
getBigramProbability(binaryDictionary, "abcde", "fgh"));
addBigramWords(binaryDictionary, "abcde", "fghij", updatedBigramProbability);
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(updatedBigramProbability,
- getBigramProbability(binaryDictionary, "abcde", "fghij"));
- }
-
- dictFile.delete();
+ assertEquals(updatedBigramProbability,
+ getBigramProbability(binaryDictionary, "abcde", "fghij"));
}
public void testRandomlyAddBigramWords() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testRandomlyAddBigramWords(formatVersion);
- }
- }
-
- private void testRandomlyAddBigramWords(final int formatVersion) {
final int wordCount = 100;
final int bigramCount = 1000;
final int codePointSetSize = 50;
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final ArrayList<String> words = new ArrayList<>();
final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -439,83 +352,40 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final int bigramProbability = bigramProbabilities.get(bigram);
assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
isValidBigram(binaryDictionary, bigram.first, bigram.second));
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability,
- getBigramProbability(binaryDictionary, bigram.first, bigram.second));
- }
- }
-
- dictFile.delete();
- }
-
- public void testRemoveBigramWords() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testRemoveBigramWords(formatVersion);
+ assertEquals(bigramProbability,
+ getBigramProbability(binaryDictionary, bigram.first, bigram.second));
}
}
- private void testRemoveBigramWords(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 */);
+ public void testAddTrigramWords() {
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final int unigramProbability = 100;
- final int bigramProbability = 150;
+ final int trigramProbability = 150;
+ final int updatedTrigramProbability = 200;
addUnigramWord(binaryDictionary, "aaa", unigramProbability);
addUnigramWord(binaryDictionary, "abb", unigramProbability);
addUnigramWord(binaryDictionary, "bcc", unigramProbability);
- addBigramWords(binaryDictionary, "aaa", "abb", bigramProbability);
- addBigramWords(binaryDictionary, "aaa", "bcc", bigramProbability);
- addBigramWords(binaryDictionary, "abb", "aaa", bigramProbability);
- addBigramWords(binaryDictionary, "abb", "bcc", bigramProbability);
-
- assertTrue(isValidBigram(binaryDictionary, "aaa", "abb"));
- assertTrue(isValidBigram(binaryDictionary, "aaa", "bcc"));
- assertTrue(isValidBigram(binaryDictionary, "abb", "aaa"));
- assertTrue(isValidBigram(binaryDictionary, "abb", "bcc"));
-
- removeBigramEntry(binaryDictionary, "aaa", "abb");
- assertFalse(isValidBigram(binaryDictionary, "aaa", "abb"));
- addBigramWords(binaryDictionary, "aaa", "abb", bigramProbability);
- assertTrue(isValidBigram(binaryDictionary, "aaa", "abb"));
+ addBigramWords(binaryDictionary, "abb", "bcc", 10);
+ addBigramWords(binaryDictionary, "abb", "aaa", 10);
- removeBigramEntry(binaryDictionary, "aaa", "bcc");
- assertFalse(isValidBigram(binaryDictionary, "aaa", "bcc"));
- removeBigramEntry(binaryDictionary, "abb", "aaa");
- assertFalse(isValidBigram(binaryDictionary, "abb", "aaa"));
- removeBigramEntry(binaryDictionary, "abb", "bcc");
- assertFalse(isValidBigram(binaryDictionary, "abb", "bcc"));
+ addTrigramEntry(binaryDictionary, "aaa", "abb", "bcc", trigramProbability);
+ addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", trigramProbability);
- removeBigramEntry(binaryDictionary, "aaa", "abb");
- // Test remove non-existing bigram operation.
- removeBigramEntry(binaryDictionary, "aaa", "abb");
- removeBigramEntry(binaryDictionary, "bcc", "aaa");
+ assertEquals(trigramProbability,
+ getTrigramProbability(binaryDictionary, "aaa", "abb", "bcc"));
+ assertEquals(trigramProbability,
+ getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
+ assertFalse(isValidBigram(binaryDictionary, "aaa", "abb"));
- dictFile.delete();
+ addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", updatedTrigramProbability);
+ assertEquals(updatedTrigramProbability,
+ getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
}
public void testFlushDictionary() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testFlushDictionary(formatVersion);
- }
- }
-
- private void testFlushDictionary(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int probability = 100;
addUnigramWord(binaryDictionary, "aaa", probability);
@@ -535,42 +405,21 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flush();
binaryDictionary.close();
- binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+ binaryDictionary = getBinaryDictionary(dictFile);
assertEquals(probability, binaryDictionary.getFrequency("aaa"));
assertEquals(probability, binaryDictionary.getFrequency("abcd"));
addUnigramWord(binaryDictionary, "bcde", probability);
binaryDictionary.flush();
binaryDictionary.close();
- binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ binaryDictionary = getBinaryDictionary(dictFile);
assertEquals(probability, binaryDictionary.getFrequency("bcde"));
binaryDictionary.close();
-
- dictFile.delete();
}
public void testFlushWithGCDictionary() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testFlushWithGCDictionary(formatVersion);
- }
- }
-
- private void testFlushWithGCDictionary(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int unigramProbability = 100;
final int bigramProbability = 150;
addUnigramWord(binaryDictionary, "aaa", unigramProbability);
@@ -583,51 +432,30 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flushWithGC();
binaryDictionary.close();
- binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ binaryDictionary = getBinaryDictionary(dictFile);
assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
assertEquals(unigramProbability, binaryDictionary.getFrequency("abb"));
assertEquals(unigramProbability, binaryDictionary.getFrequency("bcc"));
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
- }
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
assertFalse(isValidBigram(binaryDictionary, "bcc", "aaa"));
assertFalse(isValidBigram(binaryDictionary, "bcc", "bbc"));
assertFalse(isValidBigram(binaryDictionary, "aaa", "aaa"));
binaryDictionary.flushWithGC();
binaryDictionary.close();
-
- dictFile.delete();
}
public void testAddBigramWordsAndFlashWithGC() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddBigramWordsAndFlashWithGC(formatVersion);
- }
- }
-
- // TODO: Evaluate performance of GC
- private void testAddBigramWordsAndFlashWithGC(final int formatVersion) {
final int wordCount = 100;
final int bigramCount = 1000;
final int codePointSetSize = 30;
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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 File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final ArrayList<String> words = new ArrayList<>();
final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -660,52 +488,37 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flushWithGC();
binaryDictionary.close();
- binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+ binaryDictionary = getBinaryDictionary(dictFile);
for (final Pair<String, String> bigram : bigramWords) {
final int bigramProbability = bigramProbabilities.get(bigram);
assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
isValidBigram(binaryDictionary, bigram.first, bigram.second));
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability,
- getBigramProbability(binaryDictionary, bigram.first, bigram.second));
- }
+ assertEquals(bigramProbability,
+ getBigramProbability(binaryDictionary, bigram.first, bigram.second));
}
-
- dictFile.delete();
}
public void testRandomOperationsAndFlashWithGC() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testRandomOperationsAndFlashWithGC(formatVersion);
- }
- }
+ final int maxUnigramCount = 5000;
+ final int maxBigramCount = 10000;
+ final HashMap<String, String> attributeMap = new HashMap<>();
+ attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY, String.valueOf(maxUnigramCount));
+ attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY, String.valueOf(maxBigramCount));
- private void testRandomOperationsAndFlashWithGC(final int formatVersion) {
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 long seed = System.currentTimeMillis();
final Random random = new Random(seed);
+ final File dictFile = createEmptyDictionaryWithAttributesAndGetFile(FormatSpec.VERSION403,
+ attributeMap);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } 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<>();
final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
@@ -722,9 +535,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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 */);
+ binaryDictionary = getBinaryDictionary(dictFile);
for (int opCount = 0; opCount < operationCountInEachIteration; opCount++) {
// Add unigram.
if (random.nextFloat() < addUnigramProb) {
@@ -754,14 +565,6 @@ public class BinaryDictionaryTests extends AndroidTestCase {
bigramProbabilities.put(bigram, bigramProbability);
addBigramWords(binaryDictionary, 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);
- removeBigramEntry(binaryDictionary, bigram.first, bigram.second);
- }
}
// Test whether the all unigram operations are collectlly handled.
@@ -775,45 +578,29 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final Pair<String, String> bigram = bigramWords.get(i);
final int probability;
if (bigramProbabilities.containsKey(bigram)) {
- final int bigramProbability = bigramProbabilities.get(bigram);
- probability = bigramProbability;
+ probability = bigramProbabilities.get(bigram);
} else {
probability = Dictionary.NOT_A_PROBABILITY;
}
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(probability,
- getBigramProbability(binaryDictionary, bigram.first, bigram.second));
- }
+ assertEquals(probability,
+ getBigramProbability(binaryDictionary, bigram.first, bigram.second));
assertEquals(probability != Dictionary.NOT_A_PROBABILITY,
isValidBigram(binaryDictionary, bigram.first, bigram.second));
}
binaryDictionary.flushWithGC();
binaryDictionary.close();
}
-
- dictFile.delete();
}
public void testAddManyUnigramsAndFlushWithGC() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddManyUnigramsAndFlushWithGC(formatVersion);
- }
- }
-
- private void testAddManyUnigramsAndFlushWithGC(final int formatVersion) {
final int flashWithGCIterationCount = 3;
final int codePointSetSize = 50;
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
+ final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
final ArrayList<String> words = new ArrayList<>();
final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
@@ -821,9 +608,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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 */);
+ binaryDictionary = getBinaryDictionary(dictFile);
while(!binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
final String word = CodePointUtils.generateWord(random, codePointSet);
words.add(word);
@@ -841,30 +626,23 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flushWithGC();
binaryDictionary.close();
}
-
- dictFile.delete();
}
public void testUnigramAndBigramCount() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testUnigramAndBigramCount(formatVersion);
- }
- }
+ final int maxUnigramCount = 5000;
+ final int maxBigramCount = 10000;
+ final HashMap<String, String> attributeMap = new HashMap<>();
+ attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY, String.valueOf(maxUnigramCount));
+ attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY, String.valueOf(maxBigramCount));
- private void testUnigramAndBigramCount(final int formatVersion) {
final int flashWithGCIterationCount = 10;
final int codePointSetSize = 50;
final int unigramCountPerIteration = 1000;
final int bigramCountPerIteration = 2000;
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
+ final File dictFile = createEmptyDictionaryWithAttributesAndGetFile(FormatSpec.VERSION403,
+ attributeMap);
final ArrayList<String> words = new ArrayList<>();
final HashSet<Pair<String, String>> bigrams = new HashSet<>();
@@ -872,9 +650,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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 */);
+ binaryDictionary = getBinaryDictionary(dictFile);
for (int j = 0; j < unigramCountPerIteration; j++) {
final String word = CodePointUtils.generateWord(random, codePointSet);
words.add(word);
@@ -892,108 +668,31 @@ public class BinaryDictionaryTests extends AndroidTestCase {
addBigramWords(binaryDictionary, word0, word1, bigramProbability);
}
assertEquals(new HashSet<>(words).size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+ binaryDictionary.getPropertyForGettingStats(
+ BinaryDictionary.UNIGRAM_COUNT_QUERY)));
assertEquals(new HashSet<>(bigrams).size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+ binaryDictionary.getPropertyForGettingStats(
+ BinaryDictionary.BIGRAM_COUNT_QUERY)));
binaryDictionary.flushWithGC();
assertEquals(new HashSet<>(words).size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+ binaryDictionary.getPropertyForGettingStats(
+ BinaryDictionary.UNIGRAM_COUNT_QUERY)));
assertEquals(new HashSet<>(bigrams).size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+ binaryDictionary.getPropertyForGettingStats(
+ BinaryDictionary.BIGRAM_COUNT_QUERY)));
binaryDictionary.close();
}
-
- dictFile.delete();
- }
-
- public void testAddMultipleDictionaryEntries() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddMultipleDictionaryEntries(formatVersion);
- }
- }
-
- private void testAddMultipleDictionaryEntries(final int formatVersion) {
- final int codePointSetSize = 20;
- final int lmParamCount = 1000;
- final double bigramContinueRate = 0.9;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
-
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
- final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
- final HashMap<Pair<String, String>, Integer> bigramProbabilities = new HashMap<>();
-
- final LanguageModelParam[] languageModelParams = new LanguageModelParam[lmParamCount];
- String prevWord = null;
- for (int i = 0; i < languageModelParams.length; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- final int probability = random.nextInt(0xFF);
- final int bigramProbability = probability + random.nextInt(0xFF - probability);
- unigramProbabilities.put(word, probability);
- if (prevWord == null) {
- languageModelParams[i] = new LanguageModelParam(word, probability,
- BinaryDictionary.NOT_A_VALID_TIMESTAMP);
- } else {
- languageModelParams[i] = new LanguageModelParam(prevWord, word, probability,
- bigramProbability, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
- bigramProbabilities.put(new Pair<>(prevWord, word),
- bigramProbability);
- }
- prevWord = (random.nextDouble() < bigramContinueRate) ? word : null;
- }
-
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- binaryDictionary.addMultipleDictionaryEntries(languageModelParams);
-
- for (Map.Entry<String, Integer> entry : unigramProbabilities.entrySet()) {
- assertEquals((int)entry.getValue(), binaryDictionary.getFrequency(entry.getKey()));
- }
-
- for (Map.Entry<Pair<String, String>, Integer> entry : bigramProbabilities.entrySet()) {
- final String word0 = entry.getKey().first;
- final String word1 = entry.getKey().second;
- final int bigramProbability = entry.getValue();
- assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
- isValidBigram(binaryDictionary, word0, word1));
- if (canCheckBigramProbability(formatVersion)) {
- assertEquals(bigramProbability,
- getBigramProbability(binaryDictionary, word0, word1));
- }
- }
}
public void testGetWordProperties() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testGetWordProperties(formatVersion);
- }
- }
-
- private void testGetWordProperties(final int formatVersion) {
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
final int UNIGRAM_COUNT = 1000;
final int BIGRAM_COUNT = 1000;
final int codePointSetSize = 20;
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
false /* isBeginningOfSentence */);
@@ -1008,11 +707,10 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final String word = CodePointUtils.generateWord(random, codePointSet);
final int unigramProbability = random.nextInt(0xFF);
final boolean isNotAWord = random.nextBoolean();
- final boolean isBlacklisted = random.nextBoolean();
+ final boolean isPossiblyOffensive = random.nextBoolean();
// TODO: Add tests for historical info.
binaryDictionary.addUnigramEntry(word, unigramProbability,
- null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
- false /* isBeginningOfSentence */, isNotAWord, isBlacklisted,
+ false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
binaryDictionary.flushWithGC();
@@ -1024,11 +722,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(word, wordProperty.mWord);
assertTrue(wordProperty.isValid());
assertEquals(isNotAWord, wordProperty.mIsNotAWord);
- assertEquals(isBlacklisted, wordProperty.mIsBlacklistEntry);
- assertEquals(false, wordProperty.mHasBigrams);
- assertEquals(false, wordProperty.mHasShortcuts);
+ assertEquals(isPossiblyOffensive, wordProperty.mIsPossiblyOffensive);
+ assertEquals(false, wordProperty.mHasNgrams);
assertEquals(unigramProbability, wordProperty.mProbabilityInfo.mProbability);
- assertTrue(wordProperty.mShortcutTargets.isEmpty());
}
for (int i = 0; i < BIGRAM_COUNT; i++) {
@@ -1062,41 +758,25 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final HashSet<String> bigramWord1s = bigrams.get(word0);
final WordProperty wordProperty = binaryDictionary.getWordProperty(word0,
false /* isBeginningOfSentence */);
- assertEquals(bigramWord1s.size(), wordProperty.mBigrams.size());
- for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
- final String word1 = wordProperty.mBigrams.get(j).mWord;
+ assertEquals(bigramWord1s.size(), wordProperty.mNgrams.size());
+ // TODO: Support ngram.
+ for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+ final String word1 = bigramTarget.mWord;
assertTrue(bigramWord1s.contains(word1));
- if (canCheckBigramProbability(formatVersion)) {
- final int bigramProbability = bigramProbabilities.get(new Pair<>(word0, word1));
- assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
- }
+ final int bigramProbability = bigramProbabilities.get(new Pair<>(word0, word1));
+ assertEquals(bigramProbability, bigramTarget.getProbability());
}
}
}
public void testIterateAllWords() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testIterateAllWords(formatVersion);
- }
- }
-
- private void testIterateAllWords(final int formatVersion) {
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
final int UNIGRAM_COUNT = 1000;
final int BIGRAM_COUNT = 1000;
final int codePointSetSize = 20;
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
false /* isBeginningOfSentence */);
@@ -1155,15 +835,16 @@ public class BinaryDictionaryTests extends AndroidTestCase {
wordProperty.mProbabilityInfo.mProbability);
wordSet.remove(word0);
final HashSet<String> bigramWord1s = bigrams.get(word0);
- for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
- final String word1 = wordProperty.mBigrams.get(j).mWord;
- assertTrue(bigramWord1s.contains(word1));
- final Pair<String, String> bigram = new Pair<>(word0, word1);
- if (canCheckBigramProbability(formatVersion)) {
+ // TODO: Support ngram.
+ if (wordProperty.mHasNgrams) {
+ for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+ final String word1 = bigramTarget.mWord;
+ assertTrue(bigramWord1s.contains(word1));
+ final Pair<String, String> bigram = new Pair<>(word0, word1);
final int bigramProbability = bigramProbabilitiesToCheckLater.get(bigram);
- assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
+ assertEquals(bigramProbability, bigramTarget.getProbability());
+ bigramSet.remove(bigram);
}
- bigramSet.remove(bigram);
}
token = result.mNextToken;
} while (token != 0);
@@ -1171,346 +852,33 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertTrue(bigramSet.isEmpty());
}
- public void testAddShortcuts() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddShortcuts(formatVersion);
- }
- }
-
- private void testAddShortcuts(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
- final int unigramProbability = 100;
- final int shortcutProbability = 10;
- binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
- shortcutProbability, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
- WordProperty wordProperty = binaryDictionary.getWordProperty("aaa",
- false /* isBeginningOfSentence */);
- assertEquals(1, wordProperty.mShortcutTargets.size());
- assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
- assertEquals(shortcutProbability, wordProperty.mShortcutTargets.get(0).getProbability());
- final int updatedShortcutProbability = 2;
- binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
- updatedShortcutProbability, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
- wordProperty = binaryDictionary.getWordProperty("aaa",
- false /* isBeginningOfSentence */);
- assertEquals(1, wordProperty.mShortcutTargets.size());
- assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
- assertEquals(updatedShortcutProbability,
- wordProperty.mShortcutTargets.get(0).getProbability());
- binaryDictionary.addUnigramEntry("aaa", unigramProbability, "yyy",
- shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
- final HashMap<String, Integer> shortcutTargets = new HashMap<>();
- shortcutTargets.put("zzz", updatedShortcutProbability);
- shortcutTargets.put("yyy", shortcutProbability);
- wordProperty = binaryDictionary.getWordProperty("aaa",
- false /* isBeginningOfSentence */);
- assertEquals(2, wordProperty.mShortcutTargets.size());
- for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
- assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
- shortcutTarget.getProbability());
- shortcutTargets.remove(shortcutTarget.mWord);
- }
- shortcutTargets.put("zzz", updatedShortcutProbability);
- shortcutTargets.put("yyy", shortcutProbability);
- binaryDictionary.flushWithGC();
- wordProperty = binaryDictionary.getWordProperty("aaa",
- false /* isBeginningOfSentence */);
- assertEquals(2, wordProperty.mShortcutTargets.size());
- for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
- assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
- shortcutTarget.getProbability());
- shortcutTargets.remove(shortcutTarget.mWord);
- }
- }
-
- public void testAddManyShortcuts() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testAddManyShortcuts(formatVersion);
- }
- }
-
- private void testAddManyShortcuts(final int formatVersion) {
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
- final int UNIGRAM_COUNT = 1000;
- final int SHORTCUT_COUNT = 10000;
- final int codePointSetSize = 20;
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
- final ArrayList<String> words = new ArrayList<>();
- final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
- final HashMap<String, HashMap<String, Integer>> shortcutTargets = new HashMap<>();
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
- for (int i = 0; i < UNIGRAM_COUNT; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- final int unigramProbability = random.nextInt(0xFF);
- addUnigramWord(binaryDictionary, word, unigramProbability);
- words.add(word);
- unigramProbabilities.put(word, unigramProbability);
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- binaryDictionary.flushWithGC();
- }
- }
- for (int i = 0; i < SHORTCUT_COUNT; i++) {
- final String shortcutTarget = CodePointUtils.generateWord(random, codePointSet);
- final int shortcutProbability = random.nextInt(0xF);
- final String word = words.get(random.nextInt(words.size()));
- final int unigramProbability = unigramProbabilities.get(word);
- binaryDictionary.addUnigramEntry(word, unigramProbability, shortcutTarget,
- shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
- if (shortcutTargets.containsKey(word)) {
- final HashMap<String, Integer> shortcutTargetsOfWord = shortcutTargets.get(word);
- shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
- } else {
- final HashMap<String, Integer> shortcutTargetsOfWord = new HashMap<>();
- shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
- shortcutTargets.put(word, shortcutTargetsOfWord);
- }
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- binaryDictionary.flushWithGC();
- }
- }
-
- for (final String word : words) {
- final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
- false /* isBeginningOfSentence */);
- assertEquals((int)unigramProbabilities.get(word),
- wordProperty.mProbabilityInfo.mProbability);
- if (!shortcutTargets.containsKey(word)) {
- // The word does not have shortcut targets.
- continue;
- }
- assertEquals(shortcutTargets.get(word).size(), wordProperty.mShortcutTargets.size());
- for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- final String targetCodePonts = shortcutTarget.mWord;
- assertEquals((int)shortcutTargets.get(word).get(targetCodePonts),
- shortcutTarget.getProbability());
- }
- }
- }
-
- public void testDictMigration() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
- }
- }
-
- private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- final int unigramProbability = 100;
- addUnigramWord(binaryDictionary, "aaa", unigramProbability);
- addUnigramWord(binaryDictionary, "bbb", unigramProbability);
- final int bigramProbability = 150;
- addBigramWords(binaryDictionary, "aaa", "bbb", bigramProbability);
- final int shortcutProbability = 10;
- binaryDictionary.addUnigramEntry("ccc", unigramProbability, "xxx", shortcutProbability,
- false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
- binaryDictionary.addUnigramEntry("ddd", unigramProbability, null /* shortcutTarget */,
- Dictionary.NOT_A_PROBABILITY, false /* isBeginningOfSentence */,
- true /* isNotAWord */, true /* isBlacklisted */, 0 /* timestamp */);
- binaryDictionary.addNgramEntry(PrevWordsInfo.BEGINNING_OF_SENTENCE,
- "aaa", bigramProbability, 0 /* timestamp */);
- assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
- assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
- assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
- assertEquals(fromFormatVersion, binaryDictionary.getFormatVersion());
- assertTrue(binaryDictionary.migrateTo(toFormatVersion));
- assertTrue(binaryDictionary.isValidDictionary());
- assertEquals(toFormatVersion, binaryDictionary.getFormatVersion());
- assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
- assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
- if (canCheckBigramProbability(toFormatVersion)) {
- assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bbb"));
- assertEquals(bigramProbability, binaryDictionary.getNgramProbability(
- PrevWordsInfo.BEGINNING_OF_SENTENCE, "aaa"));
- }
- assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
- WordProperty wordProperty = binaryDictionary.getWordProperty("ccc",
- false /* isBeginningOfSentence */);
- assertEquals(1, wordProperty.mShortcutTargets.size());
- assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
- wordProperty = binaryDictionary.getWordProperty("ddd",
- false /* isBeginningOfSentence */);
- assertTrue(wordProperty.mIsBlacklistEntry);
- assertTrue(wordProperty.mIsNotAWord);
- }
-
- public void testLargeDictMigration() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testLargeDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
- }
- }
-
- private void testLargeDictMigration(final int fromFormatVersion, final int toFormatVersion) {
- final int UNIGRAM_COUNT = 3000;
- final int BIGRAM_COUNT = 3000;
- final int codePointSetSize = 50;
- final long seed = System.currentTimeMillis();
- final Random random = new Random(seed);
-
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
- final ArrayList<String> words = new ArrayList<>();
- final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
- final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
- final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
- final HashMap<Pair<String, String>, Integer> bigramProbabilities = new HashMap<>();
-
- for (int i = 0; i < UNIGRAM_COUNT; i++) {
- final String word = CodePointUtils.generateWord(random, codePointSet);
- final int unigramProbability = random.nextInt(0xFF);
- addUnigramWord(binaryDictionary, word, unigramProbability);
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- binaryDictionary.flushWithGC();
- }
- words.add(word);
- unigramProbabilities.put(word, unigramProbability);
- }
-
- for (int i = 0; i < BIGRAM_COUNT; i++) {
- final int word0Index = random.nextInt(words.size());
- final int word1Index = random.nextInt(words.size());
- if (word0Index == word1Index) {
- continue;
- }
- final String word0 = words.get(word0Index);
- final String word1 = words.get(word1Index);
- final int unigramProbability = unigramProbabilities.get(word1);
- final int bigramProbability =
- random.nextInt(0xFF - unigramProbability) + unigramProbability;
- addBigramWords(binaryDictionary, word0, word1, bigramProbability);
- if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
- binaryDictionary.flushWithGC();
- }
- final Pair<String, String> bigram = new Pair<>(word0, word1);
- bigrams.add(bigram);
- bigramProbabilities.put(bigram, bigramProbability);
- }
- assertTrue(binaryDictionary.migrateTo(toFormatVersion));
-
- for (final String word : words) {
- assertEquals((int)unigramProbabilities.get(word), binaryDictionary.getFrequency(word));
- }
- assertEquals(unigramProbabilities.size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
-
- for (final Pair<String, String> bigram : bigrams) {
- if (canCheckBigramProbability(toFormatVersion)) {
- assertEquals((int)bigramProbabilities.get(bigram),
- getBigramProbability(binaryDictionary, bigram.first, bigram.second));
- }
- assertTrue(isValidBigram(binaryDictionary, bigram.first, bigram.second));
- }
- assertEquals(bigramProbabilities.size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+ public void testPossiblyOffensiveAttributeMaintained() {
+ final BinaryDictionary binaryDictionary =
+ getEmptyBinaryDictionary(FormatSpec.VERSION403);
+ binaryDictionary.addUnigramEntry("ddd", 100, false, true, true, 0);
+ WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
+ assertEquals(true, wordProperty.mIsPossiblyOffensive);
}
public void testBeginningOfSentence() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- if (supportsBeginningOfSentence(formatVersion)) {
- testBeginningOfSentence(formatVersion);
- }
- }
- }
-
- private void testBeginningOfSentence(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
final int dummyProbability = 0;
- final PrevWordsInfo prevWordsInfoBeginningOfSentence = PrevWordsInfo.BEGINNING_OF_SENTENCE;
+ final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
final int bigramProbability = 200;
addUnigramWord(binaryDictionary, "aaa", dummyProbability);
- binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "aaa", bigramProbability,
+ binaryDictionary.addNgramEntry(beginningOfSentenceContext, "aaa", bigramProbability,
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
assertEquals(bigramProbability,
- binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "aaa"));
- binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "aaa", bigramProbability,
+ binaryDictionary.getNgramProbability(beginningOfSentenceContext, "aaa"));
+ binaryDictionary.addNgramEntry(beginningOfSentenceContext, "aaa", bigramProbability,
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
addUnigramWord(binaryDictionary, "bbb", dummyProbability);
- binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "bbb", bigramProbability,
+ binaryDictionary.addNgramEntry(beginningOfSentenceContext, "bbb", bigramProbability,
BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
binaryDictionary.flushWithGC();
assertEquals(bigramProbability,
- binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "aaa"));
+ binaryDictionary.getNgramProbability(beginningOfSentenceContext, "aaa"));
assertEquals(bigramProbability,
- binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "bbb"));
- }
-
- public void testGetMaxFrequencyOfExactMatches() {
- for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- testGetMaxFrequencyOfExactMatches(formatVersion);
- }
- }
-
- private void testGetMaxFrequencyOfExactMatches(final int formatVersion) {
- File dictFile = null;
- try {
- dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- addUnigramWord(binaryDictionary, "abc", 10);
- addUnigramWord(binaryDictionary, "aBc", 15);
- assertEquals(15, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
- addUnigramWord(binaryDictionary, "ab'c", 20);
- assertEquals(20, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
- addUnigramWord(binaryDictionary, "a-b-c", 25);
- assertEquals(25, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
- addUnigramWord(binaryDictionary, "ab-'-'-'-c", 30);
- assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
- addUnigramWord(binaryDictionary, "ab c", 255);
- assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
+ binaryDictionary.getNgramProbability(beginningOfSentenceContext, "bbb"));
}
}
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 6e894decf..afb94ef05 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -20,6 +20,8 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.text.style.SuggestionSpan;
import android.text.style.UnderlineSpan;
+import com.android.inputmethod.latin.common.Constants;
+
@LargeTest
public class BlueUnderlineTests extends InputTestsBase {
@@ -28,7 +30,7 @@ public class BlueUnderlineTests extends InputTestsBase {
final int EXPECTED_SPAN_START = 0;
final int EXPECTED_SPAN_END = 4;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertEquals("show blue underline, span start", EXPECTED_SPAN_START, span.mStart);
@@ -37,12 +39,12 @@ public class BlueUnderlineTests extends InputTestsBase {
}
public void testBlueUnderlineDisappears() {
- final String STRING_1_TO_TYPE = "tgis";
- final String STRING_2_TO_TYPE = "q";
+ final String STRING_1_TO_TYPE = "tqis";
+ final String STRING_2_TO_TYPE = "g";
final int EXPECTED_SPAN_START = 0;
final int EXPECTED_SPAN_END = 5;
type(STRING_1_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(STRING_2_TO_TYPE);
// We haven't have time to look into the dictionary yet, so the line should still be
@@ -51,7 +53,7 @@ public class BlueUnderlineTests extends InputTestsBase {
assertEquals("extend blue underline, span start", EXPECTED_SPAN_START, spanBefore.mStart);
assertEquals("extend blue underline, span end", EXPECTED_SPAN_END, spanBefore.mEnd);
assertTrue("extend blue underline, span color", spanBefore.isAutoCorrectionIndicator());
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
// Now we have been able to re-evaluate the word, there shouldn't be an auto-correction span
final SpanGetter spanAfter = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
@@ -61,22 +63,21 @@ public class BlueUnderlineTests extends InputTestsBase {
public void testBlueUnderlineOnBackspace() {
final String STRING_TO_TYPE = "tgis";
final int typedLength = STRING_TO_TYPE.length();
- final int EXPECTED_SUGGESTION_SPAN_START = -1;
final int EXPECTED_UNDERLINE_SPAN_START = 0;
- final int EXPECTED_UNDERLINE_SPAN_END = 4;
+ final int EXPECTED_UNDERLINE_SPAN_END = 3;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_SPACE);
// typedLength + 1 because we also typed a space
mLatinIME.onUpdateSelection(0, 0, typedLength + 1, typedLength + 1, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter suggestionSpan = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertFalse("show no blue underline after backspace, span should not be the auto-"
@@ -93,7 +94,7 @@ public class BlueUnderlineTests extends InputTestsBase {
final int typedLength = STRING_TO_TYPE.length();
final int NEW_CURSOR_POSITION = 0;
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
// Simulate the onUpdateSelection() event
mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
runMessages();
@@ -103,7 +104,7 @@ public class BlueUnderlineTests extends InputTestsBase {
mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
mLatinIME.onUpdateSelection(typedLength, typedLength,
NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
assertFalse("blue underline removed when cursor is moved",
@@ -113,7 +114,7 @@ public class BlueUnderlineTests extends InputTestsBase {
public void testComposingStopsOnSpace() {
final String STRING_TO_TYPE = "this ";
type(STRING_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
// Simulate the onUpdateSelection() event
mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
runMessages();
diff --git a/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java b/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java
new file mode 100644
index 000000000..f90a18bf1
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.ContactsContract.Contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for {@link ContactsContentObserver}.
+ */
+@SmallTest
+public class ContactsContentObserverTest {
+ private static final int UPDATED_CONTACT_COUNT = 10;
+ private static final int STALE_CONTACT_COUNT = 8;
+ private static final ArrayList<String> STALE_NAMES_LIST = new ArrayList<>();
+ private static final ArrayList<String> UPDATED_NAMES_LIST = new ArrayList<>();
+
+ static {
+ STALE_NAMES_LIST.add("Larry Page");
+ STALE_NAMES_LIST.add("Roger Federer");
+ UPDATED_NAMES_LIST.add("Larry Page");
+ UPDATED_NAMES_LIST.add("Roger Federer");
+ UPDATED_NAMES_LIST.add("Barak Obama");
+ }
+
+ @Mock private ContactsManager mMockManager;
+ @Mock private Context mContext;
+
+ private ContactsContentObserver mObserver;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mObserver = new ContactsContentObserver(mMockManager, mContext);
+ }
+
+ @After
+ public void tearDown() {
+ validateMockitoUsage();
+ }
+
+ @Test
+ public void testHaveContentsChanged_NoChange() {
+ when(mMockManager.getContactCount()).thenReturn(STALE_CONTACT_COUNT);
+ when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+ when(mMockManager.getValidNames(eq(Contacts.CONTENT_URI))).thenReturn(STALE_NAMES_LIST);
+ when(mMockManager.getHashCodeAtLastRebuild()).thenReturn(STALE_NAMES_LIST.hashCode());
+ assertFalse(mObserver.haveContentsChanged());
+ }
+ @Test
+ public void testHaveContentsChanged_UpdatedCount() {
+ when(mMockManager.getContactCount()).thenReturn(UPDATED_CONTACT_COUNT);
+ when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+ assertTrue(mObserver.haveContentsChanged());
+ }
+
+ @Test
+ public void testHaveContentsChanged_HashUpdate() {
+ when(mMockManager.getContactCount()).thenReturn(STALE_CONTACT_COUNT);
+ when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+ when(mMockManager.getValidNames(eq(Contacts.CONTENT_URI))).thenReturn(UPDATED_NAMES_LIST);
+ when(mMockManager.getHashCodeAtLastRebuild()).thenReturn(STALE_NAMES_LIST.hashCode());
+ assertTrue(mObserver.haveContentsChanged());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java b/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java
new file mode 100644
index 000000000..9b49f1abb
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Locale;
+
+/**
+ * Tests for {@link ContactsDictionaryUtils}
+ */
+@SmallTest
+public class ContactsDictionaryUtilsTest {
+
+ @Test
+ public void testGetWordEndPosition() {
+ final String testString1 = "Larry Page";
+ assertEquals(5, ContactsDictionaryUtils.getWordEndPosition(
+ testString1, testString1.length(), 0 /* startIndex */));
+
+ assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+ testString1, testString1.length(), 6 /* startIndex */));
+
+ final String testString2 = "Larry-Page";
+ assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+ testString2, testString1.length(), 0 /* startIndex */));
+
+ final String testString3 = "Larry'Page";
+ assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+ testString3, testString1.length(), 0 /* startIndex */));
+ }
+
+ @Test
+ public void testUseFirstLastBigramsForLocale() {
+ assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.ENGLISH));
+ assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.US));
+ assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.UK));
+ assertFalse(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.CHINA));
+ assertFalse(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.GERMAN));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java b/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java
new file mode 100644
index 000000000..6326b3b0f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 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.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.test.AndroidTestCase;
+import android.test.RenamingDelegatingContext;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Tests for {@link ContactsManager}
+ */
+@SmallTest
+public class ContactsManagerTest extends AndroidTestCase {
+
+ private ContactsManager mManager;
+ private FakeContactsContentProvider mFakeContactsContentProvider;
+ private MatrixCursor mMatrixCursor;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ // Fake content provider
+ mFakeContactsContentProvider = new FakeContactsContentProvider();
+ mMatrixCursor = new MatrixCursor(ContactsDictionaryConstants.PROJECTION);
+ // Add the fake content provider to fake content resolver.
+ final MockContentResolver contentResolver = new MockContentResolver();
+ contentResolver.addProvider(ContactsContract.AUTHORITY, mFakeContactsContentProvider);
+ // Add the fake content resolver to a fake context.
+ final ContextWithMockContentResolver context = new ContextWithMockContentResolver(mContext);
+ context.setContentResolver(contentResolver);
+
+ mManager = new ContactsManager(context);
+ }
+
+ @Test
+ public void testGetValidNames() {
+ final String contactName1 = "firstname lastname";
+ final String contactName2 = "larry";
+ mMatrixCursor.addRow(new Object[] { 1, contactName1 });
+ mMatrixCursor.addRow(new Object[] { 2, null /* null name */ });
+ mMatrixCursor.addRow(new Object[] { 3, contactName2 });
+ mMatrixCursor.addRow(new Object[] { 4, "floopy@example.com" /* invalid name */ });
+ mFakeContactsContentProvider.addQueryResult(Contacts.CONTENT_URI, mMatrixCursor);
+
+ final ArrayList<String> validNames = mManager.getValidNames(Contacts.CONTENT_URI);
+ assertEquals(2, validNames.size());
+ assertEquals(contactName1, validNames.get(0));
+ assertEquals(contactName2, validNames.get(1));
+ }
+
+ @Test
+ public void testGetCount() {
+ mMatrixCursor.addRow(new Object[] { 1, "firstname" });
+ mMatrixCursor.addRow(new Object[] { 2, null /* null name */ });
+ mMatrixCursor.addRow(new Object[] { 3, "larry" });
+ mMatrixCursor.addRow(new Object[] { 4, "floopy@example.com" /* invalid name */ });
+ mFakeContactsContentProvider.addQueryResult(Contacts.CONTENT_URI, mMatrixCursor);
+
+ assertEquals(4, mManager.getContactCount());
+ }
+
+
+ static class ContextWithMockContentResolver extends RenamingDelegatingContext {
+ private ContentResolver contentResolver;
+
+ public void setContentResolver(final ContentResolver contentResolver) {
+ this.contentResolver = contentResolver;
+ }
+
+ public ContextWithMockContentResolver(final Context targetContext) {
+ super(targetContext, "test");
+ }
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return contentResolver;
+ }
+ }
+
+ static class FakeContactsContentProvider extends MockContentProvider {
+ private final HashMap<String, MatrixCursor> mQueryCursorMapForTestExpectations =
+ new HashMap<>();
+
+ @Override
+ public Cursor query(final Uri uri, final String[] projection, final String selection,
+ final String[] selectionArgs, final String sortOrder) {
+ return mQueryCursorMapForTestExpectations.get(uri.toString());
+ }
+
+ public void reset() {
+ mQueryCursorMapForTestExpectations.clear();
+ }
+
+ public void addQueryResult(final Uri uri, final MatrixCursor cursor) {
+ mQueryCursorMapForTestExpectations.put(uri.toString(), cursor);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
new file mode 100644
index 000000000..6b0bbc279
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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 java.util.Locale;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+@LargeTest
+public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
+ public void testGetFacilitator() {
+ final DictionaryFacilitatorLruCache cache =
+ new DictionaryFacilitatorLruCache(getContext(), "");
+
+ final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
+ assertNotNull(dictionaryFacilitatorEnUs);
+ assertTrue(dictionaryFacilitatorEnUs.isForLocale(Locale.US));
+
+ final DictionaryFacilitator dictionaryFacilitatorFr = cache.get(Locale.FRENCH);
+ assertNotNull(dictionaryFacilitatorEnUs);
+ assertTrue(dictionaryFacilitatorFr.isForLocale(Locale.FRENCH));
+
+ final DictionaryFacilitator dictionaryFacilitatorDe = cache.get(Locale.GERMANY);
+ assertNotNull(dictionaryFacilitatorDe);
+ assertTrue(dictionaryFacilitatorDe.isForLocale(Locale.GERMANY));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
deleted file mode 100644
index e6fb28260..000000000
--- a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.util.ArrayList;
-import java.util.Locale;
-
-import android.content.Context;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
-
-/**
- * Unit test for DistracterFilter
- */
-@LargeTest
-public class DistracterFilterTest extends AndroidTestCase {
- private DistracterFilterCheckingExactMatchesAndSuggestions mDistracterFilter;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- final Context context = getContext();
- mDistracterFilter = new DistracterFilterCheckingExactMatchesAndSuggestions(context);
- RichInputMethodManager.init(context);
- final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
- final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.US.toString(), "qwerty"));
- subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.FRENCH.toString(), "azerty"));
- subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.GERMAN.toString(), "qwertz"));
- mDistracterFilter.updateEnabledSubtypes(subtypes);
- }
-
- public void testIsDistractorToWordsInDictionaries() {
- final PrevWordsInfo EMPTY_PREV_WORDS_INFO = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-
- final Locale localeEnUs = new Locale("en", "US");
- String typedWord;
-
- typedWord = "Bill";
- // For this test case, we consider "Bill" is a distracter to "bill".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "nOt";
- // For this test case, we consider "nOt" is a distracter to "not".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "youre";
- // For this test case, we consider "youre" is a distracter to "you're".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "Banana";
- // For this test case, we consider "Banana" is a distracter to "banana".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "orange";
- // For this test case, we consider "orange" is not a distracter to any word in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "Orange";
- // For this test case, we consider "Orange" is a distracter to "orange".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "café";
- // For this test case, we consider "café" is a distracter to "cafe".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "cafe";
- // For this test case, we consider "cafe" is not a distracter to any word in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "I'll";
- // For this test case, we consider "I'll" is not a distracter to any word in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "ill";
- // For this test case, we consider "ill" is a distracter to "I'll"
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "asdfd";
- // For this test case, we consider "asdfd" is not a distracter to any word in dictionaries.
- assertFalse(
- mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "thank";
- // For this test case, we consider "thank" is not a distracter to any other word
- // in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "thabk";
- // For this test case, we consider "thabk" is a distracter to "thank"
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "thanks";
- // For this test case, we consider "thanks" is not a distracter to any other word
- // in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "thabks";
- // For this test case, we consider "thabks" is a distracter to "thanks"
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "think";
- // For this test case, we consider "think" is not a distracter to any other word
- // in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "thibk";
- // For this test case, we consider "thibk" is a distracter to "think"
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- typedWord = "tgis";
- // For this test case, we consider "tgis" is a distracter to "this"
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
- final Locale localeDeDe = new Locale("de");
-
- typedWord = "fUEr";
- // For this test case, we consider "fUEr" is a distracter to "für".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
- typedWord = "fuer";
- // For this test case, we consider "fuer" is a distracter to "für".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
- typedWord = "fur";
- // For this test case, we consider "fur" is a distracter to "für".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
- final Locale localeFrFr = new Locale("fr");
-
- typedWord = "a";
- // For this test case, we consider "a" is a distracter to "à".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
- typedWord = "à";
- // For this test case, we consider "à" is not a distracter to any word in dictionaries.
- assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
- typedWord = "etre";
- // For this test case, we consider "etre" is a distracter to "être".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
- typedWord = "États-unis";
- // For this test case, we consider "États-unis" is a distracter to "États-Unis".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
- typedWord = "ÉtatsUnis";
- // For this test case, we consider "ÉtatsUnis" is a distracter to "États-Unis".
- assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
- EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
deleted file mode 100644
index 09309bcc0..000000000
--- a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
+++ /dev/null
@@ -1,52 +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.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.ProbabilityInfo;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-
-import java.util.HashMap;
-
-/**
- * Unit test for FusionDictionary
- */
-@SmallTest
-public class FusionDictionaryTests extends AndroidTestCase {
- public void testFindWordInTree() {
- FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- new DictionaryOptions(new HashMap<String,String>()));
-
- dict.add("abc", new ProbabilityInfo(10), null, false /* isNotAWord */);
- assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
-
- dict.add("aa", new ProbabilityInfo(10), null, false /* isNotAWord */);
- assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
- assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aa"));
-
- dict.add("babcd", new ProbabilityInfo(10), null, false /* isNotAWord */);
- dict.add("bacde", new ProbabilityInfo(10), null, false /* isNotAWord */);
- 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 59b858dbd..02cd21c8d 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -16,15 +16,33 @@
package com.android.inputmethod.latin;
+import static android.test.MoreAsserts.assertNotEqual;
+
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.view.inputmethod.BaseInputConnection;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
import com.android.inputmethod.latin.settings.Settings;
@LargeTest
public class InputLogicTests extends InputTestsBase {
+ private boolean mNextWordPrediction;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mNextWordPrediction = getBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, true);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mNextWordPrediction, true);
+ super.tearDown();
+ }
+
public void testTypeWord() {
final String WORD_TO_TYPE = "abcd";
type(WORD_TO_TYPE);
@@ -36,7 +54,7 @@ public class InputLogicTests extends InputTestsBase {
final String EXPECTED_RESULT = "thi";
type(WORD_TO_TYPE);
pickSuggestionManually(WORD_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
type(Constants.CODE_DELETE);
assertEquals("press suggestion then backspace", EXPECTED_RESULT,
mEditText.getText().toString());
@@ -49,7 +67,7 @@ public class InputLogicTests extends InputTestsBase {
type(WORD_TO_TYPE);
// Choose the auto-correction. For "tgis", the auto-correction should be "this".
pickSuggestionManually(WORD_TO_PICK);
- mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK,
mEditText.getText().toString());
type(Constants.CODE_DELETE);
@@ -63,7 +81,7 @@ public class InputLogicTests extends InputTestsBase {
type(WORD_TO_TYPE);
// Choose the typed word.
pickSuggestionManually(WORD_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE,
mEditText.getText().toString());
type(Constants.CODE_DELETE);
@@ -78,7 +96,7 @@ public class InputLogicTests extends InputTestsBase {
type(WORD_TO_TYPE);
// Choose the second suggestion, which should be "thus" when "tgis" is typed.
pickSuggestionManually(WORD_TO_PICK);
- mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
assertEquals("pick different suggestion then backspace", WORD_TO_PICK,
mEditText.getText().toString());
type(Constants.CODE_DELETE);
@@ -93,7 +111,8 @@ public class InputLogicTests extends InputTestsBase {
final int SELECTION_END = 19;
final String EXPECTED_RESULT = "some text some text";
type(STRING_TO_TYPE);
- // There is no IMF to call onUpdateSelection for us so we must do it by hand.
+ // Don't use the sendUpdateForCursorMove* family of methods here because they
+ // don't handle selections.
// Send once to simulate the cursor actually responding to the move caused by typing.
// This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor
// move with a move triggered by LatinIME inputting stuff.
@@ -113,7 +132,8 @@ public class InputLogicTests extends InputTestsBase {
final int SELECTION_END = 19;
final String EXPECTED_RESULT = "some text some text";
type(STRING_TO_TYPE);
- // There is no IMF to call onUpdateSelection for us so we must do it by hand.
+ // Don't use the sendUpdateForCursorMove* family of methods here because they
+ // don't handle selections.
// Send once to simulate the cursor actually responding to the move caused by typing.
// This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor
// move with a move triggered by LatinIME inputting stuff.
@@ -152,49 +172,90 @@ public class InputLogicTests extends InputTestsBase {
final String STRING_TO_TYPE = "tgis.";
final String EXPECTED_RESULT = "tgis.";
type(STRING_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
type(Constants.CODE_DELETE);
assertEquals("auto-correct with period then revert", EXPECTED_RESULT,
mEditText.getText().toString());
}
public void testAutoCorrectWithSpaceThenRevert() {
+ // Backspacing to cancel the "tgis"->"this" autocorrection should result in
+ // a "phantom space": if the user presses space immediately after,
+ // only one space will be inserted in total.
final String STRING_TO_TYPE = "tgis ";
- final String EXPECTED_RESULT = "tgis ";
+ final String EXPECTED_RESULT = "tgis";
type(STRING_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
type(Constants.CODE_DELETE);
assertEquals("auto-correct with space then revert", EXPECTED_RESULT,
mEditText.getText().toString());
}
+ public void testAutoCorrectWithSpaceThenRevertThenTypeMore() {
+ final String STRING_TO_TYPE_FIRST = "tgis ";
+ final String STRING_TO_TYPE_SECOND = "a";
+ final String EXPECTED_RESULT = "tgis a";
+ type(STRING_TO_TYPE_FIRST);
+ sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length());
+ type(Constants.CODE_DELETE);
+
+ type(STRING_TO_TYPE_SECOND);
+ sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length() - 1
+ + STRING_TO_TYPE_SECOND.length());
+ assertEquals("auto-correct with space then revert then type more", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
public void testAutoCorrectToSelfDoesNotRevert() {
final String STRING_TO_TYPE = "this ";
final String EXPECTED_RESULT = "this";
type(STRING_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+ sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
type(Constants.CODE_DELETE);
assertEquals("auto-correct with space does not revert", EXPECTED_RESULT,
mEditText.getText().toString());
}
public void testDoubleSpace() {
- // Set default pref just in case
- setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
// U+1F607 is an emoji
final String[] STRINGS_TO_TYPE =
new String[] { "this ", "a+ ", "\u1F607 ", ".. ", ") ", "( ", "% " };
final String[] EXPECTED_RESULTS =
new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "%. " };
- for (int i = 0; i < STRINGS_TO_TYPE.length; ++i) {
+ verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS);
+ }
+
+ public void testDoubleSpaceHindi() {
+ changeLanguage("hi");
+ // U+1F607 is an emoji
+ final String[] STRINGS_TO_TYPE =
+ new String[] { "this ", "a+ ", "\u1F607 ", "|| ", ") ", "( ", "% " };
+ final String[] EXPECTED_RESULTS =
+ new String[] { "this| ", "a+| ", "\u1F607| ", "|| ", ")| ", "( ", "%| " };
+ verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS);
+ }
+
+ private void verifyDoubleSpace(String[] stringsToType, String[] expectedResults) {
+ // Set default pref just in case
+ setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
+ for (int i = 0; i < stringsToType.length; ++i) {
mEditText.setText("");
- type(STRINGS_TO_TYPE[i]);
- assertEquals("double space processing", EXPECTED_RESULTS[i],
+ type(stringsToType[i]);
+ assertEquals("double space processing", expectedResults[i],
mEditText.getText().toString());
}
}
- public void testCancelDoubleSpace() {
+ public void testCancelDoubleSpaceEnglish() {
+ final String STRING_TO_TYPE = "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());
+ }
+
+ public void testCancelDoubleSpaceHindi() {
+ changeLanguage("hi");
final String STRING_TO_TYPE = "this ";
final String EXPECTED_RESULT = "this ";
type(STRING_TO_TYPE);
@@ -243,9 +304,9 @@ public class InputLogicTests extends InputTestsBase {
public void testDoubleSpacePeriod() {
// Reset settings to default, else these tests will go flaky.
setBooleanPreference(Settings.PREF_SHOW_SUGGESTIONS, true, true);
- setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD, "1", "1");
+ setBooleanPreference(Settings.PREF_AUTO_CORRECTION, true, true);
setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
- testDoubleSpacePeriodWithSettings(true /* expectsPeriod */);
+ testDoubleSpacePeriodWithSettings(true);
// "Suggestion visibility" to off
testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false);
// "Suggestion visibility" to on
@@ -255,18 +316,16 @@ public class InputLogicTests extends InputTestsBase {
testDoubleSpacePeriodWithSettings(false, Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false);
// "Auto-correction" to "off"
- testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0");
- // "Auto-correction" to "modest"
- testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "1");
- // "Auto-correction" to "very aggressive"
- testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "3");
+ testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, false);
+ // "Auto-correction" to "on"
+ testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, true);
// "Suggestion visibility" to "always hide" and "Auto-correction" to "off"
testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false,
- Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0");
+ Settings.PREF_AUTO_CORRECTION, false);
// "Suggestion visibility" to "always hide" and "Auto-correction" to "off"
testDoubleSpacePeriodWithSettings(false, Settings.PREF_SHOW_SUGGESTIONS, false,
- Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0",
+ Settings.PREF_AUTO_CORRECTION, false,
Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false);
}
@@ -276,10 +335,9 @@ public class InputLogicTests extends InputTestsBase {
final String EXPECTED_RESULT = "this ";
final int NEW_CURSOR_POSITION = 0;
type(STRING_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+ sendUpdateForCursorMoveTo(typedLength);
mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
- mLatinIME.onUpdateSelection(typedLength, typedLength,
- NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
+ sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
type(Constants.CODE_DELETE);
assertEquals("auto correct then move cursor to start of line then backspace",
EXPECTED_RESULT, mEditText.getText().toString());
@@ -291,10 +349,9 @@ public class InputLogicTests extends InputTestsBase {
final String EXPECTED_RESULT = "andthis ";
final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t');
type(STRING_TO_TYPE);
- mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+ sendUpdateForCursorMoveTo(typedLength);
mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
- mLatinIME.onUpdateSelection(typedLength, typedLength,
- NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
+ sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
type(Constants.CODE_DELETE);
assertEquals("auto correct then move cursor then backspace",
EXPECTED_RESULT, mEditText.getText().toString());
@@ -329,8 +386,8 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString());
}
- // This test matches the one in InputLogicTestsNonEnglish. In some non-English languages,
- // ! and ? are clustering punctuation signs.
+ // This test matches testClusteringPunctuationForFrench.
+ // In some non-English languages, ! and ? are clustering punctuation signs.
public void testClusteringPunctuation() {
final String WORD1_TO_TYPE = "test";
final String WORD2_TO_TYPE = "!!?!:!";
@@ -394,7 +451,7 @@ public class InputLogicTests extends InputTestsBase {
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
assertEquals("resume suggestion on backspace", -1,
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
- mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+ sendUpdateForCursorMoveTo(typedLength);
type(Constants.CODE_DELETE);
assertEquals("resume suggestion on backspace", 4,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -429,44 +486,25 @@ public class InputLogicTests extends InputTestsBase {
type(" ");
helperTestComposing("a'", true);
}
+
// TODO: Add some tests for non-BMP characters
public void testAutoCorrectByUserHistory() {
- final String WORD_TO_BE_CORRECTED = "qpmx";
- final String NOT_CORRECTED_RESULT = "qpmx ";
- final String DESIRED_WORD = "qpmz";
- final String CORRECTED_RESULT = "qpmz ";
- final int typeCountNotToAutocorrect = 1;
- final int typeCountToAutoCorrect = 16;
- int startIndex = 0;
- int endIndex = 0;
-
- for (int i = 0; i < typeCountNotToAutocorrect; i++) {
- type(DESIRED_WORD);
- type(Constants.CODE_SPACE);
- }
- startIndex = mEditText.getText().length();
- type(WORD_TO_BE_CORRECTED);
+ type("qpmz");
type(Constants.CODE_SPACE);
- endIndex = mEditText.getText().length();
- assertEquals("not auto-corrected by user history", NOT_CORRECTED_RESULT,
- mEditText.getText().subSequence(startIndex, endIndex).toString());
- for (int i = typeCountNotToAutocorrect; i < typeCountToAutoCorrect; i++) {
- type(DESIRED_WORD);
- type(Constants.CODE_SPACE);
- }
- startIndex = mEditText.getText().length();
- type(WORD_TO_BE_CORRECTED);
+
+ int startIndex = mEditText.getText().length();
+ type("qpmx");
type(Constants.CODE_SPACE);
- endIndex = mEditText.getText().length();
+ int endIndex = mEditText.getText().length();
assertEquals("auto-corrected by user history",
- CORRECTED_RESULT, mEditText.getText().subSequence(startIndex, endIndex).toString());
+ "qpmz ", mEditText.getText().subSequence(startIndex, endIndex).toString());
}
public void testPredictionsAfterSpace() {
final String WORD_TO_TYPE = "Barack ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -476,24 +514,19 @@ public class InputLogicTests extends InputTestsBase {
public void testPredictionsWithDoubleSpaceToPeriod() {
mLatinIME.clearPersonalizedDictionariesForTest();
- final String WORD_TO_TYPE = "Barack ";
+ final String WORD_TO_TYPE = "Barack ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
- // No need to test here, testPredictionsAfterSpace is testing it already
- type(" ");
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
- runMessages();
- // Test the predictions have been cleared
- SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
- assertEquals("predictions cleared after double-space-to-period", suggestedWords.size(), 0);
+
type(Constants.CODE_DELETE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
- // Test the first prediction is displayed
+
+ SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("predictions after cancel double-space-to-period", "Obama",
- suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
+ mLatinIME.getSuggestedWordsForTest().getWord(0));
}
public void testPredictionsAfterManualPick() {
@@ -501,7 +534,7 @@ public class InputLogicTests extends InputTestsBase {
type(WORD_TO_TYPE);
// Choose the auto-correction. For "Barack", the auto-correction should be "Barack".
pickSuggestionManually(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -513,17 +546,11 @@ public class InputLogicTests extends InputTestsBase {
mLatinIME.clearPersonalizedDictionariesForTest();
final String WORD_TO_TYPE = "Barack. ";
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
- SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
- assertEquals("No prediction after period after inputting once.", 0, suggestedWords.size());
- type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
- runMessages();
- suggestedWords = mLatinIME.getSuggestedWordsForTest();
- assertEquals("Beginning-of-Sentence prediction after inputting 2 times.", "Barack",
- suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
+ SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
+ assertFalse(mLatinIME.getSuggestedWordsForTest().isEmpty());
}
public void testPredictionsAfterRecorrection() {
@@ -535,27 +562,23 @@ public class InputLogicTests extends InputTestsBase {
final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length();
final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack"
type(PREFIX);
- mLatinIME.onUpdateSelection(0, 0, endOfPrefix, endOfPrefix, -1, -1);
+ sendUpdateForCursorMoveTo(endOfPrefix);
type(WORD_TO_TYPE);
pickSuggestionManually(FIRST_NON_TYPED_SUGGESTION);
- mLatinIME.onUpdateSelection(endOfPrefix, endOfPrefix, endOfSuggestion, endOfSuggestion,
- -1, -1);
+ sendUpdateForCursorMoveTo(endOfSuggestion);
runMessages();
type(" ");
- mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion,
- endOfSuggestion + 1, endOfSuggestion + 1, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sendUpdateForCursorMoveBy(1);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Simulate a manual cursor move
mInputConnection.setSelection(indexForManualCursor, indexForManualCursor);
- mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1,
- indexForManualCursor, indexForManualCursor, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sendUpdateForCursorMoveTo(indexForManualCursor);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
pickSuggestionManually(WORD_TO_TYPE);
- mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor,
- endOfWord, endOfWord, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sendUpdateForCursorMoveTo(endOfWord);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Test the first prediction is displayed
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -603,7 +626,7 @@ public class InputLogicTests extends InputTestsBase {
for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
type(WORD_TO_TYPE.substring(i, i+1));
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
assertEquals("type many trailing single quotes one by one", EXPECTED_RESULT,
@@ -615,26 +638,148 @@ public class InputLogicTests extends InputTestsBase {
final String EXPECTED_RESULT = WORD_TO_TYPE;
for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
type(WORD_TO_TYPE.substring(i, i+1));
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
assertEquals("type words letter by letter", EXPECTED_RESULT,
mEditText.getText().toString());
}
- public void testSwitchLanguages() {
- final String WORD_TO_TYPE_FIRST_PART = "com";
- final String WORD_TO_TYPE_SECOND_PART = "md";
- final String EXPECTED_RESULT = "comme";
- changeLanguage("en");
- type(WORD_TO_TYPE_FIRST_PART);
+ public void testBasicGesture() {
+ gesture("this");
+ assertEquals("this", mEditText.getText().toString());
+ }
+
+ public void testGestureGesture() {
+ gesture("got");
+ gesture("milk");
+ assertEquals("got milk", mEditText.getText().toString());
+ }
+
+ public void testGestureBackspaceGestureAgain() {
+ gesture("this");
+ type(Constants.CODE_DELETE);
+ assertEquals("gesture then backspace", "", mEditText.getText().toString());
+ gesture("this");
+ if (DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION) {
+ assertNotEqual("this", mEditText.getText().toString());
+ } else {
+ assertEquals("this", mEditText.getText().toString());
+ }
+ }
+
+ private void typeOrGestureWordAndPutCursorInside(final boolean gesture, final String word,
+ final int startPos) {
+ final int END_OF_WORD = startPos + word.length();
+ final int NEW_CURSOR_POSITION = startPos + word.length() / 2;
+ if (gesture) {
+ gesture(word);
+ } else {
+ type(word);
+ }
+ sendUpdateForCursorMoveTo(END_OF_WORD);
+ runMessages();
+ sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
+ runMessages();
+ }
+
+ private void typeWordAndPutCursorInside(final String word, final int startPos) {
+ typeOrGestureWordAndPutCursorInside(false /* gesture */, word, startPos);
+ }
+
+ private void gestureWordAndPutCursorInside(final String word, final int startPos) {
+ typeOrGestureWordAndPutCursorInside(true /* gesture */, word, startPos);
+ }
+
+ private void ensureComposingSpanPos(final String message, final int from, final int to) {
+ assertEquals(message, from, BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals(message, to, BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ }
+
+ public void testTypeWithinComposing() {
+ final String WORD_TO_TYPE = "something";
+ final String EXPECTED_RESULT = "some thing";
+ typeWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */);
+ type(" ");
+ ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1);
+ assertEquals("space in the middle of a composing word", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ int cursorPos = sendUpdateForCursorMoveToEndOfLine();
+ runMessages();
+ type(" ");
+ assertEquals("mbo", "some thing ", mEditText.getText().toString());
+ typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */);
+ type(Constants.CODE_DELETE);
+ ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1);
+ }
+
+ public void testTypeWithinGestureComposing() {
+ final String WORD_TO_TYPE = "something";
+ final String EXPECTED_RESULT = "some thing";
+ gestureWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */);
+ type(" ");
+ ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1);
+ assertEquals("space in the middle of a composing word", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ int cursorPos = sendUpdateForCursorMoveToEndOfLine();
+ runMessages();
+ type(" ");
+ typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */);
+ type(Constants.CODE_DELETE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
+ ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1);
+ }
+
+ public void testManualPickThenSeparatorForFrench() {
+ final String WORD1_TO_TYPE = "test";
+ final String WORD2_TO_TYPE = "!";
+ final String EXPECTED_RESULT = "test !";
changeLanguage("fr");
+ type(WORD1_TO_TYPE);
+ pickSuggestionManually(WORD1_TO_TYPE);
+ type(WORD2_TO_TYPE);
+ assertEquals("manual pick then separator for French", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testClusteringPunctuationForFrench() {
+ final String WORD1_TO_TYPE = "test";
+ final String WORD2_TO_TYPE = "!!?!:!";
+ // In English, the expected result would be "test!!?!:!"
+ final String EXPECTED_RESULT = "test !!?! : !";
+ changeLanguage("fr");
+ type(WORD1_TO_TYPE);
+ pickSuggestionManually(WORD1_TO_TYPE);
+ type(WORD2_TO_TYPE);
+ assertEquals("clustering punctuation for French", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testWordThenSpaceThenPunctuationFromStripTwice() {
+ setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, false, true);
+
+ final String WORD_TO_TYPE = "test ";
+ final String PUNCTUATION_FROM_STRIP = "!";
+ final String EXPECTED_RESULT = "test!! ";
+ type(WORD_TO_TYPE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
- type(WORD_TO_TYPE_SECOND_PART);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ assertTrue("type word then type space should display punctuation strip",
+ mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
+ pickSuggestionManually(PUNCTUATION_FROM_STRIP);
+ pickSuggestionManually(PUNCTUATION_FROM_STRIP);
+ assertEquals(EXPECTED_RESULT, mEditText.getText().toString());
+ }
+
+ public void testWordThenSpaceDisplaysPredictions() {
+ final String WORD_TO_TYPE = "Barack ";
+ final String EXPECTED_RESULT = "Obama";
+ type(WORD_TO_TYPE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
- assertEquals("Suggestions updated after switching languages",
- EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
+ assertEquals("type word then type space yields predictions for French",
+ EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
new file mode 100644
index 000000000..4b44138a7
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2014 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 com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.ArrayList;
+
+@LargeTest
+public class InputLogicTestsDeadKeys extends InputTestsBase {
+ // A helper class for readability
+ static class EventList extends ArrayList<Event> {
+ public EventList addCodePoint(final int codePoint, final boolean isDead) {
+ final Event event;
+ if (isDead) {
+ event = Event.createDeadEvent(codePoint, Event.NOT_A_KEY_CODE, null /* next */);
+ } else {
+ event = Event.createSoftwareKeypressEvent(codePoint, Event.NOT_A_KEY_CODE,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+ false /* isKeyRepeat */);
+ }
+ add(event);
+ return this;
+ }
+
+ public EventList addKey(final int keyCode) {
+ add(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT, keyCode,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+ false /* isKeyRepeat */));
+ return this;
+ }
+ }
+
+ public void testDeadCircumflexSimple() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final String EXPECTED_RESULT = "aê";
+ final EventList events = new EventList()
+ .addCodePoint('a', false)
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+ .addCodePoint('e', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("simple dead circumflex", EXPECTED_RESULT, mEditText.getText().toString());
+ }
+
+ public void testDeadCircumflexBackspace() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final String EXPECTED_RESULT = "ae";
+ final EventList events = new EventList()
+ .addCodePoint('a', false)
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+ .addKey(Constants.CODE_DELETE)
+ .addCodePoint('e', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead circumflex backspace", EXPECTED_RESULT, mEditText.getText().toString());
+ }
+
+ public void testDeadCircumflexFeedback() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final String EXPECTED_RESULT = "a\u02C6";
+ final EventList events = new EventList()
+ .addCodePoint('a', false)
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead circumflex gives feedback", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDeadDiaeresisSpace() {
+ final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+ final String EXPECTED_RESULT = "a\u00A8e\u00A8i";
+ final EventList events = new EventList()
+ .addCodePoint('a', false)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addCodePoint(Constants.CODE_SPACE, false)
+ .addCodePoint('e', false)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addCodePoint(Constants.CODE_ENTER, false)
+ .addCodePoint('i', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead diaeresis space commits the dead char", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDeadAcuteLetterBackspace() {
+ final int MODIFIER_LETTER_ACUTE = 0xB4;
+ final String EXPECTED_RESULT1 = "aá";
+ final String EXPECTED_RESULT2 = "a";
+ final EventList events = new EventList()
+ .addCodePoint('a', false)
+ .addCodePoint(MODIFIER_LETTER_ACUTE, true)
+ .addCodePoint('a', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead acute on a typed", EXPECTED_RESULT1, mEditText.getText().toString());
+ mLatinIME.onEvent(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT,
+ Constants.CODE_DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+ false /* isKeyRepeat */));
+ assertEquals("a with acute deleted", EXPECTED_RESULT2, mEditText.getText().toString());
+ }
+
+ public void testFinnishStroke() {
+ final int MODIFIER_LETTER_STROKE = '-';
+ final String EXPECTED_RESULT = "x\u0110\u0127";
+ final EventList events = new EventList()
+ .addCodePoint('x', false)
+ .addCodePoint(MODIFIER_LETTER_STROKE, true)
+ .addCodePoint('D', false)
+ .addCodePoint(MODIFIER_LETTER_STROKE, true)
+ .addCodePoint('h', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("Finnish dead stroke", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDoubleDeadOgonek() {
+ final int MODIFIER_LETTER_OGONEK = 0x02DB;
+ final String EXPECTED_RESULT = "txǫs\u02DBfk";
+ final EventList events = new EventList()
+ .addCodePoint('t', false)
+ .addCodePoint('x', false)
+ .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+ .addCodePoint('o', false)
+ .addCodePoint('s', false)
+ .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+ .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+ .addCodePoint('f', false)
+ .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+ .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+ .addKey(Constants.CODE_DELETE)
+ .addCodePoint('k', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("double dead ogonek, and backspace", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDeadCircumflexDeadDiaeresis() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+ final String EXPECTED_RESULT = "r̂̈";
+
+ final EventList events = new EventList()
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addCodePoint('r', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("both circumflex and diaeresis on r", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDeadCircumflexDeadDiaeresisBackspace() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+ final String EXPECTED_RESULT = "û";
+
+ final EventList events = new EventList()
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addKey(Constants.CODE_DELETE)
+ .addCodePoint('u', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead circumflex, dead diaeresis, backspace, u", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+
+ public void testDeadCircumflexDoubleDeadDiaeresisBackspace() {
+ final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+ final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+ final String EXPECTED_RESULT = "\u02C6u";
+
+ final EventList events = new EventList()
+ .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+ .addKey(Constants.CODE_DELETE)
+ .addCodePoint('u', false);
+ for (final Event event : events) {
+ mLatinIME.onEvent(event);
+ }
+ assertEquals("dead circumflex, double dead diaeresis, backspace, u", EXPECTED_RESULT,
+ mEditText.getText().toString());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
index 2560407dc..12461c96e 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
@@ -19,6 +19,8 @@ package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.inputmethod.BaseInputConnection;
+import com.android.inputmethod.latin.common.Constants;
+
@LargeTest
public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
public void testAutoCorrectForLanguageWithoutSpaces() {
@@ -74,7 +76,7 @@ public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
mLatinIME.onUpdateSelection(typedLength, typedLength,
CURSOR_POS, CURSOR_POS, -1, -1);
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertEquals("start composing inside text", -1,
BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -87,11 +89,39 @@ public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
}
+ public void testMovingCursorInsideWordAndType() {
+ final String WORD_TO_TYPE = "abcdefgh";
+ final int typedLength = WORD_TO_TYPE.length();
+ final int CURSOR_POS = 4;
+ changeKeyboardLocaleAndDictLocale("th", "en_US");
+ type(WORD_TO_TYPE);
+ mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, 0, typedLength);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+ runMessages();
+ mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
+ mLatinIME.onUpdateSelection(typedLength, typedLength,
+ CURSOR_POS, CURSOR_POS, 0, typedLength);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+ runMessages();
+ assertEquals("move cursor inside text", 0,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("move cursor inside text", typedLength,
+ BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+ type("x");
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+ runMessages();
+ assertEquals("start typing while cursor inside composition", CURSOR_POS,
+ BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+ assertEquals("start typing while cursor inside composition", CURSOR_POS + 1,
+ 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);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
// Make sure there is no space
assertEquals("predictions in lang without spaces", "Barack",
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
deleted file mode 100644
index 866f8894c..000000000
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ /dev/null
@@ -1,124 +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.test.suitebuilder.annotation.LargeTest;
-
-@LargeTest
-public class InputLogicTestsNonEnglish extends InputTestsBase {
- final String NEXT_WORD_PREDICTION_OPTION = "next_word_prediction";
-
- public void testAutoCorrectForFrench() {
- final String STRING_TO_TYPE = "irq ";
- final String EXPECTED_RESULT = "ira ";
- changeLanguage("fr");
- type(STRING_TO_TYPE);
- assertEquals("simple auto-correct for French", EXPECTED_RESULT,
- mEditText.getText().toString());
- }
-
- public void testManualPickThenSeparatorForFrench() {
- final String WORD1_TO_TYPE = "test";
- final String WORD2_TO_TYPE = "!";
- final String EXPECTED_RESULT = "test !";
- changeLanguage("fr");
- type(WORD1_TO_TYPE);
- pickSuggestionManually(WORD1_TO_TYPE);
- type(WORD2_TO_TYPE);
- assertEquals("manual pick then separator for French", EXPECTED_RESULT,
- mEditText.getText().toString());
- }
-
- public void testClusteringPunctuationForFrench() {
- final String WORD1_TO_TYPE = "test";
- final String WORD2_TO_TYPE = "!!?!:!";
- // In English, the expected result would be "test!!?!:!"
- final String EXPECTED_RESULT = "test !!?! : !";
- changeLanguage("fr");
- type(WORD1_TO_TYPE);
- pickSuggestionManually(WORD1_TO_TYPE);
- type(WORD2_TO_TYPE);
- assertEquals("clustering punctuation for French", EXPECTED_RESULT,
- mEditText.getText().toString());
- }
-
- public void testWordThenSpaceThenPunctuationFromStripTwiceForFrench() {
- final String WORD_TO_TYPE = "test ";
- final String PUNCTUATION_FROM_STRIP = "!";
- final String EXPECTED_RESULT = "test !!";
- final boolean defaultNextWordPredictionOption =
- mLatinIME.getResources().getBoolean(R.bool.config_default_next_word_prediction);
- final boolean previousNextWordPredictionOption =
- setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, false,
- defaultNextWordPredictionOption);
- try {
- changeLanguage("fr");
- type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
- runMessages();
- assertTrue("type word then type space should display punctuation strip",
- mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
- pickSuggestionManually(PUNCTUATION_FROM_STRIP);
- pickSuggestionManually(PUNCTUATION_FROM_STRIP);
- assertEquals("type word then type space then punctuation from strip twice for French",
- EXPECTED_RESULT, mEditText.getText().toString());
- } finally {
- setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, previousNextWordPredictionOption,
- defaultNextWordPredictionOption);
- }
- }
-
- public void testWordThenSpaceDisplaysPredictions() {
- final String WORD_TO_TYPE = "beaujolais ";
- final String EXPECTED_RESULT = "nouveau";
- final boolean defaultNextWordPredictionOption =
- mLatinIME.getResources().getBoolean(R.bool.config_default_next_word_prediction);
- final boolean previousNextWordPredictionOption =
- setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, true,
- defaultNextWordPredictionOption);
- try {
- changeLanguage("fr");
- type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
- runMessages();
- final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
- assertEquals("type word then type space yields predictions for French",
- EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
- } finally {
- setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, previousNextWordPredictionOption,
- defaultNextWordPredictionOption);
- }
- }
-
- public void testAutoCorrectForGerman() {
- final String STRING_TO_TYPE = "unf ";
- final String EXPECTED_RESULT = "und ";
- changeLanguage("de");
- type(STRING_TO_TYPE);
- assertEquals("simple auto-correct for German", EXPECTED_RESULT,
- mEditText.getText().toString());
- }
-
- public void testAutoCorrectWithUmlautForGerman() {
- final String STRING_TO_TYPE = "ueber ";
- final String EXPECTED_RESULT = "über ";
- changeLanguage("de");
- type(STRING_TO_TYPE);
- assertEquals("auto-correct with umlaut for German", EXPECTED_RESULT,
- mEditText.getText().toString());
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
deleted file mode 100644
index ab69c8592..000000000
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
+++ /dev/null
@@ -1,237 +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.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.util.Pair;
-
-/*
- * Relevant characters for this test :
- * Spurs the need to reorder :
- * U+1031 MYANMAR VOWEL SIGN E : ေ
- * U+1004 U+103A U+1039 Kinzi. It's a compound character.
- *
- * List of consonants :
- * U+1000 MYANMAR LETTER KA က
- * U+1001 MYANMAR LETTER KHA ခ
- * U+1002 MYANMAR LETTER GA ဂ
- * U+1003 MYANMAR LETTER GHA ဃ
- * U+1004 MYANMAR LETTER NGA င
- * U+1005 MYANMAR LETTER CA စ
- * U+1006 MYANMAR LETTER CHA ဆ
- * U+1007 MYANMAR LETTER JA ဇ
- * U+1008 MYANMAR LETTER JHA ဈ
- * U+1009 MYANMAR LETTER NYA ဉ
- * U+100A MYANMAR LETTER NNYA ည
- * U+100B MYANMAR LETTER TTA ဋ
- * U+100C MYANMAR LETTER TTHA ဌ
- * U+100D MYANMAR LETTER DDA ဍ
- * U+100E MYANMAR LETTER DDHA ဎ
- * U+100F MYANMAR LETTER NNA ဏ
- * U+1010 MYANMAR LETTER TA တ
- * U+1011 MYANMAR LETTER THA ထ
- * U+1012 MYANMAR LETTER DA ဒ
- * U+1013 MYANMAR LETTER DHA ဓ
- * U+1014 MYANMAR LETTER NA န
- * U+1015 MYANMAR LETTER PA ပ
- * U+1016 MYANMAR LETTER PHA ဖ
- * U+1017 MYANMAR LETTER BA ဗ
- * U+1018 MYANMAR LETTER BHA ဘ
- * U+1019 MYANMAR LETTER MA မ
- * U+101A MYANMAR LETTER YA ယ
- * U+101B MYANMAR LETTER RA ရ
- * U+101C MYANMAR LETTER LA လ
- * U+101D MYANMAR LETTER WA ဝ
- * U+101E MYANMAR LETTER SA သ
- * U+101F MYANMAR LETTER HA ဟ
- * U+1020 MYANMAR LETTER LLA ဠ
- * U+103F MYANMAR LETTER GREAT SA ဿ
- *
- * List of medials :
- * U+103B MYANMAR CONSONANT SIGN MEDIAL YA ျ
- * U+103C MYANMAR CONSONANT SIGN MEDIAL RA ြ
- * U+103D MYANMAR CONSONANT SIGN MEDIAL WA ွ
- * U+103E MYANMAR CONSONANT SIGN MEDIAL HA ှ
- * U+105E MYANMAR CONSONANT SIGN MON MEDIAL NA ၞ
- * U+105F MYANMAR CONSONANT SIGN MON MEDIAL MA ၟ
- * U+1060 MYANMAR CONSONANT SIGN MON MEDIAL LA ၠ
- * U+1082 MYANMAR CONSONANT SIGN SHAN MEDIAL WA ႂ
- *
- * Other relevant characters :
- * U+200C ZERO WIDTH NON-JOINER
- * U+200B ZERO WIDTH SPACE
- */
-
-@LargeTest
-// These tests are inactive until the combining code for Myanmar Reordering is sorted out.
-@Suppress
-@SuppressWarnings("rawtypes")
-public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
- // The tests are formatted as follows.
- // Each test is an entry in the array of Pair arrays.
-
- // One test is an array of pairs. Each pair contains, in the `first' member,
- // the code points that the next key press should contain. In the `second'
- // member is stored the string that should be in the text view after this
- // key press.
-
- private static final Pair[][] TESTS = {
-
- // Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
- new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
- Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
- Pair.create(new int[] { 0x1000 }, "\u1000\u1031"), // ကေ
- Pair.create(new int[] { 0x101F }, "\u1000\u1031\u101F") // ကေဟ
- },
-
- new Pair[] { // Type : U+1000 U+1031 U+101F က ေ ဟ
- Pair.create(new int[] { 0x1000 }, "\u1000"), // က
- Pair.create(new int[] { 0x1031 }, "\u1000\u200B\u1031"), // က‌ေ
- Pair.create(new int[] { 0x101F }, "\u1000\u101F\u1031") // ကဟေ
- },
-
- new Pair[] { // Type : U+1031 U+101D U+103E U+1018 ေ ဝ ှ ဘ
- Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
- Pair.create(new int[] { 0x101D }, "\u101D\u1031"), // ဝေ
- Pair.create(new int[] { 0x103E }, "\u101D\u103E\u1031"), // ဝှေ
- Pair.create(new int[] { 0x1018 }, "\u101D\u103E\u1031\u1018") // ဝှေဘ
- },
-
- new Pair[] { // Type : U+1031 U+1014 U+1031 U+1000 U+102C U+1004 U+103A U+1038 U+101C
- // U+102C U+1038 U+104B ေ န ေ က ာ င ် း လ ာ း ။
- Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
- Pair.create(new int[] { 0x1014 }, "\u1014\u1031"), // နေ
- Pair.create(new int[] { 0x1031 }, "\u1014\u1031\u1031"), // နေ‌ေ
- Pair.create(new int[] { 0x1000 }, "\u1014\u1031\u1000\u1031"), // နေကေ
- Pair.create(new int[] { 0x102C }, "\u1014\u1031\u1000\u1031\u102C"), // နေကော
- Pair.create(new int[] { 0x1004 }, "\u1014\u1031\u1000\u1031\u102C\u1004"), // နေကောင
- Pair.create(new int[] { 0x103A }, // နေကောင်
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A"),
- Pair.create(new int[] { 0x1038 }, // နေကောင်း
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038"),
- Pair.create(new int[] { 0x101C }, // နေကောင်းလ
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C"),
- Pair.create(new int[] { 0x102C }, // နေကောင်းလာ
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C"),
- Pair.create(new int[] { 0x1038 }, // နေကောင်းလား
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038"),
- Pair.create(new int[] { 0x104B }, // နေကောင်းလား။
- "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038\u104B")
- },
-
- new Pair[] { // Type : U+1031 U+1031 U+1031 U+1000 ေ ေ ေ က
- Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
- Pair.create(new int[] { 0x1031 }, "\u1031\u1031"), // ေေ
- Pair.create(new int[] { 0x1031 }, "\u1031\u1031\u1031"), // U+1031ေေေ
- Pair.create(new int[] { 0x1000 }, "\u1031\u1031\u1000\u1031") // ေေကေ
- },
-
- new Pair[] { // Type : U+1031 U+1001 U+103B U+103D U+1038 ေ ခ ျ ွ း
- Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
- Pair.create(new int[] { 0x1001 }, "\u1001\u1031"), // ခေ
- Pair.create(new int[] { 0x103B }, "\u1001\u103B\u1031"), // ချေ
- Pair.create(new int[] { 0x103D }, "\u1001\u103B\u103D\u1031"), // ချွေ
- Pair.create(new int[] { 0x1038 }, "\u1001\u103B\u103D\u1031\u1038") // ချွေး
- },
-
- // Tests for Kinzi U+1004 U+103A U+1039 :
-
- /* Kinzi reordering is not implemented yet. Uncomment these tests when it is.
-
- new Pair[] { // Type : U+1021 U+1002 (U+1004 U+103A U+1039)
- // U+101C U+1014 U+103A အ ဂ (င ် ္) လ န ်
- Pair.create(new int[] { 0x1021 }, "\u1021"), // အ
- Pair.create(new int[] { 0x1002 }, "\u1021\u1002"), // အဂ
- Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // အင်္ဂ
- "\u1021\u1004\u103A\u1039\u1002"),
- Pair.create(new int[] { 0x101C }, // အင်္ဂလ
- "\u1021\u1004\u103A\u1039\u1002\u101C"),
- Pair.create(new int[] { 0x1014 }, // အင်္ဂလန
- "\u1021\u1004\u103A\u1039\u1002\u101C\u1014"),
- Pair.create(new int[] { 0x103A }, // အင်္ဂလန်
- "\u1021\u1004\u103A\u1039\u1002\u101C\u1014\u103A")
- },
-
- new Pair[] { //Type : kinzi after a whole syllable U+101E U+1001 U+103B U+102D U+102F
- // (U+1004 U+103A U+1039) U+1004 U+103A U+1038 သ ခ ျ ိ ု င ် ္ င ် း
- Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
- Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
- Pair.create(new int[] { 0x103B }, "\u101E\u1001\u103B"), // သချ
- Pair.create(new int[] { 0x102D }, "\u101E\u1001\u103B\u102D"), // သချိ
- Pair.create(new int[] { 0x102F }, "\u101E\u1001\u103B\u102D\u102F"), // သချို
- Pair.create(new int[] { 0x1004, 0x103A, 0x1039}, // သင်္ချို
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
- Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
- Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
- Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
- },
-
- new Pair[] { // Type : kinzi after the consonant U+101E U+1001 (U+1004 U+103A U+1039)
- // U+103B U+102D U+102F U+1004 U+103A U+1038 သ ခ င ် ္ ျ ိ ု င ် း
- Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
- Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
- Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // သင်္ခ
- "\u101E\u1004\u103A\u1039\u1001"),
- Pair.create(new int[] { 0x103B }, // သင်္ချ
- "\u101E\u1004\u103A\u1039\u1001\u103B"),
- Pair.create(new int[] { 0x102D }, // သင်္ချိ
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D"),
- Pair.create(new int[] { 0x102F }, // သင်္ချို
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
- Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
- Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
- Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
- "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
- },
- */
- };
-
- @SuppressWarnings("unchecked")
- private void doMyanmarTest(final int testNumber, final Pair[] test) {
- int stepNumber = 0;
- for (final Pair<int[], String> step : test) {
- ++stepNumber;
- final int[] input = step.first;
- final String expectedResult = step.second;
- if (input.length > 1) {
- mLatinIME.onTextInput(new String(input, 0, input.length));
- } else {
- type(input[0]);
- }
- assertEquals("Myanmar reordering test " + testNumber + ", step " + stepNumber,
- expectedResult, mEditText.getText().toString());
- }
- }
-
- public void testMyanmarReordering() {
- int testNumber = 0;
- changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
- for (final Pair[] test : TESTS) {
- // Small trick to reset LatinIME : setText("") and send updateSelection with values
- // LatinIME has never seen, and cursor pos 0,0.
- mEditText.setText("");
- mLatinIME.onUpdateSelection(1, 1, 0, 0, -1, -1);
- doMyanmarTest(++testNumber, test);
- }
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 986fb1097..dead53da2 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.content.SharedPreferences;
+import android.graphics.Point;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.test.ServiceTestCase;
@@ -36,12 +37,17 @@ import android.widget.EditText;
import android.widget.FrameLayout;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.event.Event;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.settings.DebugSettings;
import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Locale;
@@ -52,21 +58,28 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// Default value for auto-correction threshold. This is the string representation of the
// index in the resources array of auto-correction threshold settings.
- private static final String DEFAULT_AUTO_CORRECTION_THRESHOLD = "1";
+ private static final boolean DEFAULT_AUTO_CORRECTION = true;
// The message that sets the underline is posted with a 500 ms delay
- protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 500;
+ protected static final int DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS = 500;
// The message that sets predictions is posted with a 200 ms delay
- protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
- private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
+ protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS = 200;
+ // We wait for gesture computation for this delay
+ protected static final int DELAY_TO_WAIT_FOR_GESTURE_MILLIS = 200;
+ // If a dictionary takes longer to load, we could have serious problems.
+ private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 5;
+
+ // Type for a test phony dictionary
+ private static final String TYPE_TEST = "test";
+ private static final PhonyDictionary DICTIONARY_TEST = new PhonyDictionary(TYPE_TEST);
protected LatinIME mLatinIME;
protected Keyboard mKeyboard;
protected MyEditText mEditText;
protected View mInputView;
protected InputConnection mInputConnection;
+ private boolean mPreviousAutoCorrectSetting;
private boolean mPreviousBigramPredictionSettings;
- private String mPreviousAutoCorrectSetting;
// A helper class to ease span tests
public static class SpanGetter {
@@ -94,12 +107,15 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
throw new RuntimeException("Expected one span, found " + spans.length);
}
}
+ public SuggestionSpan getSpan() {
+ return (SuggestionSpan) mSpan;
+ }
public boolean isAutoCorrectionIndicator() {
return (mSpan instanceof SuggestionSpan) &&
- 0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & ((SuggestionSpan)mSpan).getFlags());
+ 0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & getSpan().getFlags());
}
public String[] getSuggestions() {
- return ((SuggestionSpan)mSpan).getSuggestions();
+ return getSpan().getSuggestions();
}
}
@@ -140,8 +156,6 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
super(LatinIMEForTests.class);
}
- // TODO: Isn't there a way to make this generic somehow? We can take a <T> and return a <T>
- // but we'd have to dispatch types on editor.put...() functions
protected boolean setBooleanPreference(final String key, final boolean value,
final boolean defaultValue) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
@@ -152,6 +166,11 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
return previousSetting;
}
+ protected boolean getBooleanPreference(final String key, final boolean defaultValue) {
+ return PreferenceManager.getDefaultSharedPreferences(mLatinIME)
+ .getBoolean(key, defaultValue);
+ }
+
protected String setStringPreference(final String key, final String value,
final String defaultValue) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
@@ -182,13 +201,17 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
| InputType.TYPE_TEXT_FLAG_MULTI_LINE;
mEditText.setInputType(inputType);
mEditText.setEnabled(true);
+ mLastCursorPos = 0;
+ if (null == Looper.myLooper()) {
+ Looper.prepare();
+ }
setupService();
mLatinIME = getService();
setDebugMode(true);
mPreviousBigramPredictionSettings = setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS,
true, true /* defaultValue */);
- mPreviousAutoCorrectSetting = setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
- DEFAULT_AUTO_CORRECTION_THRESHOLD, DEFAULT_AUTO_CORRECTION_THRESHOLD);
+ mPreviousAutoCorrectSetting = setBooleanPreference(Settings.PREF_AUTO_CORRECTION,
+ DEFAULT_AUTO_CORRECTION, DEFAULT_AUTO_CORRECTION);
mLatinIME.onCreate();
EditorInfo ei = new EditorInfo();
final InputConnection ic = mEditText.onCreateInputConnection(ei);
@@ -207,7 +230,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// Run messages to avoid the messages enqueued by startInputView() and its friends
// to run on a later call and ruin things. We need to wait first because some of them
// can be posted with a delay (notably, MSG_RESUME_SUGGESTIONS)
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
}
@@ -219,8 +242,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
mLatinIME.mHandler.removeAllMessages();
setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mPreviousBigramPredictionSettings,
true /* defaultValue */);
- setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD, mPreviousAutoCorrectSetting,
- DEFAULT_AUTO_CORRECTION_THRESHOLD);
+ setBooleanPreference(Settings.PREF_AUTO_CORRECTION, mPreviousAutoCorrectSetting,
+ DEFAULT_AUTO_CORRECTION);
setDebugMode(false);
mLatinIME.recycle();
super.tearDown();
@@ -236,7 +259,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
// is called, which has a lot of bad side effects. We can however just throw an exception
// in the runnable which will unwind the stack and allow us to exit.
- private final class InterruptRunMessagesException extends RuntimeException {
+ final class InterruptRunMessagesException extends RuntimeException {
// Empty class
}
protected void runMessages() {
@@ -263,14 +286,16 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
// but keep them in mind if something breaks. Commenting them out as is should work.
//mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
final Key key = mKeyboard.getKey(codePoint);
+ final Event event;
if (key == null) {
- mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
- isKeyRepeat);
+ event = Event.createSoftwareKeypressEvent(codePoint, Event.NOT_A_KEY_CODE,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, isKeyRepeat);
} else {
final int x = key.getX() + key.getWidth() / 2;
final int y = key.getY() + key.getHeight() / 2;
- mLatinIME.onCodeInput(codePoint, x, y, isKeyRepeat);
+ event = LatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
}
+ mLatinIME.onEvent(event);
// Also see the comment at the top of this function about onReleaseKey
//mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
}
@@ -289,6 +314,46 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
}
}
+ protected Point getXY(final int codePoint) {
+ final Key key = mKeyboard.getKey(codePoint);
+ if (key == null) {
+ throw new RuntimeException("Code point not on the keyboard");
+ }
+ return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
+ }
+
+ protected void gesture(final String stringToGesture) {
+ if (StringUtils.codePointCount(stringToGesture) < 2) {
+ throw new RuntimeException("Can't gesture strings less than 2 chars long");
+ }
+
+ mLatinIME.onStartBatchInput();
+ final int startCodePoint = stringToGesture.codePointAt(0);
+ Point oldPoint = getXY(startCodePoint);
+ int timestamp = 0; // In milliseconds since the start of the gesture
+ final InputPointers pointers = new InputPointers(Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
+ pointers.addPointer(oldPoint.x, oldPoint.y, 0 /* pointerId */, timestamp);
+
+ for (int i = Character.charCount(startCodePoint); i < stringToGesture.length();
+ i = stringToGesture.offsetByCodePoints(i, 1)) {
+ final Point newPoint = getXY(stringToGesture.codePointAt(i));
+ // Arbitrarily 0.5s between letters and 0.1 between events. Refine this later if needed.
+ final int STEPS = 5;
+ for (int j = 0; j < STEPS; ++j) {
+ timestamp += 100;
+ pointers.addPointer(oldPoint.x + ((newPoint.x - oldPoint.x) * j) / STEPS,
+ oldPoint.y + ((newPoint.y - oldPoint.y) * j) / STEPS,
+ 0 /* pointerId */, timestamp);
+ }
+ oldPoint.x = newPoint.x;
+ oldPoint.y = newPoint.y;
+ mLatinIME.onUpdateBatchInput(pointers);
+ }
+ mLatinIME.onEndBatchInput(pointers);
+ sleep(DELAY_TO_WAIT_FOR_GESTURE_MILLIS);
+ runMessages();
+ }
+
protected void waitForDictionariesToBeLoaded() {
try {
mLatinIME.waitForLoadingDictionaries(
@@ -329,7 +394,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
false /* isAuxiliary */,
false /* overridesImplicitlyEnabledSubtype */,
0 /* id */);
- SubtypeSwitcher.getInstance().forceSubtype(subtype);
+ RichInputMethodManager.forceSubtype(subtype);
mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
runMessages();
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
@@ -346,8 +411,9 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
}
protected void pickSuggestionManually(final String suggestion) {
- mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion, 1,
- SuggestedWordInfo.KIND_CORRECTION, null /* sourceDict */,
+ mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion,
+ "" /* prevWordsContext */, 1 /* score */,
+ SuggestedWordInfo.KIND_CORRECTION, DICTIONARY_TEST,
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
@@ -358,4 +424,40 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {}
}
+
+ // Some helper methods to manage the mock cursor position
+ // DO NOT CALL LatinIME#onUpdateSelection IF YOU WANT TO USE THOSE
+ int mLastCursorPos = 0;
+ /**
+ * Move the cached cursor position to the passed position and send onUpdateSelection to LatinIME
+ */
+ protected int sendUpdateForCursorMoveTo(final int position) {
+ mInputConnection.setSelection(position, position);
+ mLatinIME.onUpdateSelection(mLastCursorPos, mLastCursorPos, position, position, -1, -1);
+ mLastCursorPos = position;
+ return position;
+ }
+
+ /**
+ * Move the cached cursor position by the passed amount and send onUpdateSelection to LatinIME
+ */
+ protected int sendUpdateForCursorMoveBy(final int offset) {
+ final int lastPos = mEditText.getText().length();
+ final int requestedPosition = mLastCursorPos + offset;
+ if (requestedPosition < 0) {
+ return sendUpdateForCursorMoveTo(0);
+ } else if (requestedPosition > lastPos) {
+ return sendUpdateForCursorMoveTo(lastPos);
+ } else {
+ return sendUpdateForCursorMoveTo(requestedPosition);
+ }
+ }
+
+ /**
+ * Move the cached cursor position to the end of the line and send onUpdateSelection to LatinIME
+ */
+ protected int sendUpdateForCursorMoveToEndOfLine() {
+ final int lastPos = mEditText.getText().length();
+ return sendUpdateForCursorMoveTo(lastPos);
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java b/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
index e47c55736..035c8d7ce 100644
--- a/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
@@ -21,4 +21,16 @@ public class LatinIMEForTests extends LatinIME {
public boolean isInputViewShown() {
return true;
}
+
+ private boolean deallocateMemoryWasPerformed = false;
+
+ @Override
+ protected void deallocateMemory() {
+ super.deallocateMemory();
+ deallocateMemoryWasPerformed = true;
+ }
+
+ public boolean getDeallocateMemoryWasPerformed() {
+ return deallocateMemoryWasPerformed;
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
index f5e993de8..22114b7a0 100644
--- a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
@@ -18,7 +18,7 @@ package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
+import com.android.inputmethod.latin.common.CodePointUtils;
import java.util.Random;
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeTests.java b/tests/src/com/android/inputmethod/latin/LatinImeTests.java
new file mode 100644
index 000000000..c6f631328
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/LatinImeTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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;
+
+@LargeTest
+public class LatinImeTests extends InputTestsBase {
+ public void testDeferredDeallocation_doesntHappenBeforeTimeout() {
+ mLatinIME.mHandler.onFinishInputView(true);
+ runMessages();
+ sleep(1000); // 1s
+ runMessages();
+ assertFalse("memory deallocation performed before timeout passed",
+ ((LatinIMEForTests)mLatinIME).getDeallocateMemoryWasPerformed());
+ }
+
+ public void testDeferredDeallocation_doesHappenAfterTimeout() {
+ mLatinIME.mHandler.onFinishInputView(true);
+ runMessages();
+ sleep(11000); // 11s (timeout is at 10s)
+ runMessages();
+ assertTrue("memory deallocation not performed although timeout passed",
+ ((LatinIMEForTests)mLatinIME).getDeallocateMemoryWasPerformed());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/NgramContextTests.java b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
new file mode 100644
index 000000000..0a662db82
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+import com.android.inputmethod.latin.utils.NgramContextUtils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class NgramContextTests extends AndroidTestCase {
+ public void testConstruct() {
+ assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
+ assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO),
+ new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO));
+ assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
+ new NgramContext(WordInfo.EMPTY_WORD_INFO));
+ assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
+ new NgramContext(WordInfo.EMPTY_WORD_INFO));
+ }
+
+ public void testIsBeginningOfSentenceContext() {
+ assertFalse(new NgramContext().isBeginningOfSentenceContext());
+ assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+ .isBeginningOfSentenceContext());
+ assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
+ assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
+ assertFalse(new NgramContext(new WordInfo("")).isBeginningOfSentenceContext());
+ assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO).isBeginningOfSentenceContext());
+ assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO, new WordInfo("a"))
+ .isBeginningOfSentenceContext());
+ assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+ .isBeginningOfSentenceContext());
+ assertFalse(new NgramContext(
+ WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+ .isBeginningOfSentenceContext());
+ }
+
+ public void testGetNextNgramContext() {
+ final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+ final NgramContext ngramContext_b_a =
+ ngramContext_a.getNextNgramContext(new WordInfo("b"));
+ assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+ assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+ final NgramContext ngramContext_bos_b =
+ ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+ assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+ assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+ final NgramContext ngramContext_c_bos =
+ ngramContext_b_a.getNextNgramContext(new WordInfo("c"));
+ assertEquals("c", ngramContext_c_bos.getNthPrevWord(1));
+ }
+
+ public void testExtractPrevWordsContextTest() {
+ final NgramContext ngramContext_bos =
+ new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+ assertEquals("<S>", ngramContext_bos.extractPrevWordsContext());
+ final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+ final NgramContext ngramContext_b_a =
+ ngramContext_a.getNextNgramContext(new WordInfo("b"));
+ assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+ assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+ assertEquals("a b", ngramContext_b_a.extractPrevWordsContext());
+
+ final NgramContext ngramContext_bos_b =
+ ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+ assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+ assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+ assertEquals("a b <S>", ngramContext_bos_b.extractPrevWordsContext());
+
+ final NgramContext ngramContext_empty = new NgramContext(WordInfo.EMPTY_WORD_INFO);
+ assertEquals("", ngramContext_empty.extractPrevWordsContext());
+ final NgramContext ngramContext_a_empty =
+ ngramContext_empty.getNextNgramContext(new WordInfo("a"));
+ assertEquals("a", ngramContext_a_empty.getNthPrevWord(1));
+ assertEquals("a", ngramContext_a_empty.extractPrevWordsContext());
+ }
+
+ public void testExtractPrevWordsContextArray() {
+ final NgramContext ngramContext_bos =
+ new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+ assertEquals("<S>", ngramContext_bos.extractPrevWordsContext());
+ assertEquals(1, ngramContext_bos.extractPrevWordsContextArray().length);
+ final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+ final NgramContext ngramContext_b_a =
+ ngramContext_a.getNextNgramContext(new WordInfo("b"));
+ assertEquals(2, ngramContext_b_a.extractPrevWordsContextArray().length);
+ assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+ assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+ assertEquals("a", ngramContext_b_a.extractPrevWordsContextArray()[0]);
+ assertEquals("b", ngramContext_b_a.extractPrevWordsContextArray()[1]);
+
+ final NgramContext ngramContext_bos_b =
+ ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+ assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+ assertEquals(3, ngramContext_bos_b.extractPrevWordsContextArray().length);
+ assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+ assertEquals("a", ngramContext_bos_b.extractPrevWordsContextArray()[0]);
+ assertEquals("b", ngramContext_bos_b.extractPrevWordsContextArray()[1]);
+ assertEquals("<S>", ngramContext_bos_b.extractPrevWordsContextArray()[2]);
+
+ final NgramContext ngramContext_empty = new NgramContext(WordInfo.EMPTY_WORD_INFO);
+ assertEquals(0, ngramContext_empty.extractPrevWordsContextArray().length);
+ final NgramContext ngramContext_a_empty =
+ ngramContext_empty.getNextNgramContext(new WordInfo("a"));
+ assertEquals(1, ngramContext_a_empty.extractPrevWordsContextArray().length);
+ assertEquals("a", ngramContext_a_empty.extractPrevWordsContextArray()[0]);
+ }
+
+ public void testGetNgramContextFromNthPreviousWord() {
+ SpacingAndPunctuations spacingAndPunctuations = new SpacingAndPunctuations(
+ mContext.getResources());
+ assertEquals("<S>", NgramContextUtils.getNgramContextFromNthPreviousWord("",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a. b ",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a? b ",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a! b ",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a\nb ",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertEquals("<S> a b", NgramContextUtils.getNgramContextFromNthPreviousWord("a b ",
+ spacingAndPunctuations, 1).extractPrevWordsContext());
+ assertFalse(NgramContextUtils
+ .getNgramContextFromNthPreviousWord("a b c d e", spacingAndPunctuations, 1)
+ .extractPrevWordsContext().startsWith("<S>"));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
index 64750fbda..3537918de 100644
--- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java
+++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
@@ -38,7 +38,7 @@ public class PunctuationTests extends InputTestsBase {
try {
mLatinIME.loadSettings();
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
assertTrue("type word then type space should display punctuation strip",
mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
index f9d72269e..08779b9d3 100644
--- a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
+++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
@@ -30,12 +30,12 @@ import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.PrevWordsInfoUtils;
+import com.android.inputmethod.latin.utils.NgramContextUtils;
import com.android.inputmethod.latin.utils.RunInLocale;
import com.android.inputmethod.latin.utils.ScriptUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.TextRange;
import java.util.Locale;
@@ -137,7 +137,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
}
}
- private class MockInputMethodService extends InputMethodService {
+ static class MockInputMethodService extends InputMethodService {
private MockConnection mMockConnection;
public void setInputConnection(final MockConnection mockConnection) {
mMockConnection = mockConnection;
@@ -158,26 +158,25 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
*/
public void testGetPreviousWord() {
// If one of the following cases breaks, the bigram suggestions won't work.
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc. def", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
-
- assertFalse(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence);
- assertTrue(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc. def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+
+ assertFalse(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
+ assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
// For n-gram
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[1].mWord, "abc");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[1],
- WordInfo.BEGINNING_OF_SENTENCE);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(2), "abc");
+ assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 2).isNthPrevWordBeginningOfSentence(2));
// The following tests reflect the current behavior of the function
// RichInputConnection#getNthPreviousWord.
@@ -186,33 +185,37 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
// this function if needed - especially since it does not seem very
// logical. These tests are just there to catch any unintentional
// changes in the behavior of the RichInputConnection#getPreviousWord method.
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def ", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def.", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def .", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "def");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc ", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
-
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def ", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc 'def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "'def");
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def.", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc def .", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc, def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc? def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc! def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
- assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
- "abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def ", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def.", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def .", mSpacingAndPunctuations, 2).getNthPrevWord(1), "def");
+ assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc ", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
+
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def ", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc 'def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "'def");
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def.", mSpacingAndPunctuations, 1), NgramContext.BEGINNING_OF_SENTENCE);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc def .", mSpacingAndPunctuations, 1), NgramContext.BEGINNING_OF_SENTENCE);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc, def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
+ // question mark is treated as the end of the sentence. Hence, beginning of the
+ // sentence is expected.
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc? def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+ // Exclamation mark is treated as the end of the sentence. Hence, beginning of the
+ // sentence is expected.
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc! def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc 'def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
}
public void testGetWordRangeAtCursor() {
@@ -223,7 +226,6 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
- final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
// A character that needs surrogate pair to represent its code point (U+2008A).
final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
diff --git a/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java b/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java
new file mode 100644
index 000000000..af94be664
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2014 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.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+@SmallTest
+public class RichInputMethodSubtypeTests extends AndroidTestCase {
+ // All input method subtypes of LatinIME.
+ private final ArrayList<RichInputMethodSubtype> mSubtypesList = new ArrayList<>();
+
+ private RichInputMethodManager mRichImm;
+ private Resources mRes;
+ private InputMethodSubtype mSavedAddtionalSubtypes[];
+
+ RichInputMethodSubtype EN_US;
+ RichInputMethodSubtype EN_GB;
+ RichInputMethodSubtype ES_US;
+ RichInputMethodSubtype FR;
+ RichInputMethodSubtype FR_CA;
+ RichInputMethodSubtype FR_CH;
+ RichInputMethodSubtype DE;
+ RichInputMethodSubtype DE_CH;
+ RichInputMethodSubtype HI;
+ RichInputMethodSubtype SR;
+ RichInputMethodSubtype ZZ;
+ RichInputMethodSubtype DE_QWERTY;
+ RichInputMethodSubtype FR_QWERTZ;
+ RichInputMethodSubtype EN_US_AZERTY;
+ RichInputMethodSubtype EN_UK_DVORAK;
+ RichInputMethodSubtype ES_US_COLEMAK;
+ RichInputMethodSubtype ZZ_AZERTY;
+ RichInputMethodSubtype ZZ_PC;
+
+ // These are preliminary subtypes and may not exist.
+ RichInputMethodSubtype HI_LATN; // Hinglish
+ RichInputMethodSubtype SR_LATN; // Serbian Latin
+ RichInputMethodSubtype HI_LATN_DVORAK;
+ RichInputMethodSubtype SR_LATN_QWERTY;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Context context = getContext();
+ mRes = context.getResources();
+ RichInputMethodManager.init(context);
+ mRichImm = RichInputMethodManager.getInstance();
+
+ // Save and reset additional subtypes
+ mSavedAddtionalSubtypes = mRichImm.getAdditionalSubtypes();
+ final InputMethodSubtype[] predefinedAddtionalSubtypes =
+ AdditionalSubtypeUtils.createAdditionalSubtypesArray(
+ AdditionalSubtypeUtils.createPrefSubtypes(
+ mRes.getStringArray(R.array.predefined_subtypes)));
+ mRichImm.setAdditionalInputMethodSubtypes(predefinedAddtionalSubtypes);
+
+ final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int index = 0; index < subtypeCount; index++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+ mSubtypesList.add(new RichInputMethodSubtype(subtype));
+ }
+
+ EN_US = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.US.toString(), "qwerty"));
+ EN_GB = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.UK.toString(), "qwerty"));
+ ES_US = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "es_US", "spanish"));
+ FR = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.FRENCH.toString(), "azerty"));
+ FR_CA = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.CANADA_FRENCH.toString(), "qwerty"));
+ FR_CH = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "fr_CH", "swiss"));
+ DE = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.GERMAN.toString(), "qwertz"));
+ DE_CH = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "de_CH", "swiss"));
+ HI = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "hi", "hindi"));
+ SR = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "sr", "south_slavic"));
+ ZZ = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"));
+ DE_QWERTY = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ Locale.GERMAN.toString(), "qwerty"));
+ FR_QWERTZ = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ Locale.FRENCH.toString(), "qwertz"));
+ EN_US_AZERTY = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ Locale.US.toString(), "azerty"));
+ EN_UK_DVORAK = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ Locale.UK.toString(), "dvorak"));
+ ES_US_COLEMAK = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ "es_US", "colemak"));
+ ZZ_AZERTY = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "azerty"));
+ ZZ_PC = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty"));
+
+ final InputMethodSubtype hiLatn = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "hi_ZZ", "qwerty");
+ if (hiLatn != null) {
+ HI_LATN = new RichInputMethodSubtype(hiLatn);
+ HI_LATN_DVORAK = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ "hi_ZZ", "dvorak"));
+ }
+ final InputMethodSubtype srLatn = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "sr_ZZ", "serbian_qwertz");
+ if (srLatn != null) {
+ SR_LATN = new RichInputMethodSubtype(srLatn);
+ SR_LATN_QWERTY = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ "sr_ZZ", "qwerty"));
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Restore additional subtypes.
+ mRichImm.setAdditionalInputMethodSubtypes(mSavedAddtionalSubtypes);
+ super.tearDown();
+ }
+
+ public void testAllFullDisplayNameForSpacebar() {
+ for (final RichInputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+ final String spacebarText = subtype.getFullDisplayName();
+ final String languageName = SubtypeLocaleUtils
+ .getSubtypeLocaleDisplayName(subtype.getLocale().toString());
+ if (subtype.isNoLanguage()) {
+ assertFalse(subtypeName, spacebarText.contains(languageName));
+ } else {
+ assertTrue(subtypeName, spacebarText.contains(languageName));
+ }
+ }
+ }
+
+ public void testAllMiddleDisplayNameForSpacebar() {
+ for (final RichInputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+ final Locale locale = subtype.getLocale();
+ final Locale displayLocale = SubtypeLocaleUtils.getDisplayLocaleOfSubtypeLocale(
+ locale.toString());
+ if (Locale.ROOT.equals(displayLocale)) {
+ // Skip test because the language part of this locale string doesn't represent
+ // the locale to be displayed on the spacebar (for example Hinglish).
+ continue;
+ }
+ final String spacebarText = subtype.getMiddleDisplayName();
+ if (subtype.isNoLanguage()) {
+ assertEquals(subtypeName, SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(
+ subtype.getRawSubtype()), spacebarText);
+ } else {
+ assertEquals(subtypeName,
+ SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale.toString()),
+ spacebarText);
+ }
+ }
+ }
+
+ // InputMethodSubtype's display name for spacebar text in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | Middle Full
+ // ------ -------------- - --------- ----------------------
+ // en_US qwerty F English English (US) exception
+ // en_GB qwerty F English English (UK) exception
+ // es_US spanish F Español Español (EE.UU.) exception
+ // fr azerty F Français Français
+ // fr_CA qwerty F Français Français (Canada)
+ // fr_CH swiss F Français Français (Suisse)
+ // de qwertz F Deutsch Deutsch
+ // de_CH swiss F Deutsch Deutsch (Schweiz)
+ // hi hindi F हिन्दी हिन्दी
+ // hi_ZZ qwerty F Hinglish Hinglish exception
+ // sr south_slavic F Српски Српски
+ // sr_ZZ serbian_qwertz F Srpski Srpski exception
+ // zz qwerty F QWERTY QWERTY
+ // fr qwertz T Français Français
+ // de qwerty T Deutsch Deutsch
+ // en_US azerty T English English (US)
+ // en_GB dvorak T English English (UK)
+ // hi_ZZ dvorak T Hinglish Hinglish exception
+ // sr_ZZ qwerty T Srpski Srpski exception
+ // 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)", EN_US.getFullDisplayName());
+ assertEquals("en_GB", "English (UK)", EN_GB.getFullDisplayName());
+ assertEquals("es_US", "Español (EE.UU.)", ES_US.getFullDisplayName());
+ assertEquals("fr", "Français", FR.getFullDisplayName());
+ assertEquals("fr_CA", "Français (Canada)", FR_CA.getFullDisplayName());
+ assertEquals("fr_CH", "Français (Suisse)", FR_CH.getFullDisplayName());
+ assertEquals("de", "Deutsch", DE.getFullDisplayName());
+ assertEquals("de_CH", "Deutsch (Schweiz)", DE_CH.getFullDisplayName());
+ assertEquals("hi", "हिन्दी", HI.getFullDisplayName());
+ assertEquals("sr", "Српски", SR.getFullDisplayName());
+ assertEquals("zz", "QWERTY", ZZ.getFullDisplayName());
+
+ assertEquals("en_US", "English", EN_US.getMiddleDisplayName());
+ assertEquals("en_GB", "English", EN_GB.getMiddleDisplayName());
+ assertEquals("es_US", "Español", ES_US.getMiddleDisplayName());
+ assertEquals("fr", "Français", FR.getMiddleDisplayName());
+ assertEquals("fr_CA", "Français", FR_CA.getMiddleDisplayName());
+ assertEquals("fr_CH", "Français", FR_CH.getMiddleDisplayName());
+ assertEquals("de", "Deutsch", DE.getMiddleDisplayName());
+ assertEquals("de_CH", "Deutsch", DE_CH.getMiddleDisplayName());
+ assertEquals("zz", "QWERTY", ZZ.getMiddleDisplayName());
+
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN != null) {
+ assertEquals("hi_ZZ", "Hinglish", HI_LATN.getFullDisplayName());
+ assertEquals("hi_ZZ", "Hinglish", HI_LATN.getMiddleDisplayName());
+ }
+ if (SR_LATN != null) {
+ assertEquals("sr_ZZ", "Srpski", SR_LATN.getFullDisplayName());
+ assertEquals("sr_ZZ", "Srpski", SR_LATN.getMiddleDisplayName());
+ }
+ return null;
+ }
+ };
+
+ private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("fr qwertz", "Français", FR_QWERTZ.getFullDisplayName());
+ assertEquals("de qwerty", "Deutsch", DE_QWERTY.getFullDisplayName());
+ assertEquals("en_US azerty", "English (US)", EN_US_AZERTY.getFullDisplayName());
+ assertEquals("en_UK dvorak", "English (UK)", EN_UK_DVORAK.getFullDisplayName());
+ assertEquals("es_US colemak", "Español (EE.UU.)", ES_US_COLEMAK.getFullDisplayName());
+ assertEquals("zz azerty", "AZERTY", ZZ_AZERTY.getFullDisplayName());
+ assertEquals("zz pc", "PC", ZZ_PC.getFullDisplayName());
+
+ assertEquals("fr qwertz", "Français", FR_QWERTZ.getMiddleDisplayName());
+ assertEquals("de qwerty", "Deutsch", DE_QWERTY.getMiddleDisplayName());
+ assertEquals("en_US azerty", "English", EN_US_AZERTY.getMiddleDisplayName());
+ assertEquals("en_UK dvorak", "English", EN_UK_DVORAK.getMiddleDisplayName());
+ assertEquals("es_US colemak", "Español", ES_US_COLEMAK.getMiddleDisplayName());
+ assertEquals("zz azerty", "AZERTY", ZZ_AZERTY.getMiddleDisplayName());
+ assertEquals("zz pc", "PC", ZZ_PC.getMiddleDisplayName());
+
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN_DVORAK != null) {
+ assertEquals("hi_ZZ dvorak", "Hinglish", HI_LATN_DVORAK.getFullDisplayName());
+ assertEquals("hi_ZZ dvorak", "Hinglish", HI_LATN_DVORAK.getMiddleDisplayName());
+ }
+ if (SR_LATN_QWERTY != null) {
+ assertEquals("sr_ZZ qwerty", "Srpski", SR_LATN_QWERTY.getFullDisplayName());
+ assertEquals("sr_ZZ qwerty", "Srpski", SR_LATN_QWERTY.getMiddleDisplayName());
+ }
+ 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);
+ }
+
+ public void testRichInputMethodSubtypeForNullInputMethodSubtype() {
+ RichInputMethodSubtype subtype = RichInputMethodSubtype.getRichInputMethodSubtype(null);
+ assertNotNull(subtype);
+ assertEquals("zz", subtype.getRawSubtype().getLocale());
+ assertEquals("keyboard", subtype.getRawSubtype().getMode());
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index db3c9baa9..59bb5f8a4 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -16,13 +16,11 @@
package com.android.inputmethod.latin;
-import android.os.Build;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.common.Constants;
@LargeTest
public class ShiftModeTests extends InputTestsBase {
@@ -75,7 +73,7 @@ public class ShiftModeTests extends InputTestsBase {
repeatKey(Constants.CODE_DELETE);
}
assertFalse("Caps immediately after repeating Backspace a lot", isCapsModeAutoShifted());
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
}
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 869c550e0..d465ce674 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -37,7 +37,7 @@ public class SuggestedWordsTests extends AndroidTestCase {
private static SuggestedWordInfo createTypedWordInfo(final String word) {
// Use 100 as the frequency because the numerical value does not matter as
// long as it's > 1 and < INT_MAX.
- return new SuggestedWordInfo(word, 100 /* score */,
+ return new SuggestedWordInfo(word, "" /* prevWordsContext */, 100 /* score */,
SuggestedWordInfo.KIND_TYPED,
null /* sourceDict */,
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
@@ -52,49 +52,23 @@ public class SuggestedWordsTests extends AndroidTestCase {
* @return a new instance of {@link SuggestedWordInfo}.
*/
private static SuggestedWordInfo createCorrectionWordInfo(final String word) {
- return new SuggestedWordInfo(word, 1 /* score */,
+ return new SuggestedWordInfo(word, "" /* prevWordsContext */, 1 /* score */,
SuggestedWordInfo.KIND_CORRECTION,
null /* sourceDict */,
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
}
- public void testGetSuggestedWordsExcludingTypedWord() {
- final String TYPED_WORD = "typed";
- final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
- final int KIND_OF_SECOND_CORRECTION = SuggestedWordInfo.KIND_CORRECTION;
- final ArrayList<SuggestedWordInfo> list = new ArrayList<>();
- list.add(createTypedWordInfo(TYPED_WORD));
- for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
- list.add(createCorrectionWordInfo(Integer.toString(i)));
+ private static ArrayList<SuggestedWordInfo> createCorrectionWordInfos(final String... words) {
+ final ArrayList<SuggestedWordInfo> infos = new ArrayList<>();
+ for (final String word : words) {
+ infos.add(createCorrectionWordInfo(word));
}
-
- final SuggestedWords words = new SuggestedWords(
- list, null /* rawSuggestions */,
- false /* typedWordValid */,
- false /* willAutoCorrect */,
- false /* isObsoleteSuggestions */,
- SuggestedWords.INPUT_STYLE_NONE);
- assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
- assertEquals("typed", words.getWord(0));
- assertTrue(words.getInfo(0).isKindOf(SuggestedWordInfo.KIND_TYPED));
- assertEquals("0", words.getWord(1));
- assertTrue(words.getInfo(1).isKindOf(KIND_OF_SECOND_CORRECTION));
- assertEquals("4", words.getWord(5));
- assertTrue(words.getInfo(5).isKindOf(KIND_OF_SECOND_CORRECTION));
-
- final SuggestedWords wordsWithoutTyped =
- words.getSuggestedWordsExcludingTypedWordForRecorrection();
- // Make sure that the typed word has indeed been excluded, by testing the size of the
- // suggested words, the string and the kind of the top suggestion, which should match
- // the string and kind of what we inserted after the typed word.
- assertEquals(words.size() - 1, wordsWithoutTyped.size());
- assertEquals("0", wordsWithoutTyped.getWord(0));
- assertTrue(wordsWithoutTyped.getInfo(0).isKindOf(KIND_OF_SECOND_CORRECTION));
+ return infos;
}
// Helper for testGetTransformedWordInfo
- private SuggestedWordInfo transformWordInfo(final String info,
+ private static SuggestedWordInfo transformWordInfo(final String info,
final int trailingSingleQuotesCount) {
final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
final SuggestedWordInfo returnedWordInfo =
@@ -106,6 +80,30 @@ public class SuggestedWordsTests extends AndroidTestCase {
return returnedWordInfo;
}
+ public void testRemoveDupesNoDupes() {
+ final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "c");
+ assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
+ assertEquals(2, infos.size());
+ }
+
+ public void testRemoveDupesTypedWordNotDupe() {
+ final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "a", "c");
+ assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
+ assertEquals(2, infos.size());
+ }
+
+ public void testRemoveDupesTypedWordOnlyDupe() {
+ final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "c");
+ assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
+ assertEquals(2, infos.size());
+ }
+
+ public void testRemoveDupesTypedWordNotOnlyDupe() {
+ final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "b", "c");
+ assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
+ assertEquals(2, infos.size());
+ }
+
public void testGetTransformedSuggestedWordInfo() {
SuggestedWordInfo result = transformWordInfo("word", 0);
assertEquals(result.mWord, "word");
@@ -123,9 +121,10 @@ public class SuggestedWordsTests extends AndroidTestCase {
public void testGetTypedWordInfoOrNull() {
final String TYPED_WORD = "typed";
+ final SuggestedWordInfo TYPED_WORD_INFO = createTypedWordInfo(TYPED_WORD);
final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
final ArrayList<SuggestedWordInfo> list = new ArrayList<>();
- list.add(createTypedWordInfo(TYPED_WORD));
+ list.add(TYPED_WORD_INFO);
for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
list.add(createCorrectionWordInfo(Integer.toString(i)));
}
@@ -133,30 +132,41 @@ public class SuggestedWordsTests extends AndroidTestCase {
// Make sure getTypedWordInfoOrNull() returns non-null object.
final SuggestedWords wordsWithTypedWord = new SuggestedWords(
list, null /* rawSuggestions */,
+ TYPED_WORD_INFO,
false /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
- SuggestedWords.INPUT_STYLE_NONE);
+ SuggestedWords.INPUT_STYLE_NONE,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER);
final SuggestedWordInfo typedWord = wordsWithTypedWord.getTypedWordInfoOrNull();
assertNotNull(typedWord);
assertEquals(TYPED_WORD, typedWord.mWord);
- // Make sure getTypedWordInfoOrNull() returns null.
- final SuggestedWords wordsWithoutTypedWord =
- wordsWithTypedWord.getSuggestedWordsExcludingTypedWordForRecorrection();
+ // Make sure getTypedWordInfoOrNull() returns null when no typed word.
+ list.remove(0);
+ final SuggestedWords wordsWithoutTypedWord = new SuggestedWords(
+ list, null /* rawSuggestions */,
+ null /* typedWord */,
+ false /* typedWordValid */,
+ false /* willAutoCorrect */,
+ false /* isObsoleteSuggestions */,
+ SuggestedWords.INPUT_STYLE_NONE,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER);
assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
// Make sure getTypedWordInfoOrNull() returns null.
- assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
+ assertNull(SuggestedWords.getEmptyInstance().getTypedWordInfoOrNull());
final SuggestedWords emptySuggestedWords = new SuggestedWords(
new ArrayList<SuggestedWordInfo>(), null /* rawSuggestions */,
+ null /* typedWord */,
false /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
- SuggestedWords.INPUT_STYLE_NONE);
+ SuggestedWords.INPUT_STYLE_NONE,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER);
assertNull(emptySuggestedWords.getTypedWordInfoOrNull());
- assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
+ assertNull(SuggestedWords.getEmptyInstance().getTypedWordInfoOrNull());
}
}
diff --git a/tests/src/com/android/inputmethod/latin/WordComposerTests.java b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
index c44544f3d..8ae475f7e 100644
--- a/tests/src/com/android/inputmethod/latin/WordComposerTests.java
+++ b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
@@ -19,8 +19,9 @@ package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.StringUtils;
/**
* Unit tests for WordComposer.
diff --git a/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java b/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java
new file mode 100644
index 000000000..832817967
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+
+import com.android.inputmethod.latin.settings.LocalSettingsConstants;
+
+/**
+ * Tests for {@link AccountsChangedReceiver}.
+ */
+public class AccountsChangedReceiverTests extends AndroidTestCase {
+ private static final String ACCOUNT_1 = "account1@example.com";
+ private static final String ACCOUNT_2 = "account2@example.com";
+
+ private SharedPreferences mPrefs;
+ private String mLastKnownAccount = null;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ // Keep track of the current account so that we restore it when the test finishes.
+ mLastKnownAccount = mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ // Restore the account that was present before running the test.
+ updateAccountName(mLastKnownAccount);
+ }
+
+ public void testUnknownIntent() {
+ updateAccountName(ACCOUNT_1);
+ AccountsChangedReceiver reciever = new AccountsChangedReceiver();
+ reciever.onReceive(getContext(), new Intent("some-random-action"));
+ // Account should *not* be removed from preferences.
+ assertAccountName(ACCOUNT_1);
+ }
+
+ public void testAccountRemoved() {
+ updateAccountName(ACCOUNT_1);
+ AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+ @Override
+ protected String[] getAccountsForLogin(Context context) {
+ return new String[] {ACCOUNT_2};
+ }
+ };
+ reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+ // Account should be removed from preferences.
+ assertAccountName(null);
+ }
+
+ public void testAccountRemoved_noAccounts() {
+ updateAccountName(ACCOUNT_2);
+ AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+ @Override
+ protected String[] getAccountsForLogin(Context context) {
+ return new String[0];
+ }
+ };
+ reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+ // Account should be removed from preferences.
+ assertAccountName(null);
+ }
+
+ public void testAccountNotRemoved() {
+ updateAccountName(ACCOUNT_2);
+ AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+ @Override
+ protected String[] getAccountsForLogin(Context context) {
+ return new String[] {ACCOUNT_1, ACCOUNT_2};
+ }
+ };
+ reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+ // Account should *not* be removed from preferences.
+ assertAccountName(ACCOUNT_2);
+ }
+
+ private void updateAccountName(String accountName) {
+ if (accountName == null) {
+ mPrefs.edit().remove(LocalSettingsConstants.PREF_ACCOUNT_NAME).apply();
+ } else {
+ mPrefs.edit().putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, accountName).apply();
+ }
+ }
+
+ private void assertAccountName(String expectedAccountName) {
+ assertEquals(expectedAccountName,
+ mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/common/InputPointersTests.java
index 1a47cddf4..6b3490de8 100644
--- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java
+++ b/tests/src/com/android/inputmethod/latin/common/InputPointersTests.java
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.common;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.inputmethod.latin.utils.ResizableIntArray;
-
import java.util.Arrays;
@SmallTest
diff --git a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java b/tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java
index 8f58e6873..bd1629faf 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
+++ b/tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin.utils;
+package com.android.inputmethod.latin.common;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -79,13 +79,13 @@ public class ResizableIntArrayTests extends AndroidTestCase {
public void testGet() {
final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
try {
- final int value = src.get(0);
+ src.get(0);
fail("get(0) shouldn't succeed");
} catch (ArrayIndexOutOfBoundsException e) {
// success
}
try {
- final int value = src.get(DEFAULT_CAPACITY);
+ src.get(DEFAULT_CAPACITY);
fail("get(DEFAULT_CAPACITY) shouldn't succeed");
} catch (ArrayIndexOutOfBoundsException e) {
// success
@@ -98,7 +98,7 @@ public class ResizableIntArrayTests extends AndroidTestCase {
assertEquals("value after add at " + index, valueAddAt, src.get(index));
assertEquals("value after add at 0", 0, src.get(0));
try {
- final int value = src.get(src.getLength());
+ src.get(src.getLength());
fail("get(length) shouldn't succeed");
} catch (ArrayIndexOutOfBoundsException e) {
// success
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java
index 637ae10ee..ec9d4be92 100644
--- a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 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.
@@ -14,22 +14,177 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin.utils;
+package com.android.inputmethod.latin.common;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.SpannedString;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Arrays;
-import java.util.List;
import java.util.Locale;
@SmallTest
-public class StringAndJsonUtilsTests extends AndroidTestCase {
+public class StringUtilsTests extends AndroidTestCase {
+ private static final Locale US = Locale.US;
+ private static final Locale GERMAN = Locale.GERMAN;
+ private static final Locale TURKEY = new Locale("tr", "TR");
+ private static final Locale GREECE = new Locale("el", "GR");
+
+ private static void assert_toTitleCaseOfKeyLabel(final Locale locale,
+ final String lowerCase, final String expected) {
+ assertEquals(lowerCase + " in " + locale, expected,
+ StringUtils.toTitleCaseOfKeyLabel(lowerCase, locale));
+ }
+
+ public void test_toTitleCaseOfKeyLabel() {
+ assert_toTitleCaseOfKeyLabel(US, null, null);
+ assert_toTitleCaseOfKeyLabel(US, "", "");
+ assert_toTitleCaseOfKeyLabel(US, "aeiou", "AEIOU");
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+00C0: "À" LATIN CAPITAL LETTER A WITH GRAVE
+ // U+00C8: "È" LATIN CAPITAL LETTER E WITH GRAVE
+ // U+00CE: "Î" LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+ // U+00D6: "Ö" LATIN CAPITAL LETTER O WITH DIAERESIS
+ // U+016A: "Ū" LATIN CAPITAL LETTER U WITH MACRON
+ // U+00D1: "Ñ" LATIN CAPITAL LETTER N WITH TILDE
+ // U+00C7: "Ç" LATIN CAPITAL LETTER C WITH CEDILLA
+ assert_toTitleCaseOfKeyLabel(US,
+ "\u00E0\u00E8\u00EE\u00F6\u016B\u00F1\u00E7",
+ "\u00C0\u00C8\u00CE\u00D6\u016A\u00D1\u00C7");
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+015A: "Ś" LATIN CAPITAL LETTER S WITH ACUTE
+ // U+0160: "Š" LATIN CAPITAL LETTER S WITH CARONZ
+ assert_toTitleCaseOfKeyLabel(GERMAN,
+ "\u00DF\u015B\u0161",
+ "SS\u015A\u0160");
+ // U+0259: "ə" LATIN SMALL LETTER SCHWA
+ // U+0069: "i" LATIN SMALL LETTER I
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ // U+018F: "Ə" LATIN SMALL LETTER SCHWA
+ // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
+ // U+0049: "I" LATIN SMALL LETTER I
+ assert_toTitleCaseOfKeyLabel(TURKEY,
+ "\u0259\u0069\u0131",
+ "\u018F\u0130\u0049");
+ // U+03C3: "σ" GREEK SMALL LETTER SIGMA
+ // U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA
+ // U+03A3: "Σ" GREEK CAPITAL LETTER SIGMA
+ assert_toTitleCaseOfKeyLabel(GREECE,
+ "\u03C3\u03C2",
+ "\u03A3\u03A3");
+ // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
+ // U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS
+ // U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS
+ // U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+ // U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS
+ // U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+ // U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS
+ // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
+ // U+0388: "Έ" GREEK CAPITAL LETTER EPSILON WITH TONOS
+ // U+0389: "Ή" GREEK CAPITAL LETTER ETA WITH TONOS
+ // U+038A: "Ί" GREEK CAPITAL LETTER IOTA WITH TONOS
+ // U+038C: "Ό" GREEK CAPITAL LETTER OMICRON WITH TONOS
+ // U+038E: "Ύ" GREEK CAPITAL LETTER UPSILON WITH TONOS
+ // U+038F: "Ώ" GREEK CAPITAL LETTER OMEGA WITH TONOS
+ assert_toTitleCaseOfKeyLabel(GREECE,
+ "\u03AC\u03AD\u03AE\u03AF\u03CC\u03CD\u03CE",
+ "\u0386\u0388\u0389\u038A\u038C\u038E\u038F");
+ // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+ // U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+ // U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+ // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+ // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+ // U+03AB: "Ϋ" GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+ // U+0399: "Ι" GREEK CAPITAL LETTER IOTA
+ // U+03A5: "Υ" GREEK CAPITAL LETTER UPSILON
+ // U+0308: COMBINING DIAERESIS
+ // U+0301: COMBINING GRAVE ACCENT
+ assert_toTitleCaseOfKeyLabel(GREECE,
+ "\u03CA\u03CB\u0390\u03B0",
+ "\u03AA\u03AB\u0399\u0308\u0301\u03A5\u0308\u0301");
+ }
+
+ private static void assert_toTitleCaseOfKeyCode(final Locale locale, final int lowerCase,
+ final int expected) {
+ assertEquals(lowerCase + " in " + locale, expected,
+ StringUtils.toTitleCaseOfKeyCode(lowerCase, locale));
+ }
+
+ public void test_toTitleCaseOfKeyCode() {
+ assert_toTitleCaseOfKeyCode(US, Constants.CODE_ENTER, Constants.CODE_ENTER);
+ assert_toTitleCaseOfKeyCode(US, Constants.CODE_SPACE, Constants.CODE_SPACE);
+ assert_toTitleCaseOfKeyCode(US, Constants.CODE_COMMA, Constants.CODE_COMMA);
+ // U+0069: "i" LATIN SMALL LETTER I
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
+ // U+0049: "I" LATIN SMALL LETTER I
+ assert_toTitleCaseOfKeyCode(US, 0x0069, 0x0049); // i -> I
+ assert_toTitleCaseOfKeyCode(US, 0x0131, 0x0049); // ı -> I
+ assert_toTitleCaseOfKeyCode(TURKEY, 0x0069, 0x0130); // i -> İ
+ assert_toTitleCaseOfKeyCode(TURKEY, 0x0131, 0x0049); // ı -> I
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // The title case of "ß" is "SS".
+ assert_toTitleCaseOfKeyCode(US, 0x00DF, Constants.CODE_UNSPECIFIED);
+ // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
+ // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
+ assert_toTitleCaseOfKeyCode(GREECE, 0x03AC, 0x0386);
+ // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+ // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+ assert_toTitleCaseOfKeyCode(GREECE, 0x03CA, 0x03AA);
+ // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+ // The title case of "ΰ" is "\u03A5\u0308\u0301".
+ assert_toTitleCaseOfKeyCode(GREECE, 0x03B0, Constants.CODE_UNSPECIFIED);
+ }
+
+ private static void assert_capitalizeFirstCodePoint(final Locale locale, final String text,
+ final String expected) {
+ assertEquals(text + " in " + locale, expected,
+ StringUtils.capitalizeFirstCodePoint(text, locale));
+ }
+
+ public void test_capitalizeFirstCodePoint() {
+ assert_capitalizeFirstCodePoint(US, "", "");
+ assert_capitalizeFirstCodePoint(US, "a", "A");
+ assert_capitalizeFirstCodePoint(US, "à", "À");
+ assert_capitalizeFirstCodePoint(US, "ß", "SS");
+ assert_capitalizeFirstCodePoint(US, "text", "Text");
+ assert_capitalizeFirstCodePoint(US, "iGoogle", "IGoogle");
+ assert_capitalizeFirstCodePoint(TURKEY, "iyi", "İyi");
+ assert_capitalizeFirstCodePoint(TURKEY, "ısırdı", "Isırdı");
+ assert_capitalizeFirstCodePoint(GREECE, "ά", "Ά");
+ assert_capitalizeFirstCodePoint(GREECE, "άνεση", "Άνεση");
+ }
+
+ private static void assert_capitalizeFirstAndDowncaseRest(final Locale locale,
+ final String text, final String expected) {
+ assertEquals(text + " in " + locale, expected,
+ StringUtils.capitalizeFirstAndDowncaseRest(text, locale));
+ }
+
+ public void test_capitalizeFirstAndDowncaseRest() {
+ assert_capitalizeFirstAndDowncaseRest(US, "", "");
+ assert_capitalizeFirstAndDowncaseRest(US, "a", "A");
+ assert_capitalizeFirstAndDowncaseRest(US, "à", "À");
+ assert_capitalizeFirstAndDowncaseRest(US, "ß", "SS");
+ assert_capitalizeFirstAndDowncaseRest(US, "text", "Text");
+ assert_capitalizeFirstAndDowncaseRest(US, "iGoogle", "Igoogle");
+ assert_capitalizeFirstAndDowncaseRest(US, "invite", "Invite");
+ assert_capitalizeFirstAndDowncaseRest(US, "INVITE", "Invite");
+ assert_capitalizeFirstAndDowncaseRest(TURKEY, "iyi", "İyi");
+ assert_capitalizeFirstAndDowncaseRest(TURKEY, "İYİ", "İyi");
+ assert_capitalizeFirstAndDowncaseRest(TURKEY, "ısırdı", "Isırdı");
+ assert_capitalizeFirstAndDowncaseRest(TURKEY, "ISIRDI", "Isırdı");
+ assert_capitalizeFirstAndDowncaseRest(GREECE, "ά", "Ά");
+ assert_capitalizeFirstAndDowncaseRest(GREECE, "άνεση", "Άνεση");
+ assert_capitalizeFirstAndDowncaseRest(GREECE, "ΆΝΕΣΗ", "Άνεση");
+ }
+
public void testContainsInArray() {
assertFalse("empty array", StringUtils.containsInArray("key", new String[0]));
assertFalse("not in 1 element", StringUtils.containsInArray("key", new String[] {
@@ -246,16 +401,6 @@ public class StringAndJsonUtilsTests extends AndroidTestCase {
assertTrue(bytesStr.equals(bytesStr2));
}
- public void testJsonUtils() {
- final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
- final List<Object> objArray = Arrays.asList(objs);
- final String str = JsonUtils.listToJsonStr(objArray);
- final List<Object> newObjArray = JsonUtils.jsonStrToList(str);
- for (int i = 0; i < objs.length; ++i) {
- assertEquals(objs[i], newObjArray.get(i));
- }
- }
-
public void testToCodePointArray() {
final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh\u0000\u2002\u2003\u3000xx";
final int[] EXPECTED_RESULT = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7, 'f', 'g', 'h',
@@ -329,171 +474,4 @@ public class StringAndJsonUtilsTests extends AndroidTestCase {
assertEquals(1, StringUtils.getTrailingSingleQuotesCount("'word'"));
assertEquals(0, StringUtils.getTrailingSingleQuotesCount("I'm"));
}
-
- private static void assertSpanCount(final int expectedCount, final CharSequence cs) {
- final int actualCount;
- if (cs instanceof Spanned) {
- final Spanned spanned = (Spanned) cs;
- actualCount = spanned.getSpans(0, spanned.length(), Object.class).length;
- } else {
- actualCount = 0;
- }
- assertEquals(expectedCount, actualCount);
- }
-
- private static void assertSpan(final CharSequence cs, final Object expectedSpan,
- final int expectedStart, final int expectedEnd, final int expectedFlags) {
- assertTrue(cs instanceof Spanned);
- final Spanned spanned = (Spanned) cs;
- final Object[] actualSpans = spanned.getSpans(0, spanned.length(), Object.class);
- for (Object actualSpan : actualSpans) {
- if (actualSpan == expectedSpan) {
- final int actualStart = spanned.getSpanStart(actualSpan);
- final int actualEnd = spanned.getSpanEnd(actualSpan);
- final int actualFlags = spanned.getSpanFlags(actualSpan);
- assertEquals(expectedStart, actualStart);
- assertEquals(expectedEnd, actualEnd);
- assertEquals(expectedFlags, actualFlags);
- return;
- }
- }
- assertTrue(false);
- }
-
- public void testSplitCharSequenceWithSpan() {
- // text: " a bcd efg hij "
- // span1: ^^^^^^^
- // span2: ^^^^^
- // span3: ^
- final SpannableString spannableString = new SpannableString(" a bcd efg hij ");
- final Object span1 = new Object();
- final Object span2 = new Object();
- final Object span3 = new Object();
- final int SPAN1_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
- final int SPAN2_FLAGS = Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
- final int SPAN3_FLAGS = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
- spannableString.setSpan(span1, 0, 7, SPAN1_FLAGS);
- spannableString.setSpan(span2, 0, 5, SPAN2_FLAGS);
- spannableString.setSpan(span3, 12, 13, SPAN3_FLAGS);
- final CharSequence[] charSequencesFromSpanned = StringUtils.split(
- spannableString, " ", true /* preserveTrailingEmptySegmengs */);
- final CharSequence[] charSequencesFromString = StringUtils.split(
- spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */);
-
-
- assertEquals(7, charSequencesFromString.length);
- assertEquals(7, charSequencesFromSpanned.length);
-
- // text: ""
- // span1: ^
- // span2: ^
- // span3:
- assertEquals("", charSequencesFromString[0].toString());
- assertSpanCount(0, charSequencesFromString[0]);
- assertEquals("", charSequencesFromSpanned[0].toString());
- assertSpanCount(2, charSequencesFromSpanned[0]);
- assertSpan(charSequencesFromSpanned[0], span1, 0, 0, SPAN1_FLAGS);
- assertSpan(charSequencesFromSpanned[0], span2, 0, 0, SPAN2_FLAGS);
-
- // text: "a"
- // span1: ^
- // span2: ^
- // span3:
- assertEquals("a", charSequencesFromString[1].toString());
- assertSpanCount(0, charSequencesFromString[1]);
- assertEquals("a", charSequencesFromSpanned[1].toString());
- assertSpanCount(2, charSequencesFromSpanned[1]);
- assertSpan(charSequencesFromSpanned[1], span1, 0, 1, SPAN1_FLAGS);
- assertSpan(charSequencesFromSpanned[1], span2, 0, 1, SPAN2_FLAGS);
-
- // text: "bcd"
- // span1: ^^^
- // span2: ^^
- // span3:
- assertEquals("bcd", charSequencesFromString[2].toString());
- assertSpanCount(0, charSequencesFromString[2]);
- assertEquals("bcd", charSequencesFromSpanned[2].toString());
- assertSpanCount(2, charSequencesFromSpanned[2]);
- assertSpan(charSequencesFromSpanned[2], span1, 0, 3, SPAN1_FLAGS);
- assertSpan(charSequencesFromSpanned[2], span2, 0, 2, SPAN2_FLAGS);
-
- // text: "efg"
- // span1:
- // span2:
- // span3:
- assertEquals("efg", charSequencesFromString[3].toString());
- assertSpanCount(0, charSequencesFromString[3]);
- assertEquals("efg", charSequencesFromSpanned[3].toString());
- assertSpanCount(0, charSequencesFromSpanned[3]);
-
- // text: "hij"
- // span1:
- // span2:
- // span3: ^
- assertEquals("hij", charSequencesFromString[4].toString());
- assertSpanCount(0, charSequencesFromString[4]);
- assertEquals("hij", charSequencesFromSpanned[4].toString());
- assertSpanCount(1, charSequencesFromSpanned[4]);
- assertSpan(charSequencesFromSpanned[4], span3, 1, 2, SPAN3_FLAGS);
-
- // text: ""
- // span1:
- // span2:
- // span3:
- assertEquals("", charSequencesFromString[5].toString());
- assertSpanCount(0, charSequencesFromString[5]);
- assertEquals("", charSequencesFromSpanned[5].toString());
- assertSpanCount(0, charSequencesFromSpanned[5]);
-
- // text: ""
- // span1:
- // span2:
- // span3:
- assertEquals("", charSequencesFromString[6].toString());
- assertSpanCount(0, charSequencesFromString[6]);
- assertEquals("", charSequencesFromSpanned[6].toString());
- assertSpanCount(0, charSequencesFromSpanned[6]);
- }
-
- public void testSplitCharSequencePreserveTrailingEmptySegmengs() {
- assertEquals(1, StringUtils.split("", " ",
- false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(1, StringUtils.split(new SpannedString(""), " ",
- false /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(1, StringUtils.split("", " ",
- true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(1, StringUtils.split(new SpannedString(""), " ",
- true /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(0, StringUtils.split(" ", " ",
- false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(0, StringUtils.split(new SpannedString(" "), " ",
- false /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(2, StringUtils.split(" ", " ",
- true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(2, StringUtils.split(new SpannedString(" "), " ",
- true /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(3, StringUtils.split("a b c ", " ",
- false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(3, StringUtils.split(new SpannedString("a b c "), " ",
- false /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(5, StringUtils.split("a b c ", " ",
- true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(5, StringUtils.split(new SpannedString("a b c "), " ",
- true /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(6, StringUtils.split("a b ", " ",
- false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(6, StringUtils.split(new SpannedString("a b "), " ",
- false /* preserveTrailingEmptySegmengs */).length);
-
- assertEquals(7, StringUtils.split("a b ", " ",
- true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(7, StringUtils.split(new SpannedString("a b "), " ",
- true /* preserveTrailingEmptySegmengs */).length);
- }
}
diff --git a/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java b/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java
new file mode 100644
index 000000000..59bb08292
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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.common;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class UnicodeSurrogateTests extends AndroidTestCase {
+
+ public void testIsLowSurrogate() {
+ assertFalse(UnicodeSurrogate.isLowSurrogate('\uD7FF'));
+ assertTrue(UnicodeSurrogate.isLowSurrogate('\uD83D'));
+ assertFalse(UnicodeSurrogate.isLowSurrogate('\uDC00'));
+ }
+
+ public void testIsHighSurrogate() {
+ assertFalse(UnicodeSurrogate.isHighSurrogate('\uDBFF'));
+ assertTrue(UnicodeSurrogate.isHighSurrogate('\uDE25'));
+ assertFalse(UnicodeSurrogate.isHighSurrogate('\uE000'));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
deleted file mode 100644
index 406046a74..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ /dev/null
@@ -1,696 +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.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.ByteArrayDictBuffer;
-
-import java.io.File;
-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.Locale;
-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 = 300;
- private static final int DEFAULT_CODE_POINT_SET_SIZE = 50;
- private static final int LARGE_CODE_POINT_SET_SIZE = 300;
- 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 ArrayList<String> sWords = new ArrayList<>();
- private static final ArrayList<String> sWordsWithVariousCodePoints = new ArrayList<>();
- private static final SparseArray<List<Integer>> sEmptyBigrams = new SparseArray<>();
- private static final SparseArray<List<Integer>> sStarBigrams = new SparseArray<>();
- private static final SparseArray<List<Integer>> sChainBigrams = new SparseArray<>();
- private static final HashMap<String, List<String>> sShortcuts = new HashMap<>();
-
- public BinaryDictDecoderEncoderTests() {
- this(System.currentTimeMillis(), DEFAULT_MAX_UNIGRAMS);
- }
-
- public BinaryDictDecoderEncoderTests(final long seed, final int maxUnigrams) {
- super();
- BinaryDictionaryUtils.setCurrentTimeForTest(0);
- Log.e(TAG, "Testing dictionary: seed is " + seed);
- final Random random = new Random(seed);
- sWords.clear();
- sWordsWithVariousCodePoints.clear();
- generateWords(maxUnigrams, 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>());
- // MAX - 1 because we added one above already
- final int maxBigrams = Math.min(sWords.size(), FormatSpec.MAX_BIGRAMS_IN_A_PTNODE - 1);
- for (int i = 1; i < maxBigrams; ++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));
- }
- }
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- BinaryDictionaryUtils.setCurrentTimeForTest(0);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Quit test mode.
- BinaryDictionaryUtils.setCurrentTimeForTest(-1);
- super.tearDown();
- }
-
- private void generateWords(final int number, final Random random) {
- final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
- random);
- final Set<String> wordSet = new HashSet<>();
- while (wordSet.size() < number) {
- wordSet.add(CodePointUtils.generateWord(random, codePointSet));
- }
- sWords.addAll(wordSet);
-
- final int[] largeCodePointSet = CodePointUtils.generateCodePointSet(
- LARGE_CODE_POINT_SET_SIZE, random);
- wordSet.clear();
- while (wordSet.size() < number) {
- wordSet.add(CodePointUtils.generateWord(random, largeCodePointSet));
- }
- sWordsWithVariousCodePoints.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 = new ArrayList<>();
- if (shortcutMap != null && shortcutMap.containsKey(word)) {
- for (final String shortcut : shortcutMap.get(word)) {
- shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
- }
- }
- dict.add(word, new ProbabilityInfo(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), new ProbabilityInfo(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 = BinaryDictUtils.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 == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
- return result + " : version = " + formatOptions.mVersion;
- }
-
- // 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) {
- long now, diff = -1;
-
- FusionDictionary dict = null;
- try {
- final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
- bufferType);
- now = System.currentTimeMillis();
- dict = dictDecoder.readDictionaryBinary(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 = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
- getContext().getCacheDir());
-
- final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
- 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"));
- 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"));
- results.add(runReadAndWrite(sWordsWithVariousCodePoints, sEmptyBigrams,
- null /* shortcuts */, bufferType, formatOptions,
- "unigram with various code points"));
- }
-
- // 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) {
- 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 = new ArrayList<>();
-
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- public void testReadAndWriteWithByteArray() {
- final List<String> results = new ArrayList<>();
-
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
- runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
-
- 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,
- final boolean checkProbability) {
- // check unigrams
- final Set<String> actualWordsSet = new HashSet<>(resultWords.values());
- final Set<String> expectedWordsSet = new HashSet<>(expectedWords);
- assertEquals(actualWordsSet, expectedWordsSet);
- if (checkProbability) {
- for (int freq : resultFrequencies.values()) {
- assertEquals(freq, UNIGRAM_FREQ);
- }
- }
-
- // check bigrams
- final HashMap<String, Set<String>> expBigrams = new HashMap<>();
- 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 HashSet<String>());
- }
- expBigrams.get(word1).add(expectedWords.get(w2));
- }
- }
-
- final HashMap<String, Set<String>> actBigrams = new HashMap<>();
- 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 HashSet<String>());
- }
- actBigrams.get(word1).add(word2);
-
- if (checkProbability) {
- 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 boolean checkProbability) {
- final TreeMap<Integer, String> resultWords = new TreeMap<>();
- final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
- final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
-
- long now = -1, diff = -1;
- try {
- final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
- bufferType);
- 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);
- }
-
- checkWordMap(words, bigrams, resultWords, resultFreqs, resultBigrams, checkProbability);
- 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 = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
- getContext().getCacheDir());
-
- // making the dictionary from lists of words.
- final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
- addUnigrams(words.size(), dict, words, null /* shortcutMap */);
- addBigrams(dict, words, bigrams);
-
- timeWritingDictToFile(file, dict, formatOptions);
-
- // Caveat: Currently, the Java code to read a v4 dictionary doesn't calculate the
- // probability when there's a timestamp for the entry.
- // TODO: Abandon the Java code, and implement the v4 dictionary reading code in native.
- long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType,
- !formatOptions.mHasTimestamp /* checkProbability */);
- long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
- bufferType);
-
- 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 = new ArrayList<>();
-
- runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- public void testReadUnigramsAndBigramsBinaryWithByteArray() {
- final ArrayList<String> results = new ArrayList<>();
-
- runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
-
- 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);
-
- DictionaryHeader 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.mBodyOffset,
- address).mWord;
- }
-
- private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
- final boolean contained) {
- 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 = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
- getContext().getCacheDir());
-
- final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
- addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
- addBigrams(dict, words, bigrams);
- timeWritingDictToFile(file, dict, formatOptions);
-
- final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
- DictDecoder.USE_BYTEARRAY);
- try {
- dictDecoder.openDictBuffer();
- } catch (IOException e) {
- Log.e(TAG, "IOException while opening the buffer", e);
- } catch (UnsupportedFormatException e) {
- 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), 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, false);
- }
- }
-
- private void runGetTerminalPositionTests(final int bufferType,
- final FormatOptions formatOptions) {
- runGetTerminalPosition(sWords, sEmptyBigrams, bufferType, formatOptions, "unigram");
- }
-
- public void testGetTerminalPosition() {
- final ArrayList<String> results = new ArrayList<>();
-
- runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
- runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
-
- for (final String result : results) {
- Log.d(TAG, result);
- }
- }
-
- public void testVer2DictGetWordProperty() {
- final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
- final ArrayList<String> words = sWords;
- final HashMap<String, List<String>> shortcuts = sShortcuts;
- final String dictName = "testGetWordProperty";
- final String dictVersion = Long.toString(System.currentTimeMillis());
- final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
- addUnigrams(words.size(), dict, words, shortcuts);
- addBigrams(dict, words, sEmptyBigrams);
- final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
- getContext().getCacheDir());
- file.delete();
- timeWritingDictToFile(file, dict, formatOptions);
- final BinaryDictionary binaryDictionary = new BinaryDictionary(file.getAbsolutePath(),
- 0 /* offset */, file.length(), true /* useFullEditDistance */,
- Locale.ENGLISH, dictName, false /* isUpdatable */);
- for (final String word : words) {
- final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
- false /* isBeginningOfSentence */);
- assertEquals(word, wordProperty.mWord);
- assertEquals(UNIGRAM_FREQ, wordProperty.getProbability());
- if (shortcuts.containsKey(word)) {
- assertEquals(shortcuts.get(word).size(), wordProperty.mShortcutTargets.size());
- final List<String> shortcutList = shortcuts.get(word);
- assertTrue(wordProperty.mHasShortcuts);
- for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- assertTrue(shortcutList.contains(shortcutTarget.mWord));
- assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
- shortcutList.remove(shortcutTarget.mWord);
- }
- assertTrue(shortcutList.isEmpty());
- }
- }
- }
-
- public void testVer2DictIteration() {
- final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
- final ArrayList<String> words = sWords;
- final HashMap<String, List<String>> shortcuts = sShortcuts;
- final SparseArray<List<Integer>> bigrams = sEmptyBigrams;
- final String dictName = "testGetWordProperty";
- final String dictVersion = Long.toString(System.currentTimeMillis());
- final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
- addUnigrams(words.size(), dict, words, shortcuts);
- addBigrams(dict, words, bigrams);
- final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
- getContext().getCacheDir());
- timeWritingDictToFile(file, dict, formatOptions);
- Log.d(TAG, file.getAbsolutePath());
- final BinaryDictionary binaryDictionary = new BinaryDictionary(file.getAbsolutePath(),
- 0 /* offset */, file.length(), true /* useFullEditDistance */,
- Locale.ENGLISH, dictName, false /* isUpdatable */);
-
- final HashSet<String> wordSet = new HashSet<>(words);
- final HashSet<Pair<String, String>> bigramSet = new HashSet<>();
-
- for (int i = 0; i < words.size(); i++) {
- final List<Integer> bigramList = bigrams.get(i);
- if (bigramList != null) {
- for (final Integer word1Index : bigramList) {
- final String word1 = words.get(word1Index);
- bigramSet.add(new Pair<>(words.get(i), word1));
- }
- }
- }
- int token = 0;
- do {
- final BinaryDictionary.GetNextWordPropertyResult result =
- binaryDictionary.getNextWordProperty(token);
- final WordProperty wordProperty = result.mWordProperty;
- final String word0 = wordProperty.mWord;
- assertEquals(UNIGRAM_FREQ, wordProperty.mProbabilityInfo.mProbability);
- wordSet.remove(word0);
- if (shortcuts.containsKey(word0)) {
- assertEquals(shortcuts.get(word0).size(), wordProperty.mShortcutTargets.size());
- final List<String> shortcutList = shortcuts.get(word0);
- assertNotNull(wordProperty.mShortcutTargets);
- for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- assertTrue(shortcutList.contains(shortcutTarget.mWord));
- assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
- shortcutList.remove(shortcutTarget.mWord);
- }
- assertTrue(shortcutList.isEmpty());
- }
- for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
- final String word1 = wordProperty.mBigrams.get(j).mWord;
- final Pair<String, String> bigram = new Pair<>(word0, word1);
- assertTrue(bigramSet.contains(bigram));
- bigramSet.remove(bigram);
- }
- token = result.mNextToken;
- } while (token != 0);
- assertTrue(wordSet.isEmpty());
- assertTrue(bigramSet.isEmpty());
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 96604a197..be75565bb 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -17,11 +17,16 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import javax.annotation.Nonnull;
/**
* Decodes binary files for a FusionDictionary.
@@ -109,15 +114,20 @@ public final class BinaryDictDecoderUtils {
* A class grouping utility function for our specific character encoding.
*/
static final class CharEncoding {
- private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20;
- private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF;
/**
* Helper method to find out whether this code fits on one byte
*/
- private static boolean fitsOnOneByte(final int character) {
- return character >= MINIMAL_ONE_BYTE_CHARACTER_VALUE
- && character <= MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
+ private static boolean fitsOnOneByte(final int character,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ int codePoint = character;
+ if (codePointToOneByteCodeMap != null) {
+ if (codePointToOneByteCodeMap.containsKey(character)) {
+ codePoint = codePointToOneByteCodeMap.get(character);
+ }
+ }
+ return codePoint >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
+ && codePoint <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
}
/**
@@ -137,9 +147,10 @@ public final class BinaryDictDecoderUtils {
* @param character the character code.
* @return the size in binary encoded-form, either 1 or 3 bytes.
*/
- static int getCharSize(final int character) {
+ static int getCharSize(final int character,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
// See char encoding in FusionDictionary.java
- if (fitsOnOneByte(character)) return 1;
+ if (fitsOnOneByte(character, codePointToOneByteCodeMap)) return 1;
if (FormatSpec.INVALID_CHARACTER == character) return 1;
return 3;
}
@@ -147,9 +158,10 @@ public final class BinaryDictDecoderUtils {
/**
* Compute the byte size of a character array.
*/
- static int getCharArraySize(final int[] chars) {
+ static int getCharArraySize(final int[] chars,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
int size = 0;
- for (int character : chars) size += getCharSize(character);
+ for (int character : chars) size += getCharSize(character, codePointToOneByteCodeMap);
return size;
}
@@ -158,12 +170,21 @@ public final class BinaryDictDecoderUtils {
*
* @param codePoints the code point array to write.
* @param buffer the byte buffer to write to.
- * @param index the index in buffer to write the character array to.
+ * @param fromIndex the index in buffer to write the character array to.
+ * @param codePointToOneByteCodeMap the map to convert the code point.
* @return the index after the last character.
*/
- static int writeCharArray(final int[] codePoints, final byte[] buffer, int index) {
+ static int writeCharArray(final int[] codePoints, final byte[] buffer, final int fromIndex,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ int index = fromIndex;
for (int codePoint : codePoints) {
- if (1 == getCharSize(codePoint)) {
+ if (codePointToOneByteCodeMap != null) {
+ if (codePointToOneByteCodeMap.containsKey(codePoint)) {
+ // Convert code points
+ codePoint = codePointToOneByteCodeMap.get(codePoint);
+ }
+ }
+ if (1 == getCharSize(codePoint, codePointToOneByteCodeMap)) {
buffer[index++] = (byte)codePoint;
} else {
buffer[index++] = (byte)(0xFF & (codePoint >> 16));
@@ -184,12 +205,19 @@ public final class BinaryDictDecoderUtils {
* @param word the string to write.
* @return the size written, in bytes.
*/
- static int writeString(final byte[] buffer, final int origin, final String word) {
+ static int writeString(final byte[] buffer, final int origin, final String word,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
final int length = word.length();
int index = origin;
for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
- final int codePoint = word.codePointAt(i);
- if (1 == getCharSize(codePoint)) {
+ int codePoint = word.codePointAt(i);
+ if (codePointToOneByteCodeMap != null) {
+ if (codePointToOneByteCodeMap.containsKey(codePoint)) {
+ // Convert code points
+ codePoint = codePointToOneByteCodeMap.get(codePoint);
+ }
+ }
+ if (1 == getCharSize(codePoint, codePointToOneByteCodeMap)) {
buffer[index++] = (byte)codePoint;
} else {
buffer[index++] = (byte)(0xFF & (codePoint >> 16));
@@ -210,12 +238,13 @@ public final class BinaryDictDecoderUtils {
* @param word the string to write.
* @return the size written, in bytes.
*/
- static int writeString(final OutputStream stream, final String word) throws IOException {
+ static int writeString(final OutputStream stream, final String word,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) throws IOException {
final int length = word.length();
int written = 0;
for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
final int codePoint = word.codePointAt(i);
- final int charSize = getCharSize(codePoint);
+ final int charSize = getCharSize(codePoint, codePointToOneByteCodeMap);
if (1 == charSize) {
stream.write((byte) codePoint);
} else {
@@ -253,7 +282,7 @@ public final class BinaryDictDecoderUtils {
*/
static int readChar(final DictBuffer dictBuffer) {
int character = dictBuffer.readUnsignedByte();
- if (!fitsOnOneByte(character)) {
+ if (!fitsOnOneByte(character, null)) {
if (FormatSpec.PTNODE_CHARACTERS_TERMINATOR == character) {
return FormatSpec.INVALID_CHARACTER;
}
@@ -271,10 +300,9 @@ public final class BinaryDictDecoderUtils {
final int msb = dictBuffer.readUnsignedByte();
if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= msb) {
return msb;
- } else {
- return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
- + dictBuffer.readUnsignedByte();
}
+ return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
+ + dictBuffer.readUnsignedByte();
}
/**
@@ -338,6 +366,43 @@ public final class BinaryDictDecoderUtils {
}
/**
+ * Helper method that brutally decodes a header from a byte array.
+ *
+ * @param headerBuffer a buffer containing the bytes of the header.
+ * @return a hashmap of the attributes stored in the header
+ */
+ @Nonnull
+ public static HashMap<String, String> decodeHeaderAttributes(@Nonnull final byte[] headerBuffer)
+ throws UnsupportedFormatException {
+ final StringBuilder sb = new StringBuilder();
+ final LinkedList<String> keyValues = new LinkedList<>();
+ int index = 0;
+ while (index < headerBuffer.length) {
+ if (headerBuffer[index] == FormatSpec.PTNODE_CHARACTERS_TERMINATOR) {
+ keyValues.add(sb.toString());
+ sb.setLength(0);
+ } else if (CharEncoding.fitsOnOneByte(headerBuffer[index] & 0xFF,
+ null /* codePointTable */)) {
+ sb.appendCodePoint(headerBuffer[index] & 0xFF);
+ } else {
+ sb.appendCodePoint(((headerBuffer[index] & 0xFF) << 16)
+ + ((headerBuffer[index + 1] & 0xFF) << 8)
+ + (headerBuffer[index + 2] & 0xFF));
+ index += 2;
+ }
+ index += 1;
+ }
+ if ((keyValues.size() & 1) != 0) {
+ throw new UnsupportedFormatException("Odd number of attributes");
+ }
+ final HashMap<String, String> attributes = new HashMap<>();
+ for (int i = 0; i < keyValues.size(); i += 2) {
+ attributes.put(keyValues.get(i), keyValues.get(i + 1));
+ }
+ return attributes;
+ }
+
+ /**
* Helper method to pass a file name instead of a File object to isBinaryDictionary.
*/
public static boolean isBinaryDictionary(final String filename) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index eabd8d722..bd5136583 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -16,9 +16,7 @@
package com.android.inputmethod.latin.makedict;
-import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
@@ -27,6 +25,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map.Entry;
/**
* Encodes binary files for a FusionDictionary.
@@ -59,8 +59,9 @@ public class BinaryDictEncoderUtils {
* @param characters the character array
* @return the size of the char array, including the terminator if any
*/
- static int getPtNodeCharactersSize(final int[] characters) {
- int size = CharEncoding.getCharArraySize(characters);
+ static int getPtNodeCharactersSize(final int[] characters,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ int size = CharEncoding.getCharArraySize(characters, codePointToOneByteCodeMap);
if (characters.length > 1) size += FormatSpec.PTNODE_TERMINATOR_SIZE;
return size;
}
@@ -74,8 +75,9 @@ public class BinaryDictEncoderUtils {
* @param ptNode the PtNode
* @return the size of the char array, including the terminator if any
*/
- private static int getPtNodeCharactersSize(final PtNode ptNode) {
- return getPtNodeCharactersSize(ptNode.mChars);
+ private static int getPtNodeCharactersSize(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ return getPtNodeCharactersSize(ptNode.mChars, codePointToOneByteCodeMap);
}
/**
@@ -88,49 +90,19 @@ public class BinaryDictEncoderUtils {
}
/**
- * Compute the size of a shortcut in bytes.
- */
- private static int getShortcutSize(final WeightedString shortcut) {
- int size = FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE;
- final String word = shortcut.mWord;
- final int length = word.length();
- for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
- final int codePoint = word.codePointAt(i);
- size += CharEncoding.getCharSize(codePoint);
- }
- size += FormatSpec.PTNODE_TERMINATOR_SIZE;
- return size;
- }
-
- /**
- * Compute the size of a shortcut list in bytes.
- *
- * This is known in advance and does not change according to position in the file
- * like address lists do.
- */
- static int getShortcutListSize(final ArrayList<WeightedString> shortcutList) {
- if (null == shortcutList || shortcutList.isEmpty()) return 0;
- int size = FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
- for (final WeightedString shortcut : shortcutList) {
- size += getShortcutSize(shortcut);
- }
- return size;
- }
-
- /**
* Compute the maximum size of a PtNode, assuming 3-byte addresses for everything.
*
* @param ptNode the PtNode to compute the size of.
* @return the maximum size of the PtNode.
*/
- private static int getPtNodeMaximumSize(final PtNode ptNode) {
- int size = getNodeHeaderSize(ptNode);
+ private static int getPtNodeMaximumSize(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ int size = getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
if (ptNode.isTerminal()) {
// If terminal, one byte for the frequency.
size += FormatSpec.PTNODE_FREQUENCY_SIZE;
}
size += FormatSpec.PTNODE_MAX_ADDRESS_SIZE; // For children address
- size += getShortcutListSize(ptNode.mShortcutTargets);
if (null != ptNode.mBigrams) {
size += (FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE
+ FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE)
@@ -146,10 +118,11 @@ public class BinaryDictEncoderUtils {
*
* @param ptNodeArray the node array to compute the maximum size of.
*/
- private static void calculatePtNodeArrayMaximumSize(final PtNodeArray ptNodeArray) {
+ private static void calculatePtNodeArrayMaximumSize(final PtNodeArray ptNodeArray,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
int size = getPtNodeCountSize(ptNodeArray);
for (PtNode node : ptNodeArray.mData) {
- final int nodeSize = getPtNodeMaximumSize(node);
+ final int nodeSize = getPtNodeMaximumSize(node, codePointToOneByteCodeMap);
node.mCachedSize = nodeSize;
size += nodeSize;
}
@@ -161,8 +134,10 @@ public class BinaryDictEncoderUtils {
*
* @param ptNode the PtNode of which to compute the size of the header
*/
- private static int getNodeHeaderSize(final PtNode ptNode) {
- return FormatSpec.PTNODE_FLAGS_SIZE + getPtNodeCharactersSize(ptNode);
+ private static int getNodeHeaderSize(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ return FormatSpec.PTNODE_FLAGS_SIZE + getPtNodeCharactersSize(ptNode,
+ codePointToOneByteCodeMap);
}
/**
@@ -188,8 +163,9 @@ public class BinaryDictEncoderUtils {
}
}
- static int writeUIntToBuffer(final byte[] buffer, int position, final int value,
+ static int writeUIntToBuffer(final byte[] buffer, final int fromPosition, final int value,
final int size) {
+ int position = fromPosition;
switch(size) {
case 4:
buffer[position++] = (byte) ((value >> 24) & 0xFF);
@@ -229,27 +205,6 @@ public class BinaryDictEncoderUtils {
}
}
- @UsedForTesting
- static void writeUIntToDictBuffer(final DictBuffer dictBuffer, final int value,
- final int size) {
- switch(size) {
- case 4:
- dictBuffer.put((byte) ((value >> 24) & 0xFF));
- /* fall through */
- case 3:
- dictBuffer.put((byte) ((value >> 16) & 0xFF));
- /* fall through */
- case 2:
- dictBuffer.put((byte) ((value >> 8) & 0xFF));
- /* fall through */
- case 1:
- dictBuffer.put((byte) (value & 0xFF));
- break;
- default:
- /* nop */
- }
- }
-
// End utility methods
// This method is responsible for finding a nice ordering of the nodes that favors run-time
@@ -313,11 +268,9 @@ public class BinaryDictEncoderUtils {
return targetNodeArray.mCachedAddressAfterUpdate
- (currentNodeArray.mCachedAddressAfterUpdate
+ offsetFromStartOfCurrentNodeArray);
- } else {
- return targetNodeArray.mCachedAddressBeforeUpdate
- - (currentNodeArray.mCachedAddressBeforeUpdate
- + offsetFromStartOfCurrentNodeArray);
}
+ return targetNodeArray.mCachedAddressBeforeUpdate
+ - (currentNodeArray.mCachedAddressBeforeUpdate + offsetFromStartOfCurrentNodeArray);
}
/**
@@ -345,9 +298,8 @@ public class BinaryDictEncoderUtils {
final int newOffsetBasePoint = currentNodeArray.mCachedAddressAfterUpdate
+ offsetFromStartOfCurrentNodeArray;
return targetPtNode.mCachedAddressAfterUpdate - newOffsetBasePoint;
- } else {
- return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
}
+ return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
}
/**
@@ -365,7 +317,8 @@ public class BinaryDictEncoderUtils {
* @return false if none of the cached addresses inside the node array changed, true otherwise.
*/
private static boolean computeActualPtNodeArraySize(final PtNodeArray ptNodeArray,
- final FusionDictionary dict) {
+ final FusionDictionary dict,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
boolean changed = false;
int size = getPtNodeCountSize(ptNodeArray);
for (PtNode ptNode : ptNodeArray.mData) {
@@ -373,7 +326,7 @@ public class BinaryDictEncoderUtils {
if (ptNode.mCachedAddressAfterUpdate != ptNode.mCachedAddressBeforeUpdate) {
changed = true;
}
- int nodeSize = getNodeHeaderSize(ptNode);
+ int nodeSize = getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
if (ptNode.isTerminal()) {
nodeSize += FormatSpec.PTNODE_FREQUENCY_SIZE;
}
@@ -381,7 +334,6 @@ public class BinaryDictEncoderUtils {
nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
nodeSize + size, ptNode.mChildren));
}
- nodeSize += getShortcutListSize(ptNode.mShortcutTargets);
if (null != ptNode.mBigrams) {
for (WeightedString bigram : ptNode.mBigrams) {
final int offset = getOffsetToTargetPtNodeDuringUpdate(ptNodeArray,
@@ -452,10 +404,11 @@ public class BinaryDictEncoderUtils {
* @return the same array it was passed. The nodes have been updated for address and size.
*/
/* package */ static ArrayList<PtNodeArray> computeAddresses(final FusionDictionary dict,
- final ArrayList<PtNodeArray> flatNodes) {
+ final ArrayList<PtNodeArray> flatNodes,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
// First get the worst possible sizes and offsets
for (final PtNodeArray n : flatNodes) {
- calculatePtNodeArrayMaximumSize(n);
+ calculatePtNodeArrayMaximumSize(n, codePointToOneByteCodeMap);
}
final int offset = initializePtNodeArraysCachedAddresses(flatNodes);
@@ -470,7 +423,8 @@ public class BinaryDictEncoderUtils {
for (final PtNodeArray ptNodeArray : flatNodes) {
ptNodeArray.mCachedAddressAfterUpdate = ptNodeArrayStartOffset;
final int oldNodeArraySize = ptNodeArray.mCachedSize;
- final boolean changed = computeActualPtNodeArraySize(ptNodeArray, dict);
+ final boolean changed = computeActualPtNodeArraySize(ptNodeArray, dict,
+ codePointToOneByteCodeMap);
final int newNodeArraySize = ptNodeArray.mCachedSize;
if (oldNodeArraySize < newNodeArraySize) {
throw new RuntimeException("Increased size ?!");
@@ -521,12 +475,13 @@ public class BinaryDictEncoderUtils {
* Helper method to write a children position to a file.
*
* @param buffer the buffer to write to.
- * @param index the index in the buffer to write the address to.
+ * @param fromIndex the index in the buffer to write the address to.
* @param position the position to write.
* @return the size in bytes the address actually took.
*/
- /* package */ static int writeChildrenPosition(final byte[] buffer, int index,
+ /* package */ static int writeChildrenPosition(final byte[] buffer, final int fromIndex,
final int position) {
+ int index = fromIndex;
switch (getByteSize(position)) {
case 1:
buffer[index++] = (byte)position;
@@ -548,42 +503,19 @@ public class BinaryDictEncoderUtils {
}
/**
- * Helper method to write a signed children position to a file.
- *
- * @param buffer the buffer to write to.
- * @param index the index in the buffer to write the address to.
- * @param position the position to write.
- * @return the size in bytes the address actually took.
- */
- /* package */ static int writeSignedChildrenPosition(final byte[] buffer, int index,
- final int position) {
- if (!BinaryDictIOUtils.hasChildrenAddress(position)) {
- buffer[index] = buffer[index + 1] = buffer[index + 2] = 0;
- } else {
- final int absPosition = Math.abs(position);
- buffer[index++] =
- (byte)((position < 0 ? FormatSpec.MSB8 : 0) | (0xFF & (absPosition >> 16)));
- buffer[index++] = (byte)(0xFF & (absPosition >> 8));
- buffer[index++] = (byte)(0xFF & absPosition);
- }
- return 3;
- }
-
- /**
* Makes the flag value for a PtNode.
*
* @param hasMultipleChars whether the PtNode has multiple chars.
* @param isTerminal whether the PtNode is terminal.
* @param childrenAddressSize the size of a children address.
- * @param hasShortcuts whether the PtNode has shortcuts.
* @param hasBigrams whether the PtNode has bigrams.
* @param isNotAWord whether the PtNode is not a word.
- * @param isBlackListEntry whether the PtNode is a blacklist entry.
+ * @param isPossiblyOffensive whether the PtNode is a possibly offensive entry.
* @return the flags
*/
static int makePtNodeFlags(final boolean hasMultipleChars, final boolean isTerminal,
- final int childrenAddressSize, final boolean hasShortcuts, final boolean hasBigrams,
- final boolean isNotAWord, final boolean isBlackListEntry) {
+ final int childrenAddressSize, final boolean hasBigrams,
+ final boolean isNotAWord, final boolean isPossiblyOffensive) {
byte flags = 0;
if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
if (isTerminal) flags |= FormatSpec.FLAG_IS_TERMINAL;
@@ -603,19 +535,17 @@ public class BinaryDictEncoderUtils {
default:
throw new RuntimeException("Node with a strange address");
}
- if (hasShortcuts) flags |= FormatSpec.FLAG_HAS_SHORTCUT_TARGETS;
if (hasBigrams) flags |= FormatSpec.FLAG_HAS_BIGRAMS;
if (isNotAWord) flags |= FormatSpec.FLAG_IS_NOT_A_WORD;
- if (isBlackListEntry) flags |= FormatSpec.FLAG_IS_BLACKLISTED;
+ if (isPossiblyOffensive) flags |= FormatSpec.FLAG_IS_POSSIBLY_OFFENSIVE;
return flags;
}
/* package */ static byte makePtNodeFlags(final PtNode node, final int childrenOffset) {
return (byte) makePtNodeFlags(node.mChars.length > 1, node.isTerminal(),
getByteSize(childrenOffset),
- node.mShortcutTargets != null && !node.mShortcutTargets.isEmpty(),
node.mBigrams != null && !node.mBigrams.isEmpty(),
- node.mIsNotAWord, node.mIsBlacklistEntry);
+ node.mIsNotAWord, node.mIsPossiblyOffensive);
}
/**
@@ -628,8 +558,8 @@ public class BinaryDictEncoderUtils {
* @param word the second bigram, for debugging purposes
* @return the flags
*/
- /* package */ static final int makeBigramFlags(final boolean more, final int offset,
- int bigramFrequency, final int unigramFrequency, final String word) {
+ /* package */ static int makeBigramFlags(final boolean more, final int offset,
+ final int bigramFrequency, final int unigramFrequency, final String word) {
int bigramFlags = (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
+ (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
switch (getByteSize(offset)) {
@@ -645,13 +575,16 @@ public class BinaryDictEncoderUtils {
default:
throw new RuntimeException("Strange offset size");
}
+ final int frequency;
if (unigramFrequency > bigramFrequency) {
MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
+ "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
+ word + " is " + unigramFrequency);
- bigramFrequency = unigramFrequency;
+ frequency = unigramFrequency;
+ } else {
+ frequency = bigramFrequency;
}
- bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency)
+ bigramFlags += getBigramFrequencyDiff(unigramFrequency, frequency)
& FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
return bigramFlags;
}
@@ -694,21 +627,10 @@ public class BinaryDictEncoderUtils {
return discretizedFrequency > 0 ? discretizedFrequency : 0;
}
- /**
- * Makes the flag value for a shortcut.
- *
- * @param more whether there are more attributes after this one.
- * @param frequency the frequency of the attribute, 0..15
- * @return the flags
- */
- static final int makeShortcutFlags(final boolean more, final int frequency) {
- return (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
- + (frequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY);
- }
-
- /* package */ static final int getChildrenPosition(final PtNode ptNode) {
+ /* package */ static int getChildrenPosition(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
int positionOfChildrenPosField = ptNode.mCachedAddressAfterUpdate
- + getNodeHeaderSize(ptNode);
+ + getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
if (ptNode.isTerminal()) {
// A terminal node has the frequency.
// If positionOfChildrenPosField is incorrect, we may crash when jumping to the children
@@ -725,19 +647,16 @@ public class BinaryDictEncoderUtils {
* @param dict the dictionary the node array is a part of (for relative offsets).
* @param dictEncoder the dictionary encoder.
* @param ptNodeArray the node array to write.
+ * @param codePointToOneByteCodeMap the map to convert the code points.
*/
- @SuppressWarnings("unused")
/* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
- final DictEncoder dictEncoder, final PtNodeArray ptNodeArray) {
+ final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
// TODO: Make the code in common with BinaryDictIOUtils#writePtNode
dictEncoder.setPosition(ptNodeArray.mCachedAddressAfterUpdate);
final int ptNodeCount = ptNodeArray.mData.size();
dictEncoder.writePtNodeCount(ptNodeCount);
- final int parentPosition =
- (ptNodeArray.mCachedParentAddress == FormatSpec.NO_PARENT_ADDRESS)
- ? FormatSpec.NO_PARENT_ADDRESS
- : ptNodeArray.mCachedParentAddress + ptNodeArray.mCachedAddressAfterUpdate;
for (int i = 0; i < ptNodeCount; ++i) {
final PtNode ptNode = ptNodeArray.mData.get(i);
if (dictEncoder.getPosition() != ptNode.mCachedAddressAfterUpdate) {
@@ -751,7 +670,7 @@ public class BinaryDictEncoderUtils {
+ FormatSpec.MAX_TERMINAL_FREQUENCY
+ " : " + ptNode.mProbabilityInfo.toString());
}
- dictEncoder.writePtNode(ptNode, dict);
+ dictEncoder.writePtNode(ptNode, dict, codePointToOneByteCodeMap);
}
if (dictEncoder.getPosition() != ptNodeArray.mCachedAddressAfterUpdate
+ ptNodeArray.mCachedSize) {
@@ -817,18 +736,26 @@ public class BinaryDictEncoderUtils {
* @param destination the stream to write the file header to.
* @param dict the dictionary to write.
* @param formatOptions file format options.
+ * @param codePointOccurrenceArray code points ordered by occurrence count.
* @return the size of the header.
*/
/* package */ static int writeDictionaryHeader(final OutputStream destination,
- final FusionDictionary dict, final FormatOptions formatOptions)
+ final FusionDictionary dict, final FormatOptions formatOptions,
+ final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray)
throws IOException, UnsupportedFormatException {
final int version = formatOptions.mVersion;
- if (version < FormatSpec.MINIMUM_SUPPORTED_VERSION
- || version > FormatSpec.MAXIMUM_SUPPORTED_VERSION) {
+ if ((version >= FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION &&
+ version <= FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION) || (
+ version >= FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION &&
+ version <= FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION)) {
+ // Dictionary is valid
+ } else {
throw new UnsupportedFormatException("Requested file format version " + version
- + ", but this implementation only supports versions "
- + FormatSpec.MINIMUM_SUPPORTED_VERSION + " through "
- + FormatSpec.MAXIMUM_SUPPORTED_VERSION);
+ + ", but this implementation only supports static versions "
+ + FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION + " through "
+ + FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION + " and dynamic versions "
+ + FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION + " through "
+ + FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION);
}
ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256);
@@ -856,8 +783,15 @@ public class BinaryDictEncoderUtils {
// Write out the options.
for (final String key : dict.mOptions.mAttributes.keySet()) {
final String value = dict.mOptions.mAttributes.get(key);
- CharEncoding.writeString(headerBuffer, key);
- CharEncoding.writeString(headerBuffer, value);
+ CharEncoding.writeString(headerBuffer, key, null);
+ CharEncoding.writeString(headerBuffer, value, null);
+ }
+ // Write out the codePointTable if there is codePointOccurrenceArray.
+ if (codePointOccurrenceArray != null) {
+ final String codePointTableString =
+ encodeCodePointTable(codePointOccurrenceArray);
+ CharEncoding.writeString(headerBuffer, DictionaryHeader.CODE_POINT_TABLE_KEY, null);
+ CharEncoding.writeString(headerBuffer, codePointTableString, null);
}
final int size = headerBuffer.size();
final byte[] bytes = headerBuffer.toByteArray();
@@ -871,4 +805,35 @@ public class BinaryDictEncoderUtils {
headerBuffer.close();
return size;
}
+
+ static final class CodePointTable {
+ final HashMap<Integer, Integer> mCodePointToOneByteCodeMap;
+ final ArrayList<Entry<Integer, Integer>> mCodePointOccurrenceArray;
+
+ // Let code point table empty for version 200 dictionary which used in test
+ CodePointTable() {
+ mCodePointToOneByteCodeMap = null;
+ mCodePointOccurrenceArray = null;
+ }
+
+ CodePointTable(final HashMap<Integer, Integer> codePointToOneByteCodeMap,
+ final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray) {
+ mCodePointToOneByteCodeMap = codePointToOneByteCodeMap;
+ mCodePointOccurrenceArray = codePointOccurrenceArray;
+ }
+ }
+
+ private static String encodeCodePointTable(
+ final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray) {
+ final StringBuilder codePointTableString = new StringBuilder();
+ int currentCodePointTableIndex = FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE;
+ for (final Entry<Integer, Integer> entry : codePointOccurrenceArray) {
+ // Native reads the table as a string
+ codePointTableString.appendCodePoint(entry.getKey());
+ if (FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE < ++currentCodePointTableIndex) {
+ break;
+ }
+ }
+ return codePointTableString.toString();
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 9c3b37387..da1b32a8b 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -17,7 +17,7 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
import java.io.File;
@@ -43,22 +43,12 @@ public final class BinaryDictIOUtils {
*/
public static DictDecoder getDictDecoder(final File dictFile, final long offset,
final long length, final int bufferType) {
- if (dictFile.isDirectory()) {
- return new Ver4DictDecoder(dictFile, bufferType);
- } else if (dictFile.isFile()) {
- return new Ver2DictDecoder(dictFile, offset, length, bufferType);
- }
- return null;
+ return new Ver4DictDecoder(dictFile);
}
public static DictDecoder getDictDecoder(final File dictFile, final long offset,
final long length, final DictionaryBufferFactory factory) {
- if (dictFile.isDirectory()) {
- return new Ver4DictDecoder(dictFile, factory);
- } else if (dictFile.isFile()) {
- return new Ver2DictDecoder(dictFile, offset, length, factory);
- }
- return null;
+ return new Ver4DictDecoder(dictFile);
}
public static DictDecoder getDictDecoder(final File dictFile, final long offset,
@@ -183,7 +173,7 @@ public final class BinaryDictIOUtils {
dictDecoder.readHeader();
int wordPos = 0;
final int wordLen = word.codePointCount(0, word.length());
- for (int depth = 0; depth < Constants.DICTIONARY_MAX_WORD_LENGTH; ++depth) {
+ for (int depth = 0; depth < DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH; ++depth) {
if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD;
do {
@@ -206,11 +196,7 @@ public final class BinaryDictIOUtils {
if (same) {
// found the PtNode matches the word.
if (wordPos + currentInfo.mCharacters.length == wordLen) {
- if (!currentInfo.isTerminal()) {
- return FormatSpec.NOT_VALID_WORD;
- } else {
- return ptNodePos;
- }
+ return currentInfo.isTerminal() ? ptNodePos : FormatSpec.NOT_VALID_WORD;
}
wordPos += currentInfo.mCharacters.length;
if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
deleted file mode 100644
index 5a3eba801..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.FormatSpec.DictionaryOptions;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-
-import java.io.File;
-import java.util.HashMap;
-
-public class BinaryDictUtils {
- public static final int USE_BYTE_ARRAY = 1;
- public static final int USE_BYTE_BUFFER = 2;
-
- public static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-
- public static final FormatSpec.FormatOptions VERSION2_OPTIONS =
- new FormatSpec.FormatOptions(FormatSpec.VERSION2);
- public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITHOUT_TIMESTAMP =
- new FormatSpec.FormatOptions(FormatSpec.VERSION4, false /* hasTimestamp */);
- public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITH_TIMESTAMP =
- new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* hasTimestamp */);
-
- public static DictionaryOptions makeDictionaryOptions(final String id, final String version,
- final FormatSpec.FormatOptions formatOptions) {
- final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>());
- options.mAttributes.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, "en_US");
- options.mAttributes.put(DictionaryHeader.DICTIONARY_ID_KEY, id);
- options.mAttributes.put(DictionaryHeader.DICTIONARY_VERSION_KEY, version);
- if (formatOptions.mHasTimestamp) {
- options.mAttributes.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- options.mAttributes.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- }
- return options;
- }
-
- public static File getDictFile(final String name, final String version,
- final FormatOptions formatOptions, final File directory) {
- if (formatOptions.mVersion == FormatSpec.VERSION2) {
- return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION);
- } else if (formatOptions.mVersion == FormatSpec.VERSION4) {
- return new File(directory, name + "." + version);
- } else {
- throw new RuntimeException("the format option has a wrong version : "
- + formatOptions.mVersion);
- }
- }
-
- public static DictEncoder getDictEncoder(final File file, final FormatOptions formatOptions) {
- if (formatOptions.mVersion == FormatSpec.VERSION4) {
- if (!file.isDirectory()) {
- file.mkdir();
- }
- return new Ver4DictEncoder(file);
- } else if (formatOptions.mVersion == FormatSpec.VERSION2) {
- return new Ver2DictEncoder(file);
- } else {
- throw new RuntimeException("The format option has a wrong version : "
- + formatOptions.mVersion);
- }
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java b/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
deleted file mode 100644
index a270ee774..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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 final int[] LATIN_ALPHABETS_LOWER = {
- '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',
- 0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
- 0x00E1 /* LATIN SMALL LETTER A WITH ACUTE */,
- 0x00E2 /* LATIN SMALL LETTER A WITH CIRCUMFLEX */,
- 0x00E3 /* LATIN SMALL LETTER A WITH TILDE */,
- 0x00E4 /* LATIN SMALL LETTER A WITH DIAERESIS */,
- 0x00E5 /* LATIN SMALL LETTER A WITH RING ABOVE */,
- 0x00E6 /* LATIN SMALL LETTER AE */,
- 0x00E7 /* LATIN SMALL LETTER C WITH CEDILLA */,
- 0x00E8 /* LATIN SMALL LETTER E WITH GRAVE */,
- 0x00E9 /* LATIN SMALL LETTER E WITH ACUTE */,
- 0x00EA /* LATIN SMALL LETTER E WITH CIRCUMFLEX */,
- 0x00EB /* LATIN SMALL LETTER E WITH DIAERESIS */,
- 0x00EC /* LATIN SMALL LETTER I WITH GRAVE */,
- 0x00ED /* LATIN SMALL LETTER I WITH ACUTE */,
- 0x00EE /* LATIN SMALL LETTER I WITH CIRCUMFLEX */,
- 0x00EF /* LATIN SMALL LETTER I WITH DIAERESIS */,
- 0x00F0 /* LATIN SMALL LETTER ETH */,
- 0x00F1 /* LATIN SMALL LETTER N WITH TILDE */,
- 0x00F2 /* LATIN SMALL LETTER O WITH GRAVE */,
- 0x00F3 /* LATIN SMALL LETTER O WITH ACUTE */,
- 0x00F4 /* LATIN SMALL LETTER O WITH CIRCUMFLEX */,
- 0x00F5 /* LATIN SMALL LETTER O WITH TILDE */,
- 0x00F6 /* LATIN SMALL LETTER O WITH DIAERESIS */,
- 0x00F7 /* LATIN SMALL LETTER O WITH STROKE */,
- 0x00F9 /* LATIN SMALL LETTER U WITH GRAVE */,
- 0x00FA /* LATIN SMALL LETTER U WITH ACUTE */,
- 0x00FB /* LATIN SMALL LETTER U WITH CIRCUMFLEX */,
- 0x00FC /* LATIN SMALL LETTER U WITH DIAERESIS */,
- 0x00FD /* LATIN SMALL LETTER Y WITH ACUTE */,
- 0x00FE /* LATIN SMALL LETTER THORN */,
- 0x00FF /* LATIN SMALL LETTER Y WITH DIAERESIS */
- };
-
- 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/DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
index 678c5ca6b..10dd00325 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
@@ -21,6 +21,7 @@ import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import java.io.IOException;
+import java.util.HashMap;
/**
* An interface of binary dictionary encoder.
@@ -33,6 +34,6 @@ public interface DictEncoder {
public void setPosition(final int position);
public int getPosition();
public void writePtNodeCount(final int ptNodeCount);
- public void writeForwardLinkAddress(final int forwardLinkAddress);
- public void writePtNode(final PtNode ptNode, final FusionDictionary dict);
+ public void writePtNode(final PtNode ptNode, final FusionDictionary dict,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap);
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index 4a8c178b5..52060bed2 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -17,7 +17,7 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
import java.util.ArrayList;
@@ -82,14 +82,13 @@ public final class FusionDictionary implements Iterable<WordProperty> {
public static final class PtNode {
private static final int NOT_A_TERMINAL = -1;
final int mChars[];
- ArrayList<WeightedString> mShortcutTargets;
ArrayList<WeightedString> mBigrams;
// null == mProbabilityInfo indicates this is not a terminal.
ProbabilityInfo mProbabilityInfo;
int mTerminalId; // NOT_A_TERMINAL == mTerminalId indicates this is not a terminal.
PtNodeArray mChildren;
boolean mIsNotAWord; // Only a shortcut
- boolean mIsBlacklistEntry;
+ boolean mIsPossiblyOffensive;
// mCachedSize and mCachedAddressBefore/AfterUpdate are helpers for binary dictionary
// generation. Before and After always hold the same value except during dictionary
// address compression, where the update process needs to know about both values at the
@@ -100,30 +99,27 @@ public final class FusionDictionary implements Iterable<WordProperty> {
int mCachedAddressBeforeUpdate; // The address of this PtNode (before update)
int mCachedAddressAfterUpdate; // The address of this PtNode (after update)
- public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
- final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
- final boolean isNotAWord, final boolean isBlacklistEntry) {
+ public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+ final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+ final boolean isPossiblyOffensive) {
mChars = chars;
mProbabilityInfo = probabilityInfo;
mTerminalId = probabilityInfo == null ? NOT_A_TERMINAL : probabilityInfo.mProbability;
- mShortcutTargets = shortcutTargets;
mBigrams = bigrams;
mChildren = null;
mIsNotAWord = isNotAWord;
- mIsBlacklistEntry = isBlacklistEntry;
+ mIsPossiblyOffensive = isPossiblyOffensive;
}
- public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
- final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
- final boolean isNotAWord, final boolean isBlacklistEntry,
- final PtNodeArray children) {
+ public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+ final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+ final boolean isPossiblyOffensive, final PtNodeArray children) {
mChars = chars;
mProbabilityInfo = probabilityInfo;
- mShortcutTargets = shortcutTargets;
mBigrams = bigrams;
mChildren = children;
mIsNotAWord = isNotAWord;
- mIsBlacklistEntry = isBlacklistEntry;
+ mIsPossiblyOffensive = isPossiblyOffensive;
}
public void addChild(PtNode n) {
@@ -142,27 +138,15 @@ public final class FusionDictionary implements Iterable<WordProperty> {
}
public int getProbability() {
- if (isTerminal()) {
- return mProbabilityInfo.mProbability;
- } else {
- return NOT_A_TERMINAL;
- }
+ return isTerminal() ? mProbabilityInfo.mProbability : NOT_A_TERMINAL;
}
public boolean getIsNotAWord() {
return mIsNotAWord;
}
- public boolean getIsBlacklistEntry() {
- return mIsBlacklistEntry;
- }
-
- public ArrayList<WeightedString> getShortcutTargets() {
- // We don't want write permission to escape outside the package, so we return a copy
- if (null == mShortcutTargets) return null;
- final ArrayList<WeightedString> copyOfShortcutTargets =
- new ArrayList<>(mShortcutTargets);
- return copyOfShortcutTargets;
+ public boolean getIsPossiblyOffensive() {
+ return mIsPossiblyOffensive;
}
public ArrayList<WeightedString> getBigrams() {
@@ -195,24 +179,6 @@ public final class FusionDictionary implements Iterable<WordProperty> {
}
/**
- * Gets the shortcut target for the given word. Returns null if the word is not in the
- * shortcut list.
- */
- public WeightedString getShortcut(final String word) {
- // TODO: Don't do a linear search
- if (mShortcutTargets != null) {
- final int size = mShortcutTargets.size();
- for (int i = 0; i < size; ++i) {
- WeightedString shortcut = mShortcutTargets.get(i);
- if (shortcut.mWord.equals(word)) {
- return shortcut;
- }
- }
- }
- return null;
- }
-
- /**
* Gets the bigram for the given word.
* Returns null if the word is not in the bigrams list.
*/
@@ -235,28 +201,10 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
* updated if they are higher than the existing ones.
*/
- private void update(final ProbabilityInfo probabilityInfo,
- final ArrayList<WeightedString> shortcutTargets,
+ void update(final ProbabilityInfo probabilityInfo,
final ArrayList<WeightedString> bigrams,
- final boolean isNotAWord, final boolean isBlacklistEntry) {
+ final boolean isNotAWord, final boolean isPossiblyOffensive) {
mProbabilityInfo = ProbabilityInfo.max(mProbabilityInfo, probabilityInfo);
- if (shortcutTargets != null) {
- if (mShortcutTargets == null) {
- mShortcutTargets = shortcutTargets;
- } else {
- final int size = shortcutTargets.size();
- for (int i = 0; i < size; ++i) {
- final WeightedString shortcut = shortcutTargets.get(i);
- final WeightedString existingShortcut = getShortcut(shortcut.mWord);
- if (existingShortcut == null) {
- mShortcutTargets.add(shortcut);
- } else {
- existingShortcut.mProbabilityInfo = ProbabilityInfo.max(
- existingShortcut.mProbabilityInfo, shortcut.mProbabilityInfo);
- }
- }
- }
- }
if (bigrams != null) {
if (mBigrams == null) {
mBigrams = bigrams;
@@ -275,7 +223,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
}
}
mIsNotAWord = isNotAWord;
- mIsBlacklistEntry = isBlacklistEntry;
+ mIsPossiblyOffensive = isPossiblyOffensive;
}
}
@@ -316,31 +264,16 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* Helper method to add a word as a string.
*
* This method adds a word to the dictionary with the given frequency. Optional
- * lists of bigrams and shortcuts can be passed here. For each word inside,
+ * lists of bigrams can be passed here. For each word inside,
* they will be added to the dictionary as necessary.
- *
- * @param word the word to add.
+ * @param word the word to add.
* @param probabilityInfo probability information of the word.
- * @param shortcutTargets a list of shortcut targets for this word, or null.
* @param isNotAWord true if this should not be considered a word (e.g. shortcut only)
+ * @param isPossiblyOffensive true if this word is possibly offensive
*/
public void add(final String word, final ProbabilityInfo probabilityInfo,
- final ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord) {
- add(getCodePoints(word), probabilityInfo, shortcutTargets, isNotAWord,
- false /* isBlacklistEntry */);
- }
-
- /**
- * Helper method to add a blacklist entry as a string.
- *
- * @param word the word to add as a blacklist entry.
- * @param shortcutTargets a list of shortcut targets for this word, or null.
- * @param isNotAWord true if this is not a word for spellcheking purposes (shortcut only or so)
- */
- public void addBlacklistEntry(final String word,
- final ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord) {
- add(getCodePoints(word), new ProbabilityInfo(0), shortcutTargets, isNotAWord,
- true /* isBlacklistEntry */);
+ final boolean isNotAWord, final boolean isPossiblyOffensive) {
+ add(getCodePoints(word), probabilityInfo, isNotAWord, isPossiblyOffensive);
}
/**
@@ -349,15 +282,15 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* This method checks that all PtNodes in a node array are ordered as expected.
* If they are, nothing happens. If they aren't, an exception is thrown.
*/
- private void checkStack(PtNodeArray ptNodeArray) {
+ private static void checkStack(PtNodeArray ptNodeArray) {
ArrayList<PtNode> stack = ptNodeArray.mData;
int lastValue = -1;
for (int i = 0; i < stack.size(); ++i) {
int currentValue = stack.get(i).mChars[0];
- if (currentValue <= lastValue)
+ if (currentValue <= lastValue) {
throw new RuntimeException("Invalid stack");
- else
- lastValue = currentValue;
+ }
+ lastValue = currentValue;
}
}
@@ -374,8 +307,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
if (ptNode0 != null) {
final PtNode ptNode1 = findWordInTree(mRootNodeArray, word1);
if (ptNode1 == null) {
- add(getCodePoints(word1), new ProbabilityInfo(0), null, false /* isNotAWord */,
- false /* isBlacklistEntry */);
+ add(getCodePoints(word1), new ProbabilityInfo(0), false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
// The PtNode for the first word may have moved by the above insertion,
// if word1 and word2 share a common stem that happens not to have been
// a cutting point until now. In this case, we need to refresh ptNode.
@@ -392,18 +325,15 @@ public final class FusionDictionary implements Iterable<WordProperty> {
*
* The shortcuts, if any, have to be in the dictionary already. If they aren't,
* an exception is thrown.
- *
- * @param word the word, as an int array.
+ * @param word the word, as an int array.
* @param probabilityInfo the probability information of the word.
- * @param shortcutTargets an optional list of shortcut targets for this word (null if none).
* @param isNotAWord true if this is not a word for spellcheking purposes (shortcut only or so)
- * @param isBlacklistEntry true if this is a blacklisted word, false otherwise
+ * @param isPossiblyOffensive true if this word is possibly offensive
*/
private void add(final int[] word, final ProbabilityInfo probabilityInfo,
- final ArrayList<WeightedString> shortcutTargets,
- final boolean isNotAWord, final boolean isBlacklistEntry) {
+ final boolean isNotAWord, final boolean isPossiblyOffensive) {
assert(probabilityInfo.mProbability <= FormatSpec.MAX_TERMINAL_FREQUENCY);
- if (word.length >= Constants.DICTIONARY_MAX_WORD_LENGTH) {
+ if (word.length >= DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) {
MakedictLog.w("Ignoring a word that is too long: word.length = " + word.length);
return;
}
@@ -430,8 +360,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
// No node at this point to accept the word. Create one.
final int insertionIndex = findInsertionIndex(currentNodeArray, word[charIndex]);
final PtNode newPtNode = new PtNode(Arrays.copyOfRange(word, charIndex, word.length),
- shortcutTargets, null /* bigrams */, probabilityInfo, isNotAWord,
- isBlacklistEntry);
+ null /* bigrams */, probabilityInfo, isNotAWord,
+ isPossiblyOffensive);
currentNodeArray.mData.add(insertionIndex, newPtNode);
if (DBG) checkStack(currentNodeArray);
} else {
@@ -441,15 +371,15 @@ public final class FusionDictionary implements Iterable<WordProperty> {
// The new word is a prefix of an existing word, but the node on which it
// should end already exists as is. Since the old PtNode was not a terminal,
// make it one by filling in its frequency and other attributes
- currentPtNode.update(probabilityInfo, shortcutTargets, null, isNotAWord,
- isBlacklistEntry);
+ currentPtNode.update(probabilityInfo, null, isNotAWord,
+ isPossiblyOffensive);
} else {
// The new word matches the full old word and extends past it.
// We only have to create a new node and add it to the end of this.
final PtNode newNode = new PtNode(
Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length),
- shortcutTargets, null /* bigrams */, probabilityInfo,
- isNotAWord, isBlacklistEntry);
+ null /* bigrams */, probabilityInfo,
+ isNotAWord, isPossiblyOffensive);
currentPtNode.mChildren = new PtNodeArray();
currentPtNode.mChildren.mData.add(newNode);
}
@@ -457,18 +387,18 @@ public final class FusionDictionary implements Iterable<WordProperty> {
if (0 == differentCharIndex) {
// Exact same word. Update the frequency if higher. This will also add the
// new shortcuts to the existing shortcut list if it already exists.
- currentPtNode.update(probabilityInfo, shortcutTargets, null,
+ currentPtNode.update(probabilityInfo, null,
currentPtNode.mIsNotAWord && isNotAWord,
- currentPtNode.mIsBlacklistEntry || isBlacklistEntry);
+ currentPtNode.mIsPossiblyOffensive || isPossiblyOffensive);
} else {
// Partial prefix match only. We have to replace the current node with a node
// containing the current prefix and create two new ones for the tails.
PtNodeArray newChildren = new PtNodeArray();
final PtNode newOldWord = new PtNode(
Arrays.copyOfRange(currentPtNode.mChars, differentCharIndex,
- currentPtNode.mChars.length), currentPtNode.mShortcutTargets,
+ currentPtNode.mChars.length),
currentPtNode.mBigrams, currentPtNode.mProbabilityInfo,
- currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry,
+ currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive,
currentPtNode.mChildren);
newChildren.mData.add(newOldWord);
@@ -476,18 +406,18 @@ public final class FusionDictionary implements Iterable<WordProperty> {
if (charIndex + differentCharIndex >= word.length) {
newParent = new PtNode(
Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
- shortcutTargets, null /* bigrams */, probabilityInfo,
- isNotAWord, isBlacklistEntry, newChildren);
+ null /* bigrams */, probabilityInfo,
+ isNotAWord, isPossiblyOffensive, newChildren);
} else {
newParent = new PtNode(
Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
- null /* shortcutTargets */, null /* bigrams */,
- null /* probabilityInfo */, false /* isNotAWord */,
- false /* isBlacklistEntry */, newChildren);
+ null /* bigrams */, null /* probabilityInfo */,
+ false /* isNotAWord */, false /* isPossiblyOffensive */,
+ newChildren);
final PtNode newWord = new PtNode(Arrays.copyOfRange(word,
charIndex + differentCharIndex, word.length),
- shortcutTargets, null /* bigrams */, probabilityInfo,
- isNotAWord, isBlacklistEntry);
+ null /* bigrams */, probabilityInfo,
+ isNotAWord, isPossiblyOffensive);
final int addIndex = word[charIndex + differentCharIndex]
> currentPtNode.mChars[differentCharIndex] ? 1 : 0;
newChildren.mData.add(addIndex, newWord);
@@ -533,14 +463,14 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* is ignored.
* This comparator imposes orderings that are inconsistent with equals.
*/
- static private final class PtNodeComparator implements java.util.Comparator<PtNode> {
+ static final class PtNodeComparator implements java.util.Comparator<PtNode> {
@Override
public int compare(PtNode p1, PtNode p2) {
if (p1.mChars[0] == p2.mChars[0]) return 0;
return p1.mChars[0] < p2.mChars[0] ? -1 : 1;
}
}
- final static private PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
+ final static PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
/**
* Finds the insertion index of a character within a node array.
@@ -548,8 +478,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
private static int findInsertionIndex(final PtNodeArray nodeArray, int character) {
final ArrayList<PtNode> data = nodeArray.mData;
final PtNode reference = new PtNode(new int[] { character },
- null /* shortcutTargets */, null /* bigrams */, null /* probabilityInfo */,
- false /* isNotAWord */, false /* isBlacklistEntry */);
+ null /* bigrams */, null /* probabilityInfo */,
+ false /* isNotAWord */, false /* isPossiblyOffensive */);
int result = Collections.binarySearch(data, reference, PTNODE_COMPARATOR);
return result >= 0 ? result : -result - 1;
}
@@ -571,7 +501,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
/**
* Helper method to find a word in a given branch.
*/
- public static PtNode findWordInTree(PtNodeArray nodeArray, final String string) {
+ public static PtNode findWordInTree(final PtNodeArray rootNodeArray, final String string) {
+ PtNodeArray nodeArray = rootNodeArray;
int index = 0;
final StringBuilder checker = DBG ? new StringBuilder() : null;
final int[] codePoints = getCodePoints(string);
@@ -684,9 +615,8 @@ public final class FusionDictionary implements Iterable<WordProperty> {
}
if (currentPtNode.isTerminal()) {
return new WordProperty(mCurrentString.toString(),
- currentPtNode.mProbabilityInfo,
- currentPtNode.mShortcutTargets, currentPtNode.mBigrams,
- currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry);
+ currentPtNode.mProbabilityInfo, currentPtNode.mBigrams,
+ currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive);
}
} else {
mPositions.removeLast();
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
deleted file mode 100644
index 65b84d5f7..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * 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.annotations.UsedForTesting;
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * An implementation of DictDecoder for version 2 binary dictionary.
- */
-// TODO: Separate logics that are used only for testing.
-@UsedForTesting
-public class Ver2DictDecoder extends AbstractDictDecoder {
- /**
- * A utility class for reading a PtNode.
- */
- protected static class PtNodeReader {
- private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
- // Ver2 dicts don't contain historical information.
- return new ProbabilityInfo(dictBuffer.readUnsignedByte());
- }
-
- protected static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
- return dictBuffer.readUnsignedByte();
- }
-
- protected static int readChildrenAddress(final DictBuffer dictBuffer,
- final int ptNodeFlags) {
- switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
- case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
- return dictBuffer.readUnsignedByte();
- case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES:
- return dictBuffer.readUnsignedShort();
- case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES:
- return dictBuffer.readUnsignedInt24();
- case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS:
- default:
- return FormatSpec.NO_CHILDREN_ADDRESS;
- }
- }
-
- // Reads shortcuts and returns the read length.
- protected static int readShortcut(final DictBuffer dictBuffer,
- final ArrayList<WeightedString> shortcutTargets) {
- final int pointerBefore = dictBuffer.position();
- dictBuffer.readUnsignedShort(); // skip the size
- while (true) {
- final int targetFlags = dictBuffer.readUnsignedByte();
- final String word = CharEncoding.readString(dictBuffer);
- shortcutTargets.add(new WeightedString(word,
- targetFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY));
- if (0 == (targetFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
- }
- return dictBuffer.position() - pointerBefore;
- }
-
- protected static int readBigramAddresses(final DictBuffer dictBuffer,
- final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
- int readLength = 0;
- int bigramCount = 0;
- while (bigramCount++ < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
- final int bigramFlags = dictBuffer.readUnsignedByte();
- ++readLength;
- final int sign = 0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE)
- ? 1 : -1;
- int bigramAddress = baseAddress + readLength;
- switch (bigramFlags & FormatSpec.MASK_BIGRAM_ATTR_ADDRESS_TYPE) {
- case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE:
- bigramAddress += sign * dictBuffer.readUnsignedByte();
- readLength += 1;
- break;
- case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_TWOBYTES:
- bigramAddress += sign * dictBuffer.readUnsignedShort();
- readLength += 2;
- break;
- case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_THREEBYTES:
- bigramAddress += sign * dictBuffer.readUnsignedInt24();
- readLength += 3;
- break;
- default:
- throw new RuntimeException("Has bigrams with no address");
- }
- bigrams.add(new PendingAttribute(
- bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY,
- bigramAddress));
- if (0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
- }
- return readLength;
- }
- }
-
- protected final File mDictionaryBinaryFile;
- protected final long mOffset;
- protected final long mLength;
- // TODO: Remove mBufferFactory and mDictBuffer from this class members because they are now
- // used only for testing.
- private final DictionaryBufferFactory mBufferFactory;
- protected DictBuffer mDictBuffer;
-
- @UsedForTesting
- /* package */ Ver2DictDecoder(final File file, final long offset, final long length,
- final int factoryFlag) {
- mDictionaryBinaryFile = file;
- mOffset = offset;
- mLength = length;
- mDictBuffer = null;
- if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) {
- mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory();
- } else if ((factoryFlag & MASK_DICTBUFFER) == USE_BYTEARRAY) {
- mBufferFactory = new DictionaryBufferFromByteArrayFactory();
- } else if ((factoryFlag & MASK_DICTBUFFER) == USE_WRITABLE_BYTEBUFFER) {
- mBufferFactory = new DictionaryBufferFromWritableByteBufferFactory();
- } else {
- mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory();
- }
- }
-
- /* package */ Ver2DictDecoder(final File file, final long offset, final long length,
- final DictionaryBufferFactory factory) {
- mDictionaryBinaryFile = file;
- mOffset = offset;
- mLength = length;
- mBufferFactory = factory;
- }
-
- @Override
- public void openDictBuffer() throws FileNotFoundException, IOException {
- mDictBuffer = mBufferFactory.getDictionaryBuffer(mDictionaryBinaryFile);
- }
-
- @Override
- public boolean isDictBufferOpen() {
- return mDictBuffer != null;
- }
-
- /* package */ DictBuffer getDictBuffer() {
- return mDictBuffer;
- }
-
- @UsedForTesting
- /* package */ DictBuffer openAndGetDictBuffer() throws FileNotFoundException, IOException {
- openDictBuffer();
- return getDictBuffer();
- }
-
- @Override
- public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException {
- // dictType is not being used in dicttool. Passing an empty string.
- final BinaryDictionary binaryDictionary = new BinaryDictionary(
- mDictionaryBinaryFile.getAbsolutePath(), mOffset, mLength,
- true /* useFullEditDistance */, null /* locale */, "" /* dictType */,
- false /* isUpdatable */);
- final DictionaryHeader header = binaryDictionary.getHeader();
- binaryDictionary.close();
- if (header == null) {
- throw new IOException("Cannot read the dictionary header.");
- }
- if (header.mFormatOptions.mVersion != FormatSpec.VERSION2) {
- throw new UnsupportedFormatException("File header has a wrong version : "
- + header.mFormatOptions.mVersion);
- }
- if (!isDictBufferOpen()) {
- openDictBuffer();
- }
- // Advance buffer reading position to the head of dictionary body.
- setPosition(header.mBodyOffset);
- return header;
- }
-
- // TODO: Make this buffer multi thread safe.
- private final int[] mCharacterBuffer = new int[FormatSpec.MAX_WORD_LENGTH];
- @Override
- public PtNodeInfo readPtNode(final int ptNodePos) {
- int addressPointer = ptNodePos;
- final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
- addressPointer += FormatSpec.PTNODE_FLAGS_SIZE;
- final int characters[];
- if (0 != (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS)) {
- int index = 0;
- int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
- while (FormatSpec.INVALID_CHARACTER != character) {
- // FusionDictionary is making sure that the length of the word is smaller than
- // MAX_WORD_LENGTH.
- // So we'll never write past the end of mCharacterBuffer.
- mCharacterBuffer[index++] = character;
- character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
- }
- characters = Arrays.copyOfRange(mCharacterBuffer, 0, index);
- } else {
- final int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
- characters = new int[] { character };
- }
- final ProbabilityInfo probabilityInfo;
- if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) {
- probabilityInfo = PtNodeReader.readProbabilityInfo(mDictBuffer);
- addressPointer += FormatSpec.PTNODE_FREQUENCY_SIZE;
- } else {
- probabilityInfo = null;
- }
- int childrenAddress = PtNodeReader.readChildrenAddress(mDictBuffer, flags);
- if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) {
- childrenAddress += addressPointer;
- }
- addressPointer += BinaryDictIOUtils.getChildrenAddressSize(flags);
- final ArrayList<WeightedString> shortcutTargets;
- if (0 != (flags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS)) {
- // readShortcut will add shortcuts to shortcutTargets.
- shortcutTargets = new ArrayList<>();
- addressPointer += PtNodeReader.readShortcut(mDictBuffer, shortcutTargets);
- } else {
- shortcutTargets = null;
- }
-
- final ArrayList<PendingAttribute> bigrams;
- if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) {
- bigrams = new ArrayList<>();
- addressPointer += PtNodeReader.readBigramAddresses(mDictBuffer, bigrams,
- addressPointer);
- if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
- throw new RuntimeException("Too many bigrams in a PtNode (" + bigrams.size()
- + " but max is " + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")");
- }
- } else {
- bigrams = null;
- }
- return new PtNodeInfo(ptNodePos, addressPointer, flags, characters, probabilityInfo,
- childrenAddress, shortcutTargets, bigrams);
- }
-
- @Override
- public FusionDictionary readDictionaryBinary(final boolean deleteDictIfBroken)
- throws FileNotFoundException, IOException, UnsupportedFormatException {
- // dictType is not being used in dicttool. Passing an empty string.
- final BinaryDictionary binaryDictionary = new BinaryDictionary(
- mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */,
- mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */,
- null /* locale */, "" /* dictType */, false /* isUpdatable */);
- final DictionaryHeader header = readHeader();
- final FusionDictionary fusionDict =
- new FusionDictionary(new FusionDictionary.PtNodeArray(), header.mDictionaryOptions);
- int token = 0;
- final ArrayList<WordProperty> wordProperties = new ArrayList<>();
- do {
- final BinaryDictionary.GetNextWordPropertyResult result =
- binaryDictionary.getNextWordProperty(token);
- final WordProperty wordProperty = result.mWordProperty;
- if (wordProperty == null) {
- binaryDictionary.close();
- if (deleteDictIfBroken) {
- mDictionaryBinaryFile.delete();
- }
- return null;
- }
- wordProperties.add(wordProperty);
- token = result.mNextToken;
- } while (token != 0);
-
- // Insert unigrams into the fusion dictionary.
- for (final WordProperty wordProperty : wordProperties) {
- if (wordProperty.mIsBlacklistEntry) {
- fusionDict.addBlacklistEntry(wordProperty.mWord, wordProperty.mShortcutTargets,
- wordProperty.mIsNotAWord);
- } else {
- fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
- wordProperty.mShortcutTargets, wordProperty.mIsNotAWord);
- }
- }
- // Insert bigrams into the fusion dictionary.
- for (final WordProperty wordProperty : wordProperties) {
- if (wordProperty.mBigrams == null) {
- continue;
- }
- final String word0 = wordProperty.mWord;
- for (final WeightedString bigram : wordProperty.mBigrams) {
- fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
- }
- }
- binaryDictionary.close();
- return fusionDict;
- }
-
- @Override
- public void setPosition(int newPos) {
- mDictBuffer.position(newPos);
- }
-
- @Override
- public int getPosition() {
- return mDictBuffer.position();
- }
-
- @Override
- public int readPtNodeCount() {
- return BinaryDictDecoderUtils.readPtNodeCount(mDictBuffer);
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java
deleted file mode 100644
index 3882c2c55..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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 Ver2DictDecoder
- */
-public class Ver2DictDecoderTests extends AndroidTestCase {
- private static final String TAG = Ver2DictDecoderTests.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);
- }
- }
- }
- }
-
- 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 Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(),
- 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());
- }
-
- 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 Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(),
- 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/makedict/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
deleted file mode 100644
index a286190cb..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * 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.annotations.UsedForTesting;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * An implementation of DictEncoder for version 2 binary dictionary.
- */
-@UsedForTesting
-public class Ver2DictEncoder implements DictEncoder {
-
- private final File mDictFile;
- private OutputStream mOutStream;
- private byte[] mBuffer;
- private int mPosition;
-
- @UsedForTesting
- public Ver2DictEncoder(final File dictFile) {
- mDictFile = dictFile;
- mOutStream = null;
- mBuffer = null;
- }
-
- // This constructor is used only by BinaryDictOffdeviceUtilsTests.
- // If you want to use this in the production code, you should consider keeping consistency of
- // the interface of Ver3DictDecoder by using factory.
- @UsedForTesting
- public Ver2DictEncoder(final OutputStream outStream) {
- mDictFile = null;
- mOutStream = outStream;
- }
-
- private void openStream() throws FileNotFoundException {
- mOutStream = new FileOutputStream(mDictFile);
- }
-
- private void close() throws IOException {
- if (mOutStream != null) {
- mOutStream.close();
- mOutStream = null;
- }
- }
-
- @Override
- public void writeDictionary(final FusionDictionary dict, final FormatOptions formatOptions)
- throws IOException, UnsupportedFormatException {
- if (formatOptions.mVersion > FormatSpec.VERSION2) {
- throw new UnsupportedFormatException(
- "The given format options has wrong version number : "
- + formatOptions.mVersion);
- }
-
- if (mOutStream == null) {
- openStream();
- }
- BinaryDictEncoderUtils.writeDictionaryHeader(mOutStream, dict, formatOptions);
-
- // Addresses are limited to 3 bytes, but since addresses can be relative to each node
- // array, the structure itself is not limited to 16MB. However, if it is over 16MB deciding
- // the order of the PtNode arrays becomes a quite complicated problem, because though the
- // dictionary itself does not have a size limit, each node array must still be within 16MB
- // of all its children and parents. As long as this is ensured, the dictionary file may
- // grow to any size.
-
- // Leave the choice of the optimal node order to the flattenTree function.
- MakedictLog.i("Flattening the tree...");
- ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
-
- MakedictLog.i("Computing addresses...");
- BinaryDictEncoderUtils.computeAddresses(dict, flatNodes);
- MakedictLog.i("Checking PtNode array...");
- if (MakedictLog.DBG) BinaryDictEncoderUtils.checkFlatPtNodeArrayList(flatNodes);
-
- // Create a buffer that matches the final dictionary size.
- final PtNodeArray lastNodeArray = flatNodes.get(flatNodes.size() - 1);
- final int bufferSize = lastNodeArray.mCachedAddressAfterUpdate + lastNodeArray.mCachedSize;
- mBuffer = new byte[bufferSize];
-
- MakedictLog.i("Writing file...");
-
- for (PtNodeArray nodeArray : flatNodes) {
- BinaryDictEncoderUtils.writePlacedPtNodeArray(dict, this, nodeArray);
- }
- if (MakedictLog.DBG) BinaryDictEncoderUtils.showStatistics(flatNodes);
- mOutStream.write(mBuffer, 0, mPosition);
-
- MakedictLog.i("Done");
- close();
- }
-
- @Override
- public void setPosition(final int position) {
- if (mBuffer == null || position < 0 || position >= mBuffer.length) return;
- mPosition = position;
- }
-
- @Override
- public int getPosition() {
- return mPosition;
- }
-
- @Override
- public void writePtNodeCount(final int ptNodeCount) {
- final int countSize = BinaryDictIOUtils.getPtNodeCountSize(ptNodeCount);
- if (countSize != 1 && countSize != 2) {
- throw new RuntimeException("Strange size from getGroupCountSize : " + countSize);
- }
- final int encodedPtNodeCount = (countSize == 2) ?
- (ptNodeCount | FormatSpec.LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG) : ptNodeCount;
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, encodedPtNodeCount,
- countSize);
- }
-
- private void writePtNodeFlags(final PtNode ptNode) {
- final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition,
- BinaryDictEncoderUtils.makePtNodeFlags(ptNode, childrenPos),
- FormatSpec.PTNODE_FLAGS_SIZE);
- }
-
- private void writeCharacters(final int[] codePoints, final boolean hasSeveralChars) {
- mPosition = CharEncoding.writeCharArray(codePoints, mBuffer, mPosition);
- if (hasSeveralChars) {
- mBuffer[mPosition++] = FormatSpec.PTNODE_CHARACTERS_TERMINATOR;
- }
- }
-
- private void writeFrequency(final int frequency) {
- if (frequency >= 0) {
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, frequency,
- FormatSpec.PTNODE_FREQUENCY_SIZE);
- }
- }
-
- private void writeChildrenPosition(final PtNode ptNode) {
- final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
- mPosition += BinaryDictEncoderUtils.writeChildrenPosition(mBuffer, mPosition,
- childrenPos);
- }
-
- /**
- * Write a shortcut attributes list to mBuffer.
- *
- * @param shortcuts the shortcut attributes list.
- */
- private void writeShortcuts(final ArrayList<WeightedString> shortcuts) {
- if (null == shortcuts || shortcuts.isEmpty()) return;
-
- final int indexOfShortcutByteSize = mPosition;
- mPosition += FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
- final Iterator<WeightedString> shortcutIterator = shortcuts.iterator();
- while (shortcutIterator.hasNext()) {
- final WeightedString target = shortcutIterator.next();
- final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags(
- shortcutIterator.hasNext(),
- target.getProbability());
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, shortcutFlags,
- FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
- final int shortcutShift = CharEncoding.writeString(mBuffer, mPosition, target.mWord);
- mPosition += shortcutShift;
- }
- final int shortcutByteSize = mPosition - indexOfShortcutByteSize;
- if (shortcutByteSize > FormatSpec.MAX_SHORTCUT_LIST_SIZE_IN_A_PTNODE) {
- throw new RuntimeException("Shortcut list too large");
- }
- BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, indexOfShortcutByteSize, shortcutByteSize,
- FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE);
- }
-
- /**
- * Write a bigram attributes list to mBuffer.
- *
- * @param bigrams the bigram attributes list.
- * @param dict the dictionary the node array is a part of (for relative offsets).
- */
- private void writeBigrams(final ArrayList<WeightedString> bigrams,
- final FusionDictionary dict) {
- if (bigrams == null) return;
-
- final Iterator<WeightedString> bigramIterator = bigrams.iterator();
- while (bigramIterator.hasNext()) {
- final WeightedString bigram = bigramIterator.next();
- final PtNode target =
- FusionDictionary.findWordInTree(dict.mRootNodeArray, bigram.mWord);
- final int addressOfBigram = target.mCachedAddressAfterUpdate;
- final int unigramFrequencyForThisWord = target.getProbability();
- final int offset = addressOfBigram
- - (mPosition + FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
- final int bigramFlags = BinaryDictEncoderUtils.makeBigramFlags(bigramIterator.hasNext(),
- offset, bigram.getProbability(), unigramFrequencyForThisWord, bigram.mWord);
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, bigramFlags,
- FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
- mPosition += BinaryDictEncoderUtils.writeChildrenPosition(mBuffer, mPosition,
- Math.abs(offset));
- }
- }
-
- @Override
- public void writeForwardLinkAddress(final int forwardLinkAddress) {
- mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, forwardLinkAddress,
- FormatSpec.FORWARD_LINK_ADDRESS_SIZE);
- }
-
- @Override
- public void writePtNode(final PtNode ptNode, final FusionDictionary dict) {
- writePtNodeFlags(ptNode);
- writeCharacters(ptNode.mChars, ptNode.hasSeveralChars());
- writeFrequency(ptNode.getProbability());
- writeChildrenPosition(ptNode);
- writeShortcuts(ptNode.mShortcutTargets);
- writeBigrams(ptNode.mBigrams, dict);
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 5e8417ed6..746431dfa 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -18,7 +18,7 @@ package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
import java.io.File;
import java.io.FileNotFoundException;
@@ -33,12 +33,7 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
final File mDictDirectory;
@UsedForTesting
- /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) {
- this(dictDirectory, null /* factory */);
- }
-
- @UsedForTesting
- /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) {
+ /* package */ Ver4DictDecoder(final File dictDirectory) {
mDictDirectory = dictDirectory;
}
@@ -88,21 +83,18 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
// Insert unigrams into the fusion dictionary.
for (final WordProperty wordProperty : wordProperties) {
- if (wordProperty.mIsBlacklistEntry) {
- fusionDict.addBlacklistEntry(wordProperty.mWord, wordProperty.mShortcutTargets,
- wordProperty.mIsNotAWord);
- } else {
- fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
- wordProperty.mShortcutTargets, wordProperty.mIsNotAWord);
- }
+ fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
+ wordProperty.mIsNotAWord,
+ wordProperty.mIsPossiblyOffensive);
}
// Insert bigrams into the fusion dictionary.
+ // TODO: Support ngrams.
for (final WordProperty wordProperty : wordProperties) {
- if (wordProperty.mBigrams == null) {
+ if (!wordProperty.mHasNgrams) {
continue;
}
final String word0 = wordProperty.mWord;
- for (final WeightedString bigram : wordProperty.mBigrams) {
+ for (final WeightedString bigram : wordProperty.getBigrams()) {
fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
deleted file mode 100644
index 76eaef431..000000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.annotations.UsedForTesting;
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * An implementation of DictEncoder for version 4 binary dictionary.
- */
-@UsedForTesting
-public class Ver4DictEncoder implements DictEncoder {
- private final File mDictPlacedDir;
-
- @UsedForTesting
- public Ver4DictEncoder(final File dictPlacedDir) {
- mDictPlacedDir = dictPlacedDir;
- }
-
- // TODO: This builds a FusionDictionary first and iterates it to add words to the binary
- // dictionary. However, it is possible to just add words directly to the binary dictionary
- // instead.
- // In the long run, when we stop supporting version 2, FusionDictionary will become deprecated
- // and we can remove it. Then we'll be able to just call BinaryDictionary directly.
- @Override
- public void writeDictionary(FusionDictionary dict, FormatOptions formatOptions)
- throws IOException, UnsupportedFormatException {
- if (formatOptions.mVersion != FormatSpec.VERSION4) {
- throw new UnsupportedFormatException("File header has a wrong version number : "
- + formatOptions.mVersion);
- }
- if (!mDictPlacedDir.isDirectory()) {
- throw new UnsupportedFormatException("Given path is not a directory.");
- }
- if (!BinaryDictionaryUtils.createEmptyDictFile(mDictPlacedDir.getAbsolutePath(),
- FormatSpec.VERSION4, LocaleUtils.constructLocaleFromString(
- dict.mOptions.mAttributes.get(DictionaryHeader.DICTIONARY_LOCALE_KEY)),
- dict.mOptions.mAttributes)) {
- throw new IOException("Cannot create dictionary file : "
- + mDictPlacedDir.getAbsolutePath());
- }
- final BinaryDictionary binaryDict = new BinaryDictionary(mDictPlacedDir.getAbsolutePath(),
- 0l, mDictPlacedDir.length(), true /* useFullEditDistance */,
- LocaleUtils.constructLocaleFromString(dict.mOptions.mAttributes.get(
- DictionaryHeader.DICTIONARY_LOCALE_KEY)),
- Dictionary.TYPE_USER /* Dictionary type. Does not matter for us */,
- true /* isUpdatable */);
- if (!binaryDict.isValidDictionary()) {
- // Somehow createEmptyDictFile returned true, but the file was not created correctly
- throw new IOException("Cannot create dictionary file");
- }
- for (final WordProperty wordProperty : dict) {
- // TODO: switch to addMultipleDictionaryEntries when they support shortcuts
- if (null == wordProperty.mShortcutTargets || wordProperty.mShortcutTargets.isEmpty()) {
- if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
- null /* shortcutTarget */, 0 /* shortcutProbability */,
- wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
- wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
- MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
- }
- } else {
- for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
- if (!binaryDict.addUnigramEntry(wordProperty.mWord,
- wordProperty.getProbability(),
- shortcutTarget.mWord, shortcutTarget.getProbability(),
- wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
- wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
- MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord
- + ", shortcutTarget: " + shortcutTarget.mWord);
- return;
- }
- }
- }
- if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
- if (!binaryDict.flushWithGC()) {
- MakedictLog.e("Cannot flush dict with GC.");
- return;
- }
- }
- }
- for (final WordProperty word0Property : dict) {
- if (null == word0Property.mBigrams) continue;
- for (final WeightedString word1 : word0Property.mBigrams) {
- final PrevWordsInfo prevWordsInfo =
- new PrevWordsInfo(new PrevWordsInfo.WordInfo(word0Property.mWord));
- if (!binaryDict.addNgramEntry(prevWordsInfo, word1.mWord,
- word1.getProbability(), 0 /* timestamp */)) {
- MakedictLog.e("Cannot add n-gram entry for "
- + prevWordsInfo + " -> " + word1.mWord);
- return;
- }
- if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
- if (!binaryDict.flushWithGC()) {
- MakedictLog.e("Cannot flush dict with GC.");
- return;
- }
- }
- }
- }
- if (!binaryDict.flushWithGC()) {
- MakedictLog.e("Cannot flush dict with GC.");
- return;
- }
- binaryDict.close();
- }
-
- @Override
- public void setPosition(int position) {
- }
-
- @Override
- public int getPosition() {
- return 0;
- }
-
- @Override
- public void writePtNodeCount(int ptNodeCount) {
- }
-
- @Override
- public void writeForwardLinkAddress(int forwardLinkAddress) {
- }
-
- @Override
- public void writePtNode(PtNode ptNode, FusionDictionary dict) {
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
new file mode 100644
index 000000000..8f24cdb44
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.network.BlockingHttpClient.ResponseProcessor;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Tests for {@link BlockingHttpClient}.
+ */
+@SmallTest
+public class BlockingHttpClientTests extends AndroidTestCase {
+ @Mock HttpURLConnection mMockHttpConnection;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void testError_badGateway() throws IOException, AuthException {
+ when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_BAD_GATEWAY);
+ final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+ final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+ try {
+ client.execute(null /* empty request */, processor);
+ fail("Expecting an HttpException");
+ } catch (HttpException e) {
+ // expected HttpException
+ assertEquals(HttpURLConnection.HTTP_BAD_GATEWAY, e.getHttpStatusCode());
+ }
+ }
+
+ public void testError_clientTimeout() throws Exception {
+ when(mMockHttpConnection.getResponseCode()).thenReturn(
+ HttpURLConnection.HTTP_CLIENT_TIMEOUT);
+ final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+ final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+ try {
+ client.execute(null /* empty request */, processor);
+ fail("Expecting an HttpException");
+ } catch (HttpException e) {
+ // expected HttpException
+ assertEquals(HttpURLConnection.HTTP_CLIENT_TIMEOUT, e.getHttpStatusCode());
+ }
+ }
+
+ public void testError_forbiddenWithRequest() throws Exception {
+ final OutputStream mockOutputStream = Mockito.mock(OutputStream.class);
+ when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
+ when(mMockHttpConnection.getOutputStream()).thenReturn(mockOutputStream);
+ final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+ final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+ try {
+ client.execute(new byte[100], processor);
+ fail("Expecting an HttpException");
+ } catch (HttpException e) {
+ assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getHttpStatusCode());
+ }
+ verify(mockOutputStream).write(any(byte[].class), eq(0), eq(100));
+ }
+
+ public void testSuccess_emptyRequest() throws Exception {
+ final Random rand = new Random();
+ byte[] response = new byte[100];
+ rand.nextBytes(response);
+ when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mMockHttpConnection.getInputStream()).thenReturn(new ByteArrayInputStream(response));
+ final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+ final FakeSuccessResponseProcessor processor =
+ new FakeSuccessResponseProcessor(response);
+
+ client.execute(null /* empty request */, processor);
+ assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
+ }
+
+ public void testSuccess() throws Exception {
+ final OutputStream mockOutputStream = Mockito.mock(OutputStream.class);
+ final Random rand = new Random();
+ byte[] response = new byte[100];
+ rand.nextBytes(response);
+ when(mMockHttpConnection.getOutputStream()).thenReturn(mockOutputStream);
+ when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mMockHttpConnection.getInputStream()).thenReturn(new ByteArrayInputStream(response));
+ final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+ final FakeSuccessResponseProcessor processor =
+ new FakeSuccessResponseProcessor(response);
+
+ client.execute(new byte[100], processor);
+ assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
+ }
+
+ static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
+ @Override
+ public Void onSuccess(InputStream response) {
+ fail("Expected an error but received success");
+ return null;
+ }
+ }
+
+ private static class FakeSuccessResponseProcessor implements ResponseProcessor<Void> {
+ private final byte[] mExpectedResponse;
+
+ boolean mInvoked;
+
+ FakeSuccessResponseProcessor(byte[] expectedResponse) {
+ mExpectedResponse = expectedResponse;
+ }
+
+ @Override
+ public Void onSuccess(InputStream response) {
+ try {
+ mInvoked = true;
+ BufferedInputStream in = new BufferedInputStream(response);
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int read = 0;
+ while ((read = in.read()) != -1) {
+ buffer.write(read);
+ }
+ byte[] actualResponse = buffer.toByteArray();
+ in.close();
+ assertTrue("Response doesn't match",
+ Arrays.equals(mExpectedResponse, actualResponse));
+ } catch (IOException ex) {
+ fail("IOException in onSuccess");
+ }
+ return null;
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java b/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java
new file mode 100644
index 000000000..5b3e78eaf
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_BI_DIRECTIONAL;
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_DOWNLOAD_ONLY;
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_UPLOAD_ONLY;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+
+
+/**
+ * Tests for {@link HttpUrlConnectionBuilder}.
+ */
+@SmallTest
+public class HttpUrlConnectionBuilderTests extends AndroidTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testSetUrl_malformed() {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ try {
+ builder.setUrl("dadasd!@%@!:11");
+ fail("Expected a MalformedURLException.");
+ } catch (MalformedURLException e) {
+ // Expected
+ }
+ }
+
+ public void testSetConnectTimeout_invalid() {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ try {
+ builder.setConnectTimeout(-1);
+ fail("Expected an IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testSetConnectTimeout() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("https://www.example.com");
+ builder.setConnectTimeout(8765);
+ HttpURLConnection connection = builder.build();
+ assertEquals(8765, connection.getConnectTimeout());
+ }
+
+ public void testSetReadTimeout_invalid() {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ try {
+ builder.setReadTimeout(-1);
+ fail("Expected an IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testSetReadTimeout() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("https://www.example.com");
+ builder.setReadTimeout(8765);
+ HttpURLConnection connection = builder.build();
+ assertEquals(8765, connection.getReadTimeout());
+ }
+
+ public void testAddHeader() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("http://www.example.com");
+ builder.addHeader("some-random-key", "some-random-value");
+ HttpURLConnection connection = builder.build();
+ assertEquals("some-random-value", connection.getRequestProperty("some-random-key"));
+ }
+
+ public void testSetUseCache_notSet() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("http://www.example.com");
+ HttpURLConnection connection = builder.build();
+ assertFalse(connection.getUseCaches());
+ }
+
+ public void testSetUseCache_false() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("http://www.example.com");
+ HttpURLConnection connection = builder.build();
+ connection.setUseCaches(false);
+ assertFalse(connection.getUseCaches());
+ }
+
+ public void testSetUseCache_true() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("http://www.example.com");
+ HttpURLConnection connection = builder.build();
+ connection.setUseCaches(true);
+ assertTrue(connection.getUseCaches());
+ }
+
+ public void testSetMode_uploadOnly() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("http://www.example.com");
+ builder.setMode(MODE_UPLOAD_ONLY);
+ HttpURLConnection connection = builder.build();
+ assertTrue(connection.getDoInput());
+ assertFalse(connection.getDoOutput());
+ }
+
+ public void testSetMode_downloadOnly() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("https://www.example.com");
+ builder.setMode(MODE_DOWNLOAD_ONLY);
+ HttpURLConnection connection = builder.build();
+ assertFalse(connection.getDoInput());
+ assertTrue(connection.getDoOutput());
+ }
+
+ public void testSetMode_bidirectional() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("https://www.example.com");
+ builder.setMode(MODE_BI_DIRECTIONAL);
+ HttpURLConnection connection = builder.build();
+ assertTrue(connection.getDoInput());
+ assertTrue(connection.getDoOutput());
+ }
+
+ public void testSetAuthToken() throws IOException {
+ HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+ builder.setUrl("https://www.example.com");
+ builder.setAuthToken("some-random-auth-token");
+ HttpURLConnection connection = builder.build();
+ assertEquals("some-random-auth-token",
+ connection.getRequestProperty(HttpUrlConnectionBuilder.HTTP_HEADER_AUTHORIZATION));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
deleted file mode 100644
index 565fadb2a..000000000
--- a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-/**
- * Unit tests for contextual dictionary
- */
-@LargeTest
-public class ContextualDictionaryTests extends AndroidTestCase {
- private static final String TAG = ContextualDictionaryTests.class.getSimpleName();
-
- private static final Locale LOCALE_EN_US = new Locale("en", "US");
-
- private DictionaryFacilitator getDictionaryFacilitator() {
- final ArrayList<String> dictTypes = new ArrayList<>();
- dictTypes.add(Dictionary.TYPE_CONTEXTUAL);
- final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
- dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
- new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
- return dictionaryFacilitator;
- }
-
- public void testAddPhrase() {
- final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
- final String[] phrase = new String[] {"a", "b", "c", "d"};
- final int probability = 100;
- final int bigramProbabilityForWords = 150;
- final int bigramProbabilityForPhrases = 200;
- dictionaryFacilitator.addPhraseToContextualDictionary(
- phrase, probability, bigramProbabilityForWords, bigramProbabilityForPhrases);
- final ExpandableBinaryDictionary contextualDictionary =
- dictionaryFacilitator.getSubDictForTesting(Dictionary.TYPE_CONTEXTUAL);
- contextualDictionary.waitAllTasksForTests();
- // Word
- assertTrue(contextualDictionary.isInDictionary("a"));
- assertTrue(contextualDictionary.isInDictionary("b"));
- assertTrue(contextualDictionary.isInDictionary("c"));
- assertTrue(contextualDictionary.isInDictionary("d"));
- // Phrase
- assertTrue(contextualDictionary.isInDictionary("a b c d"));
- assertTrue(contextualDictionary.isInDictionary("b c d"));
- assertTrue(contextualDictionary.isInDictionary("c d"));
- assertFalse(contextualDictionary.isInDictionary("a b c"));
- assertFalse(contextualDictionary.isInDictionary("abcd"));
- // TODO: Add tests for probability.
- // TODO: Add tests for n-grams.
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
deleted file mode 100644
index 0f2f9814b..000000000
--- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-/**
- * Unit tests for personalization dictionary
- */
-@LargeTest
-public class PersonalizationDictionaryTests extends AndroidTestCase {
- private static final String TAG = PersonalizationDictionaryTests.class.getSimpleName();
-
- private static final Locale LOCALE_EN_US = new Locale("en", "US");
- private static final String DUMMY_PACKAGE_NAME = "test.package.name";
- private static final long TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS = 120;
-
- private DictionaryFacilitator getDictionaryFacilitator() {
- final ArrayList<String> dictTypes = new ArrayList<>();
- dictTypes.add(Dictionary.TYPE_MAIN);
- dictTypes.add(Dictionary.TYPE_PERSONALIZATION);
- final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
- dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
- new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
- return dictionaryFacilitator;
- }
-
- public void testAddManyTokens() {
- final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
- dictionaryFacilitator.clearPersonalizationDictionary();
- final int dataChunkCount = 20;
- final int wordCountInOneChunk = 2000;
- final Random random = new Random(System.currentTimeMillis());
- final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
-
- final SpacingAndPunctuations spacingAndPunctuations =
- new SpacingAndPunctuations(getContext().getResources());
-
- final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
- System.currentTimeMillis());
-
- for (int i = 0; i < dataChunkCount; i++) {
- final ArrayList<String> tokens = new ArrayList<>();
- for (int j = 0; j < wordCountInOneChunk; j++) {
- tokens.add(CodePointUtils.generateWord(random, codePointSet));
- }
- final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk(
- true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME);
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- final AddMultipleDictionaryEntriesCallback callback =
- new AddMultipleDictionaryEntriesCallback() {
- @Override
- public void onFinished() {
- countDownLatch.countDown();
- }
- };
- dictionaryFacilitator.addEntriesToPersonalizationDictionary(personalizationDataChunk,
- spacingAndPunctuations, callback);
- try {
- countDownLatch.await(TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS,
- TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
- }
- }
- dictionaryFacilitator.flushPersonalizationDictionary();
- try {
- dictionaryFacilitator.waitForLoadingDictionariesForTesting(
- TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
- }
- final String dictName = ExpandableBinaryDictionary.getDictName(
- PersonalizationDictionary.NAME, LOCALE_EN_US, null /* dictFile */);
- final File dictFile = ExpandableBinaryDictionary.getDictFile(
- getContext(), dictName, null /* dictFile */);
-
- final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
- 0 /* offset */, 0 /* size */,
- true /* useFullEditDistance */, LOCALE_EN_US, Dictionary.TYPE_PERSONALIZATION,
- true /* isUpdatable */);
- assertTrue(binaryDictionary.isValidDictionary());
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index f87f3b494..559f28642 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -21,19 +21,11 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.DistracterFilter;
-import com.android.inputmethod.latin.utils.FileUtils;
import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
import java.util.Locale;
import java.util.Random;
-import java.util.concurrent.TimeUnit;
/**
* Unit tests for UserHistoryDictionary
@@ -41,22 +33,47 @@ import java.util.concurrent.TimeUnit;
@LargeTest
public class UserHistoryDictionaryTests extends AndroidTestCase {
private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
-
- 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 WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000;
+ private static final String TEST_ACCOUNT = "account@example.com";
private int mCurrentTime = 0;
+ private static void printAllFiles(final File dir) {
+ Log.d(TAG, dir.getAbsolutePath());
+ for (final File file : dir.listFiles()) {
+ Log.d(TAG, " " + file.getName());
+ }
+ }
+
+ private static void assertDictionaryExists(final UserHistoryDictionary dict,
+ final File dictFile) {
+ Log.d(TAG, "waiting for writing ...");
+ dict.waitAllTasksForTests();
+ if (!dictFile.exists()) {
+ try {
+ Log.d(TAG, dictFile + " is not existing. Wait "
+ + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing.");
+ printAllFiles(dictFile.getParentFile());
+ Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS);
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "Interrupted during waiting for writing the dict file.");
+ }
+ }
+ assertTrue("Following dictionary file doesn't exist: " + dictFile, dictFile.exists());
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
resetCurrentTimeForTestMode();
+ UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
+ UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
}
@Override
protected void tearDown() throws Exception {
+ UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
+ UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
stopTestModeInNativeCode();
super.tearDown();
}
@@ -66,20 +83,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
setCurrentTimeForTestMode(mCurrentTime);
}
- private void forcePassingShortTime() {
- // 3 days.
- final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(3);
- mCurrentTime += timeToElapse;
- setCurrentTimeForTestMode(mCurrentTime);
- }
-
- private void forcePassingLongTime() {
- // 365 days.
- final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(365);
- mCurrentTime += timeToElapse;
- setCurrentTimeForTestMode(mCurrentTime);
- }
-
private static int setCurrentTimeForTestMode(final int currentTime) {
return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime);
}
@@ -89,199 +92,122 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
}
/**
- * Generates a random word.
- */
- private static 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 static List<String> generateWords(final int number, final Random random) {
- final HashSet<String> wordSet = new HashSet<>();
- while (wordSet.size() < number) {
- wordSet.add(generateWord(random.nextInt()));
- }
- return new ArrayList<>(wordSet);
- }
-
- private static void addToDict(final UserHistoryDictionary dict, final List<String> words) {
- PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
- for (String word : words) {
- UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true,
- (int)TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()),
- DistracterFilter.EMPTY_DISTRACTER_FILTER);
- prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
- }
- }
-
- /**
- * @param checkContents if true, checks whether written words are actually in the dictionary
- * or not.
- */
- private void addAndWriteRandomWords(final Locale locale, final int numberOfWords,
- final Random random, final boolean checkContents) {
- final List<String> words = generateWords(numberOfWords, random);
- final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
- mContext, locale);
- // Add random words to the user history dictionary.
- addToDict(dict, words);
- if (checkContents) {
- dict.waitAllTasksForTests();
- for (int i = 0; i < numberOfWords; ++i) {
- final String word = words.get(i);
- assertTrue(dict.isInDictionary(word));
- }
- }
- // write to file.
- dict.close();
- }
-
- /**
* Clear all entries in the user history dictionary.
- * @param locale dummy locale for testing.
+ * @param dict the user history dictionary.
*/
- private void clearHistory(final Locale locale) {
- final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
- mContext, locale);
+ private static void clearHistory(final UserHistoryDictionary dict) {
dict.waitAllTasksForTests();
dict.clear();
dict.close();
dict.waitAllTasksForTests();
}
- /**
- * Shut down executer and wait until all operations of user history are done.
- * @param locale dummy locale for testing.
- */
- private void waitForWriting(final Locale locale) {
- final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
- mContext, locale);
- dict.waitAllTasksForTests();
- }
-
- public void testRandomWords() {
+ private void doTestRandomWords(final String testAccount) {
Log.d(TAG, "This test can be used for profiling.");
Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
- final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
- final String dictName = ExpandableBinaryDictionary.getDictName(
- UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+ final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("random_words");
+ final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+ UserHistoryDictionary.NAME, dummyLocale,
+ null /* dictFile */,
+ testAccount /* account */);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
+ final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+ getContext(), dummyLocale, testAccount);
+ clearHistory(dict);
final int numberOfWords = 1000;
final Random random = new Random(123456);
+ assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(
+ dict, numberOfWords, random, true /* checksContents */, mCurrentTime));
+ assertDictionaryExists(dict, dictFile);
+ }
- try {
- clearHistory(dummyLocale);
- addAndWriteRandomWords(dummyLocale, numberOfWords, random,
- true /* checksContents */);
- } finally {
- Log.d(TAG, "waiting for writing ...");
- waitForWriting(dummyLocale);
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
- }
+ public void testRandomWords_NullAccount() {
+ doTestRandomWords(null /* testAccount */);
+ }
+
+ public void testRandomWords() {
+ doTestRandomWords(TEST_ACCOUNT);
}
public void testStressTestForSwitchingLanguagesAndAddingWords() {
+ doTestStressTestForSwitchingLanguagesAndAddingWords(TEST_ACCOUNT);
+ }
+
+ public void testStressTestForSwitchingLanguagesAndAddingWords_NullAccount() {
+ doTestStressTestForSwitchingLanguagesAndAddingWords(null /* testAccount */);
+ }
+
+ private void doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount) {
final int numberOfLanguages = 2;
final int numberOfLanguageSwitching = 80;
final int numberOfWordsInsertedForEachLanguageSwitch = 100;
final File dictFiles[] = new File[numberOfLanguages];
- final Locale dummyLocales[] = new Locale[numberOfLanguages];
+ final UserHistoryDictionary dicts[] = new UserHistoryDictionary[numberOfLanguages];
+
try {
final Random random = new Random(123456);
// Create filename suffixes for this test.
for (int i = 0; i < numberOfLanguages; i++) {
- dummyLocales[i] = new Locale("test_switching_languages" + i);
- final String dictName = ExpandableBinaryDictionary.getDictName(
- UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */);
+ final Locale dummyLocale =
+ UserHistoryDictionaryTestsHelper.getDummyLocale("switching_languages" + i);
+ final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+ UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */,
+ testAccount /* account */);
dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
- clearHistory(dummyLocales[i]);
+ dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(),
+ dummyLocale, testAccount);
+ clearHistory(dicts[i]);
}
final long start = System.currentTimeMillis();
for (int i = 0; i < numberOfLanguageSwitching; i++) {
final int index = i % numberOfLanguages;
- // Switch languages to testFilenameSuffixes[index].
- addAndWriteRandomWords(dummyLocales[index],
- numberOfWordsInsertedForEachLanguageSwitch, random,
- false /* checksContents */);
+ // Switch to dicts[index].
+ assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dicts[index],
+ numberOfWordsInsertedForEachLanguageSwitch,
+ random,
+ false /* checksContents */,
+ mCurrentTime));
}
final long end = System.currentTimeMillis();
Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
+ (end - start) + " ms");
} finally {
- Log.d(TAG, "waiting for writing ...");
for (int i = 0; i < numberOfLanguages; i++) {
- waitForWriting(dummyLocales[i]);
- }
- for (final File dictFile : dictFiles) {
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
+ assertDictionaryExists(dicts[i], dictFiles[i]);
}
}
}
public void testAddManyWords() {
- final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
- final String dictName = ExpandableBinaryDictionary.getDictName(
- UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+ doTestAddManyWords(TEST_ACCOUNT);
+ }
+
+ public void testAddManyWords_NullAccount() {
+ doTestAddManyWords(null /* testAccount */);
+ }
+
+ private void doTestAddManyWords(final String testAccount) {
+ final Locale dummyLocale =
+ UserHistoryDictionaryTestsHelper.getDummyLocale("many_random_words");
+ final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+ UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, testAccount);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
final int numberOfWords = 10000;
final Random random = new Random(123456);
- clearHistory(dummyLocale);
- try {
- addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */);
- } finally {
- Log.d(TAG, "waiting for writing ...");
- waitForWriting(dummyLocale);
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
- }
- }
-
- public void testDecaying() {
- final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis());
- final int numberOfWords = 5000;
- final Random random = new Random(123456);
- resetCurrentTimeForTestMode();
- clearHistory(dummyLocale);
- final List<String> words = generateWords(numberOfWords, random);
- final UserHistoryDictionary dict =
- PersonalizationHelper.getUserHistoryDictionary(getContext(), dummyLocale);
- dict.waitAllTasksForTests();
- PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
- for (final String word : words) {
- UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true, mCurrentTime,
- DistracterFilter.EMPTY_DISTRACTER_FILTER);
- prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
- dict.waitAllTasksForTests();
- assertTrue(dict.isInDictionary(word));
- }
- forcePassingShortTime();
- dict.runGCIfRequired();
- dict.waitAllTasksForTests();
- for (final String word : words) {
- assertTrue(dict.isInDictionary(word));
- }
- forcePassingLongTime();
- dict.runGCIfRequired();
- dict.waitAllTasksForTests();
- for (final String word : words) {
- assertFalse(dict.isInDictionary(word));
- }
+ final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+ getContext(), dummyLocale, testAccount);
+ clearHistory(dict);
+ assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict,
+ numberOfWords, random, true /* checksContents */, mCurrentTime));
+ assertDictionaryExists(dict, dictFile);
}
-}
+} \ No newline at end of file
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java
new file mode 100644
index 000000000..4b7b9bc36
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 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.Context;
+
+import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.FileUtils;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Random;
+
+/**
+ * Utility class for helping while running tests involving {@link UserHistoryDictionary}.
+ */
+public class UserHistoryDictionaryTestsHelper {
+
+ /**
+ * Locale prefix for generating dummy locales for tests.
+ */
+ public static final String TEST_LOCALE_PREFIX = "test-";
+
+ /**
+ * Characters for generating random words.
+ */
+ 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"
+ };
+
+ /**
+ * Remove all the test dictionary files created for the given locale.
+ */
+ public static void removeAllTestDictFiles(final String filter, final Context context) {
+ final FilenameFilter filenameFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(final File dir, final String filename) {
+ return filename.startsWith(UserHistoryDictionary.NAME + "." + filter);
+ }
+ };
+ FileUtils.deleteFilteredFiles(context.getFilesDir(), filenameFilter);
+ }
+
+ /**
+ * Generates and writes random words to dictionary. Caller can be assured
+ * that the write tasks would be finished; and its success would be reflected
+ * in the returned boolean.
+ *
+ * @param dict {@link UserHistoryDictionary} to which words should be added.
+ * @param numberOfWords number of words to be added.
+ * @param random helps generate random words.
+ * @param checkContents if true, checks whether written words are actually in the dictionary.
+ * @param currentTime timestamp that would be used for adding the words.
+ * @returns true if all words have been written to dictionary successfully.
+ */
+ public static boolean addAndWriteRandomWords(final UserHistoryDictionary dict,
+ final int numberOfWords, final Random random, final boolean checkContents,
+ final int currentTime) {
+ final List<String> words = generateWords(numberOfWords, random);
+ // Add random words to the user history dictionary.
+ addWordsToDictionary(dict, words, currentTime);
+ boolean success = true;
+ if (checkContents) {
+ dict.waitAllTasksForTests();
+ for (int i = 0; i < numberOfWords; ++i) {
+ final String word = words.get(i);
+ if (!dict.isInDictionary(word)) {
+ success = false;
+ break;
+ }
+ }
+ }
+ // write to file.
+ dict.close();
+ dict.waitAllTasksForTests();
+ return success;
+ }
+
+ private static void addWordsToDictionary(final UserHistoryDictionary dict,
+ final List<String> words, final int timestamp) {
+ NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext(
+ BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+ for (final String word : words) {
+ UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, timestamp);
+ ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
+ }
+ }
+
+ /**
+ * Creates unique test locale for using within tests.
+ */
+ public static Locale getDummyLocale(final String name) {
+ return new Locale(TEST_LOCALE_PREFIX + name + System.currentTimeMillis());
+ }
+
+ /**
+ * Generates random words.
+ *
+ * @param numberOfWords number of words to generate.
+ * @param random salt used for generating random words.
+ */
+ public static List<String> generateWords(final int numberOfWords, final Random random) {
+ final HashSet<String> wordSet = new HashSet<>();
+ while (wordSet.size() < numberOfWords) {
+ wordSet.add(generateWord(random.nextInt()));
+ }
+ return new ArrayList<>(wordSet);
+ }
+
+ /**
+ * Generates a random word.
+ */
+ private static String generateWord(final int value) {
+ final int lengthOfChars = CHARACTERS.length;
+ final StringBuilder builder = new StringBuilder();
+ long lvalue = Math.abs((long)value);
+ while (lvalue > 0) {
+ builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
+ lvalue /= lengthOfChars;
+ }
+ return builder.toString();
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
new file mode 100644
index 000000000..7a019c364
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.widget.ListView;
+
+import com.android.inputmethod.latin.utils.ManagedProfileUtils;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@MediumTest
+public class AccountsSettingsFragmentTests
+ extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
+ private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
+ private static final long TEST_TIMEOUT_MILLIS = 5000;
+
+ @Mock private ManagedProfileUtils mManagedProfileUtils;
+
+ public AccountsSettingsFragmentTests() {
+ super(TestFragmentActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Initialize the mocks.
+ MockitoAnnotations.initMocks(this);
+ ManagedProfileUtils.setTestInstance(mManagedProfileUtils);
+
+ Intent intent = new Intent();
+ intent.putExtra(TestFragmentActivity.EXTRA_SHOW_FRAGMENT, FRAG_NAME);
+ setActivityIntent(intent);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ ManagedProfileUtils.setTestInstance(null);
+ super.tearDown();
+ }
+
+ public void testEmptyAccounts() {
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ try {
+ fragment.createAccountPicker(new String[0], null, null /* listener */);
+ fail("Expected IllegalArgumentException, never thrown");
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
+ private static class DialogHolder {
+ AlertDialog mDialog;
+ DialogHolder() {}
+ }
+
+ public void testMultipleAccounts_noSettingsForManagedProfile() {
+ when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(true);
+
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ final AlertDialog dialog = initDialog(fragment, null).mDialog;
+ final ListView lv = dialog.getListView();
+
+ // Nothing to check/uncheck.
+ assertNull(fragment.findPreference(AccountsSettingsFragment.PREF_ACCCOUNT_SWITCHER));
+ }
+
+ public void testMultipleAccounts_noCurrentAccount() {
+ when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
+
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ final AlertDialog dialog = initDialog(fragment, null).mDialog;
+ final ListView lv = dialog.getListView();
+
+ // The 1st account should be checked by default.
+ assertEquals("checked-item", 0, lv.getCheckedItemPosition());
+ // There should be 4 accounts in the list.
+ assertEquals("count", 4, lv.getCount());
+ // The sign-out button shouldn't exist
+ assertEquals(View.GONE,
+ dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+ assertEquals(View.VISIBLE,
+ dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+ assertEquals(View.VISIBLE,
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+ }
+
+ public void testMultipleAccounts_currentAccount() {
+ when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
+
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ final AlertDialog dialog = initDialog(fragment, "3@example.com").mDialog;
+ final ListView lv = dialog.getListView();
+
+ // The 3rd account should be checked by default.
+ assertEquals("checked-item", 2, lv.getCheckedItemPosition());
+ // There should be 4 accounts in the list.
+ assertEquals("count", 4, lv.getCount());
+ // The sign-out button should be shown
+ assertEquals(View.VISIBLE,
+ dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+ assertEquals(View.VISIBLE,
+ dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+ assertEquals(View.VISIBLE,
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+ }
+
+ private DialogHolder initDialog(
+ final AccountsSettingsFragment fragment,
+ final String selectedAccount) {
+ final DialogHolder dialogHolder = new DialogHolder();
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final AlertDialog dialog = fragment.createAccountPicker(
+ new String[] {
+ "1@example.com",
+ "2@example.com",
+ "3@example.com",
+ "4@example.com"},
+ selectedAccount, null /* positiveButtonListner */);
+ dialog.show();
+ dialogHolder.mDialog = dialog;
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await(TEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ex) {
+ fail();
+ }
+ getInstrumentation().waitForIdleSync();
+ return dialogHolder;
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
index eb76032b1..ed632db68 100644
--- a/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
@@ -20,9 +20,8 @@ import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.utils.RunInLocale;
import junit.framework.AssertionFailedError;
@@ -37,13 +36,11 @@ public class SpacingAndPunctuationsTests extends AndroidTestCase {
private int mScreenMetrics;
private boolean isPhone() {
- return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_PHONE
- || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_PHONE;
+ return Constants.isPhone(mScreenMetrics);
}
private boolean isTablet() {
- return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_TABLET
- || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_TABLET;
+ return Constants.isTablet(mScreenMetrics);
}
private SpacingAndPunctuations ENGLISH;
@@ -70,7 +67,7 @@ public class SpacingAndPunctuationsTests extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
- mScreenMetrics = mContext.getResources().getInteger(R.integer.config_screen_metrics);
+ mScreenMetrics = Settings.readScreenMetrics(getContext().getResources());
// Language only
ENGLISH = getSpacingAndPunctuations(Locale.ENGLISH);
diff --git a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
index 2272d6ba0..e7c48da19 100644
--- a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
+++ b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
@@ -53,14 +53,8 @@ public class AndroidSpellCheckerServiceTest extends InputTestsBase {
sleep(1000);
final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
- // If no span, the following will crash
- final String[] suggestions = span.getSuggestions();
- // For this test we consider "годп" should yield at least 2 suggestions (at this moment
- // it yields 5).
- assertTrue(suggestions.length >= 2);
- // We also assume the top suggestion should be "года", which is the top word in the
- // Russian dictionary.
- assertEquals("", "года", suggestions[0]);
+ // We don't ship with Russian LM
+ assertNull(span.getSpan());
}
public void testSpellcheckWithPeriods() {
diff --git a/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java b/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java
new file mode 100644
index 000000000..e5c813942
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015 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.spellcheck;
+
+import android.annotation.SuppressLint;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.UserDictionary;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import java.util.HashSet;
+import java.util.Locale;
+
+/**
+ * Unit tests for {@link UserDictionaryLookup}.
+ *
+ * Note, this test doesn't mock out the ContentResolver, in order to make sure UserDictionaryLookup
+ * works in a real setting.
+ */
+@SmallTest
+public class UserDictionaryLookupTest extends AndroidTestCase {
+ private static final String TAG = UserDictionaryLookupTest.class.getSimpleName();
+
+ private ContentResolver mContentResolver;
+ private HashSet<Uri> mAddedBackup;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContentResolver = mContext.getContentResolver();
+ mAddedBackup = new HashSet<Uri>();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Remove all entries added during this test.
+ for (Uri row : mAddedBackup) {
+ mContentResolver.delete(row, null, null);
+ }
+ mAddedBackup.clear();
+
+ super.tearDown();
+ }
+
+ /**
+ * Adds the given word to UserDictionary.
+ *
+ * @param word the word to add
+ * @param locale the locale of the word to add
+ * @param frequency the frequency of the word to add
+ * @return the Uri for the given word
+ */
+ @SuppressLint("NewApi")
+ private Uri addWord(final String word, final Locale locale, int frequency) {
+ // Add the given word for the given locale.
+ UserDictionary.Words.addWord(mContext, word, frequency, null, locale);
+ // Obtain an Uri for the given word.
+ Cursor cursor = mContentResolver.query(UserDictionary.Words.CONTENT_URI, null,
+ UserDictionary.Words.WORD + "='" + word + "'", null, null);
+ assertTrue(cursor.moveToFirst());
+ Uri uri = Uri.withAppendedPath(UserDictionary.Words.CONTENT_URI,
+ cursor.getString(cursor.getColumnIndex(UserDictionary.Words._ID)));
+ // Add the row to the backup for later clearing.
+ mAddedBackup.add(uri);
+ return uri;
+ }
+
+ /**
+ * Deletes the entry for the given word from UserDictionary.
+ *
+ * @param uri the Uri for the word as returned by addWord
+ */
+ private void deleteWord(Uri uri) {
+ // Remove the word from the backup so that it's not cleared again later.
+ mAddedBackup.remove(uri);
+ // Remove the word from UserDictionary.
+ mContentResolver.delete(uri, null, null);
+ }
+
+ public void testExactLocaleMatch() {
+ Log.d(TAG, "testExactLocaleMatch");
+
+ // Insert "Foo" as capitalized in the UserDictionary under en_US locale.
+ addWord("Foo", Locale.US, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // Any capitalization variation should match.
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+ assertTrue(lookup.isValidWord("Foo", Locale.US));
+ assertTrue(lookup.isValidWord("FOO", Locale.US));
+ // But similar looking words don't match.
+ assertFalse(lookup.isValidWord("fo", Locale.US));
+ assertFalse(lookup.isValidWord("fop", Locale.US));
+ assertFalse(lookup.isValidWord("fooo", Locale.US));
+ // Other locales, including more general locales won't match.
+ assertFalse(lookup.isValidWord("foo", Locale.ENGLISH));
+ assertFalse(lookup.isValidWord("foo", Locale.UK));
+ assertFalse(lookup.isValidWord("foo", Locale.FRENCH));
+ assertFalse(lookup.isValidWord("foo", new Locale("")));
+
+ lookup.close();
+ }
+
+ public void testSubLocaleMatch() {
+ Log.d(TAG, "testSubLocaleMatch");
+
+ // Insert "Foo" as capitalized in the UserDictionary under the en locale.
+ addWord("Foo", Locale.ENGLISH, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // Any capitalization variation should match for both en and en_US.
+ assertTrue(lookup.isValidWord("foo", Locale.ENGLISH));
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+ assertTrue(lookup.isValidWord("Foo", Locale.US));
+ assertTrue(lookup.isValidWord("FOO", Locale.US));
+ // But similar looking words don't match.
+ assertFalse(lookup.isValidWord("fo", Locale.US));
+ assertFalse(lookup.isValidWord("fop", Locale.US));
+ assertFalse(lookup.isValidWord("fooo", Locale.US));
+
+ lookup.close();
+ }
+
+ public void testAllLocalesMatch() {
+ Log.d(TAG, "testAllLocalesMatch");
+
+ // Insert "Foo" as capitalized in the UserDictionary under the all locales.
+ addWord("Foo", null, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // Any capitalization variation should match for fr, en and en_US.
+ assertTrue(lookup.isValidWord("foo", new Locale("")));
+ assertTrue(lookup.isValidWord("foo", Locale.FRENCH));
+ assertTrue(lookup.isValidWord("foo", Locale.ENGLISH));
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+ assertTrue(lookup.isValidWord("Foo", Locale.US));
+ assertTrue(lookup.isValidWord("FOO", Locale.US));
+ // But similar looking words don't match.
+ assertFalse(lookup.isValidWord("fo", Locale.US));
+ assertFalse(lookup.isValidWord("fop", Locale.US));
+ assertFalse(lookup.isValidWord("fooo", Locale.US));
+
+ lookup.close();
+ }
+
+ public void testMultipleLocalesMatch() {
+ Log.d(TAG, "testMultipleLocalesMatch");
+
+ // Insert "Foo" as capitalized in the UserDictionary under the en_US and en_CA and fr
+ // locales.
+ addWord("Foo", Locale.US, 17);
+ addWord("foO", Locale.CANADA, 17);
+ addWord("fOo", Locale.FRENCH, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // Both en_CA and en_US match.
+ assertTrue(lookup.isValidWord("foo", Locale.CANADA));
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+ assertTrue(lookup.isValidWord("foo", Locale.FRENCH));
+ // Other locales, including more general locales won't match.
+ assertFalse(lookup.isValidWord("foo", Locale.ENGLISH));
+ assertFalse(lookup.isValidWord("foo", Locale.UK));
+ assertFalse(lookup.isValidWord("foo", new Locale("")));
+
+ lookup.close();
+ }
+
+ public void testReload() {
+ Log.d(TAG, "testReload");
+
+ // Insert "foo".
+ Uri uri = addWord("foo", Locale.US, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // "foo" should match.
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+
+ // "bar" shouldn't match.
+ assertFalse(lookup.isValidWord("bar", Locale.US));
+
+ // Now delete "foo" and add "bar".
+ deleteWord(uri);
+ addWord("bar", Locale.US, 18);
+
+ // Wait a little bit before expecting a change. The time we wait should be greater than
+ // UserDictionaryLookup.RELOAD_DELAY_MS.
+ try {
+ Thread.sleep(UserDictionaryLookup.RELOAD_DELAY_MS + 1000);
+ } catch (InterruptedException e) {
+ }
+
+ // Perform lookups again. Reload should have occured.
+ //
+ // "foo" should not match.
+ assertFalse(lookup.isValidWord("foo", Locale.US));
+
+ // "bar" should match.
+ assertTrue(lookup.isValidWord("bar", Locale.US));
+
+ lookup.close();
+ }
+
+ public void testClose() {
+ Log.d(TAG, "testClose");
+
+ // Insert "foo".
+ Uri uri = addWord("foo", Locale.US, 17);
+
+ // Create the UserDictionaryLookup and wait until it's loaded.
+ UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+ while (!lookup.isLoaded()) {
+ }
+
+ // "foo" should match.
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+
+ // "bar" shouldn't match.
+ assertFalse(lookup.isValidWord("bar", Locale.US));
+
+ // Now close (prevents further reloads).
+ lookup.close();
+
+ // Now delete "foo" and add "bar".
+ deleteWord(uri);
+ addWord("bar", Locale.US, 18);
+
+ // Wait a little bit before expecting a change. The time we wait should be greater than
+ // UserDictionaryLookup.RELOAD_DELAY_MS.
+ try {
+ Thread.sleep(UserDictionaryLookup.RELOAD_DELAY_MS + 1000);
+ } catch (InterruptedException e) {
+ }
+
+ // Perform lookups again. Reload should not have occurred.
+ //
+ // "foo" should stil match.
+ assertTrue(lookup.isValidWord("foo", Locale.US));
+
+ // "bar" should still not match.
+ assertFalse(lookup.isValidWord("bar", Locale.US));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
new file mode 100644
index 000000000..ad6bcc3c4
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.touchinputconsumer;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for GestureConsumer.NULL_GESTURE_CONSUMER.
+ */
+@SmallTest
+public class NullGestureConsumerTests extends AndroidTestCase {
+ /**
+ * Tests that GestureConsumer.NULL_GESTURE_CONSUMER indicates that it won't consume gesture data
+ * and that its methods don't raise exceptions even for invalid data.
+ */
+ public void testNullGestureConsumer() {
+ assertFalse(GestureConsumer.NULL_GESTURE_CONSUMER.willConsume());
+ GestureConsumer.NULL_GESTURE_CONSUMER.onInit(null, null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureStarted(null, null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCanceled();
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCompleted(null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onImeSuggestionsProcessed(null, -1, -1, null);
+ }
+
+ /**
+ * Tests that newInstance returns NULL_GESTURE_CONSUMER for invalid input.
+ */
+ public void testNewInstanceGivesNullGestureConsumerForInvalidInputs() {
+ assertSame(GestureConsumer.NULL_GESTURE_CONSUMER,
+ GestureConsumer.newInstance(null, null, null, null));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
index 91c9c3775..1db839506 100644
--- a/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
@@ -16,6 +16,13 @@
package com.android.inputmethod.latin.utils;
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
+
import android.content.Context;
import android.os.Build;
import android.test.AndroidTestCase;
@@ -26,14 +33,6 @@ import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import java.util.Locale;
-import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue
- .UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
-
@SmallTest
public class AdditionalSubtypeUtilsTests extends AndroidTestCase {
@@ -151,25 +150,25 @@ public class AdditionalSubtypeUtilsTests extends AndroidTestCase {
}
public void testRestorable() {
- final InputMethodSubtype EN_UK_DVORAK =
+ final InputMethodSubtype EN_US_DVORAK =
AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
Locale.US.toString(), "dvorak");
final InputMethodSubtype ZZ_AZERTY =
AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
- assertEnUsDvorak(EN_UK_DVORAK);
+ assertEnUsDvorak(EN_US_DVORAK);
assertAzerty(ZZ_AZERTY);
// Make sure the subtype can be stored and restored in a deterministic manner.
- final InputMethodSubtype[] subtypes = { EN_UK_DVORAK, ZZ_AZERTY };
+ final InputMethodSubtype[] subtypes = { EN_US_DVORAK, ZZ_AZERTY };
final String prefSubtype = AdditionalSubtypeUtils.createPrefSubtypes(subtypes);
final InputMethodSubtype[] restoredSubtypes =
AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
assertEquals(2, restoredSubtypes.length);
- final InputMethodSubtype restored_EN_UK_DVORAK = restoredSubtypes[0];
+ final InputMethodSubtype restored_EN_US_DVORAK = restoredSubtypes[0];
final InputMethodSubtype restored_ZZ_AZERTY = restoredSubtypes[1];
- assertEnUsDvorak(restored_EN_UK_DVORAK);
+ assertEnUsDvorak(restored_EN_US_DVORAK);
assertAzerty(restored_ZZ_AZERTY);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
index 1501e942a..170d64383 100644
--- a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
@@ -22,14 +22,14 @@ import android.util.Log;
@MediumTest
public class AsyncResultHolderTests extends AndroidTestCase {
- private static final String TAG = AsyncResultHolderTests.class.getSimpleName();
+ 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,
+ private static <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
final long time) {
new Thread(new Runnable() {
@Override
diff --git a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
deleted file mode 100644
index a333ee9bc..000000000
--- a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2014 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.LargeTest;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.makedict.FormatSpec;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-@LargeTest
-public class BinaryDictionaryUtilsTests extends AndroidTestCase {
- private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
- private static final String TEST_LOCALE = "test";
-
- private File createEmptyDictionaryAndGetFile(final String dictId,
- final int formatVersion) throws IOException {
- if (formatVersion == FormatSpec.VERSION4) {
- return createEmptyVer4DictionaryAndGetFile(dictId);
- } else {
- throw new IOException("Dictionary format version " + formatVersion
- + " is not supported.");
- }
- }
-
- private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
- final File file = getDictFile(dictId);
- FileUtils.deleteRecursively(file);
- Map<String, String> attributeMap = new HashMap<>();
- attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId);
- attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
- String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
- attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
- DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
- if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), FormatSpec.VERSION4,
- LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
- return file;
- } else {
- throw new IOException("Empty dictionary " + file.getAbsolutePath()
- + " cannot be created.");
- }
- }
-
- private File getDictFile(final String dictId) {
- return new File(getContext().getCacheDir(), dictId + TEST_DICT_FILE_EXTENSION);
- }
-
- public void testRenameDictionary() {
- final int formatVersion = FormatSpec.VERSION4;
- File dictFile0 = null;
- try {
- dictFile0 = createEmptyDictionaryAndGetFile("MoveFromDictionary", formatVersion);
- } catch (IOException e) {
- fail("IOException while writing an initial dictionary : " + e);
- }
- final File dictFile1 = getDictFile("MoveToDictionary");
- FileUtils.deleteRecursively(dictFile1);
- assertTrue(BinaryDictionaryUtils.renameDict(dictFile0, dictFile1));
- assertFalse(dictFile0.exists());
- assertTrue(dictFile1.exists());
- BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile1.getAbsolutePath(),
- 0 /* offset */, dictFile1.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
- assertTrue(binaryDictionary.isValidDictionary());
- assertTrue(binaryDictionary.getFormatVersion() == formatVersion);
- binaryDictionary.close();
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
index c746c8345..9680d85b3 100644
--- a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
@@ -21,8 +21,8 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import java.util.Locale;
@@ -124,5 +124,29 @@ public class CapsModeUtilsTests extends AndroidTestCase {
allPathsForCaps("Word. ", c | w, sp, false);
// Armenian period : capitalize if MODE_SENTENCES
allPathsForCaps("Word\u0589 ", c | w | s, sp, false);
+
+ // Test for sentence terminators
+ sp = job.runInLocale(res, Locale.ENGLISH);
+ allPathsForCaps("Word? ", c | w | s, sp, false);
+ allPathsForCaps("Word?", c | w | s, sp, true);
+ allPathsForCaps("Word?", c, sp, false);
+ allPathsForCaps("Word! ", c | w | s, sp, false);
+ allPathsForCaps("Word!", c | w | s, sp, true);
+ allPathsForCaps("Word!", c, sp, false);
+ allPathsForCaps("Word; ", c | w, sp, false);
+ allPathsForCaps("Word;", c | w, sp, true);
+ allPathsForCaps("Word;", c, sp, false);
+ // Test for sentence terminators in Greek
+ sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("el"));
+ allPathsForCaps("Word? ", c | w | s, sp, false);
+ allPathsForCaps("Word?", c | w | s, sp, true);
+ allPathsForCaps("Word?", c, sp, false);
+ allPathsForCaps("Word! ", c | w | s, sp, false);
+ allPathsForCaps("Word!", c | w | s, sp, true);
+ allPathsForCaps("Word!", c, sp, false);
+ // In Greek ";" is the question mark and it terminates the sentence
+ allPathsForCaps("Word; ", c | w | s, sp, false);
+ allPathsForCaps("Word;", c | w | s, sp, true);
+ allPathsForCaps("Word;", c, sp, false);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
new file mode 100644
index 000000000..47fd5feaa
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 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.common.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Tests for {@link CollectionUtils}.
+ */
+@SmallTest
+public class CollectionUtilsTests extends AndroidTestCase {
+ /**
+ * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} fails as expected
+ * with some invalid inputs.
+ */
+ public void testArrayAsListFailure() {
+ final String[] array = { "0", "1" };
+ // Negative start
+ try {
+ CollectionUtils.arrayAsList(array, -1, 1);
+ fail("Failed to catch start < 0");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid start: -1 end: 1 with array.length: 2", e.getMessage());
+ }
+ // start > end
+ try {
+ CollectionUtils.arrayAsList(array, 1, -1);
+ fail("Failed to catch start > end");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid start: 1 end: -1 with array.length: 2", e.getMessage());
+ }
+ // end > array.length
+ try {
+ CollectionUtils.arrayAsList(array, 1, 3);
+ fail("Failed to catch end > array.length");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid start: 1 end: 3 with array.length: 2", e.getMessage());
+ }
+ }
+
+ /**
+ * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} gives the expected
+ * results for a few valid inputs.
+ */
+ public void testArrayAsList() {
+ final ArrayList<String> empty = new ArrayList<>();
+ assertEquals(empty, CollectionUtils.arrayAsList(new String[] { }, 0, 0));
+ final String[] array = { "0", "1", "2", "3", "4" };
+ assertEquals(empty, CollectionUtils.arrayAsList(array, 0, 0));
+ assertEquals(empty, CollectionUtils.arrayAsList(array, 1, 1));
+ assertEquals(empty, CollectionUtils.arrayAsList(array, array.length, array.length));
+ final ArrayList<String> expected123 = new ArrayList<>(Arrays.asList("1", "2", "3"));
+ assertEquals(expected123, CollectionUtils.arrayAsList(array, 1, 4));
+ }
+
+ /**
+ * Tests that {@link CollectionUtils#isNullOrEmpty(java.util.Collection)} gives the expected
+ * results for a few cases.
+ */
+ public void testIsNullOrEmpty() {
+ assertTrue(CollectionUtils.isNullOrEmpty(null));
+ assertTrue(CollectionUtils.isNullOrEmpty(new ArrayList<>()));
+ assertTrue(CollectionUtils.isNullOrEmpty(Collections.EMPTY_SET));
+ assertFalse(CollectionUtils.isNullOrEmpty(Collections.singleton("Not empty")));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
index 6e716074c..812353cc4 100644
--- a/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
@@ -20,6 +20,7 @@ import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import java.util.Locale;
@@ -44,4 +45,21 @@ public class DictionaryInfoUtilsTests extends AndroidTestCase {
sp));
assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("!!!", sp));
}
+
+ public void testGetMainDictId() {
+ assertEquals("main:en",
+ DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en")));
+ assertEquals("main:en_us",
+ DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_US")));
+ assertEquals("main:en_gb",
+ DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_GB")));
+
+ assertEquals("main:es",
+ DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es")));
+ assertEquals("main:es_us",
+ DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es_US")));
+
+ assertEquals("main:en_us_posix", DictionaryInfoUtils.getMainDictId(
+ LocaleUtils.constructLocaleFromString("en_US_POSIX")));
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java b/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
deleted file mode 100644
index 58312264b..000000000
--- a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-@SmallTest
-public class EditDistanceTests extends AndroidTestCase {
- /*
- * dist(kitten, sitting) == 3
- *
- * kitten-
- * .|||.|
- * sitting
- */
- public void testExample1() {
- final int dist = BinaryDictionaryUtils.editDistance("kitten", "sitting");
- assertEquals("edit distance between 'kitten' and 'sitting' is 3",
- 3, dist);
- }
-
- /*
- * dist(Sunday, Saturday) == 3
- *
- * Saturday
- * | |.|||
- * S--unday
- */
- public void testExample2() {
- final int dist = BinaryDictionaryUtils.editDistance("Saturday", "Sunday");
- assertEquals("edit distance between 'Saturday' and 'Sunday' is 3",
- 3, dist);
- }
-
- public void testBothEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("", "");
- assertEquals("when both string are empty, no edits are needed",
- 0, dist);
- }
-
- public void testFirstArgIsEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("", "aaaa");
- assertEquals("when only one string of the arguments is empty,"
- + " the edit distance is the length of the other.",
- 4, dist);
- }
-
- public void testSecoondArgIsEmpty() {
- final int dist = BinaryDictionaryUtils.editDistance("aaaa", "");
- assertEquals("when only one string of the arguments is empty,"
- + " the edit distance is the length of the other.",
- 4, dist);
- }
-
- public void testSameStrings() {
- final String arg1 = "The quick brown fox jumps over the lazy dog.";
- final String arg2 = "The quick brown fox jumps over the lazy dog.";
- final int dist = BinaryDictionaryUtils.editDistance(arg1, arg2);
- assertEquals("when same strings are passed, distance equals 0.",
- 0, dist);
- }
-
- public void testSameReference() {
- final String arg = "The quick brown fox jumps over the lazy dog.";
- final int dist = BinaryDictionaryUtils.editDistance(arg, arg);
- assertEquals("when same string references are passed, the distance equals 0.",
- 0, dist);
- }
-
- public void testNullArg() {
- try {
- BinaryDictionaryUtils.editDistance(null, "aaa");
- fail("IllegalArgumentException should be thrown.");
- } catch (Exception e) {
- assertTrue(e instanceof IllegalArgumentException);
- }
- try {
- BinaryDictionaryUtils.editDistance("aaa", null);
- fail("IllegalArgumentException should be thrown.");
- } catch (Exception e) {
- assertTrue(e instanceof IllegalArgumentException);
- }
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
index ae2623d12..86923059b 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
@@ -25,18 +25,18 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * Unit tests for ExecutorUtils.
+ * Unit tests for {@link ExecutorUtils}.
*/
@MediumTest
public class ExecutorUtilsTests extends AndroidTestCase {
private static final String TAG = ExecutorUtilsTests.class.getSimpleName();
- private static final String TEST_EXECUTOR_ID = "test";
private static final int NUM_OF_TASKS = 10;
private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500;
public void testExecute() {
- final ExecutorService executor = ExecutorUtils.getExecutor(TEST_EXECUTOR_ID);
+ final ExecutorService executor =
+ ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD);
final AtomicInteger v = new AtomicInteger(0);
for (int i = 0; i < NUM_OF_TASKS; ++i) {
executor.execute(new Runnable() {
diff --git a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
index 819d76328..e361c7704 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
@@ -16,24 +16,32 @@
package com.android.inputmethod.latin.utils;
-import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE;
import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_IMPORTANT_NOTICE_VERSION;
+import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
+import com.android.inputmethod.latin.settings.SettingsValues;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
import java.util.concurrent.TimeUnit;
-@SmallTest
+@MediumTest
public class ImportantNoticeUtilsTests extends AndroidTestCase {
// This should be aligned with R.integer.config_important_notice_version.
private static final int CURRENT_IMPORTANT_NOTICE_VERSION = 1;
private ImportantNoticePreferences mImportantNoticePreferences;
+ @Mock private SettingsValues mMockSettingsValues;
+
private static class ImportantNoticePreferences {
private final SharedPreferences mPref;
@@ -97,8 +105,10 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
+ MockitoAnnotations.initMocks(this);
mImportantNoticePreferences = new ImportantNoticePreferences(getContext());
mImportantNoticePreferences.save();
+ when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true);
}
@Override
@@ -112,11 +122,33 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
ImportantNoticeUtils.getCurrentImportantNoticeVersion(getContext()));
}
+ public void testStateAfterFreshInstall() {
+ mImportantNoticePreferences.clear();
+
+ // Check internal state of {@link ImportantNoticeUtils.shouldShowImportantNotice(Context)}
+ // after fresh install.
+ assertEquals("Has new important notice after fresh install", true,
+ ImportantNoticeUtils.hasNewImportantNotice(getContext()));
+ assertEquals("Next important notice title after fresh install", false, TextUtils.isEmpty(
+ ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
+ assertEquals("Is in system setup wizard after fresh install", false,
+ ImportantNoticeUtils.isInSystemSetupWizard(getContext()));
+ final long currentTimeMillis = System.currentTimeMillis();
+ assertEquals("Has timeout passed after fresh install", false,
+ ImportantNoticeUtils.hasTimeoutPassed(getContext(), currentTimeMillis));
+ assertEquals("Timestamp of first important notice after fresh install",
+ (Long)currentTimeMillis,
+ mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
+
+ assertEquals("Current boolean before update", true,
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+ }
+
public void testUpdateVersion() {
mImportantNoticePreferences.clear();
assertEquals("Current boolean before update", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version before update", 0,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version before update ", 1,
@@ -129,7 +161,7 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
ImportantNoticeUtils.updateLastImportantNoticeVersion(getContext());
assertEquals("Current boolean after update", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version after update", 1,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version after update", 2,
@@ -158,12 +190,12 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
// Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout.
assertEquals("Current boolean before timeout 1", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version before timeout 1", 0,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version before timeout 1", 1,
ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Last time before timeout 1", (Long)lastTime,
+ assertEquals("Timestamp of first important notice before timeout 1", (Long)lastTime,
mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
assertEquals("Current title before timeout 1", false, TextUtils.isEmpty(
ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -175,12 +207,12 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
// Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout
// again.
assertEquals("Current boolean before timeout 2", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version before timeout 2", 0,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version before timeout 2", 1,
ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Last time before timeout 2", (Long)lastTime,
+ assertEquals("Timestamp of first important notice before timeout 2", (Long)lastTime,
mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
assertEquals("Current title before timeout 2", false, TextUtils.isEmpty(
ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -191,12 +223,12 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
// Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout.
assertEquals("Current boolean after timeout 1", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version after timeout 1", 1,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version after timeout 1", 2,
ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Last time aflter timeout 1", null,
+ assertEquals("Timestamp of first important notice after timeout 1", null,
mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
assertEquals("Current title after timeout 1", true, TextUtils.isEmpty(
ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -207,16 +239,30 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
// Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout again.
assertEquals("Current boolean after timeout 2", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
assertEquals("Last version after timeout 2", 1,
ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
assertEquals("Next version after timeout 2", 2,
ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Last time aflter timeout 2", null,
+ assertEquals("Timestamp of first important notice after timeout 2", null,
mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
assertEquals("Current title after timeout 2", true, TextUtils.isEmpty(
ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
assertEquals("Current contents after timeout 2", true, TextUtils.isEmpty(
ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
}
+
+ public void testPersonalizationSetting() {
+ mImportantNoticePreferences.clear();
+
+ // Personalization enabled.
+ when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true);
+ assertEquals("Current boolean with personalization enabled", true,
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+
+ // Personalization disabled.
+ when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(false);
+ assertEquals("Current boolean with personalization disabled", false,
+ ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java
new file mode 100644
index 000000000..194112070
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.util.Arrays;
+import java.util.List;
+
+@SmallTest
+public class JsonUtilsTests extends AndroidTestCase {
+ public void testJsonUtils() {
+ final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
+ final List<Object> objArray = Arrays.asList(objs);
+ final String str = JsonUtils.listToJsonStr(objArray);
+ final List<Object> newObjArray = JsonUtils.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/LanguageOnSpacebarUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java
new file mode 100644
index 000000000..e4b6a668c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2014 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 static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE;
+import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_LANGUAGE_ONLY;
+import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_NONE;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+
+@SmallTest
+public class LanguageOnSpacebarUtilsTests extends AndroidTestCase {
+ private RichInputMethodManager mRichImm;
+
+ RichInputMethodSubtype EN_US_QWERTY;
+ RichInputMethodSubtype EN_GB_QWERTY;
+ RichInputMethodSubtype FR_AZERTY;
+ RichInputMethodSubtype FR_CA_QWERTY;
+ RichInputMethodSubtype FR_CH_SWISS;
+ RichInputMethodSubtype FR_CH_QWERTY;
+ RichInputMethodSubtype FR_CH_QWERTZ;
+ RichInputMethodSubtype IW_HEBREW;
+ RichInputMethodSubtype ZZ_QWERTY;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Context context = getContext();
+ RichInputMethodManager.init(context);
+ mRichImm = RichInputMethodManager.getInstance();
+
+ EN_US_QWERTY = findSubtypeOf(Locale.US.toString(), "qwerty");
+ EN_GB_QWERTY = findSubtypeOf(Locale.UK.toString(), "qwerty");
+ FR_AZERTY = findSubtypeOf(Locale.FRENCH.toString(), "azerty");
+ FR_CA_QWERTY = findSubtypeOf(Locale.CANADA_FRENCH.toString(), "qwerty");
+ FR_CH_SWISS = findSubtypeOf("fr_CH", "swiss");
+ FR_CH_QWERTZ = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwertz"));
+ FR_CH_QWERTY = new RichInputMethodSubtype(
+ AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwerty"));
+ IW_HEBREW = findSubtypeOf("iw", "hebrew");
+ ZZ_QWERTY = findSubtypeOf(SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
+ }
+
+ @Nonnull
+ private RichInputMethodSubtype findSubtypeOf(final String localeString,
+ final String keyboardLayoutSetName) {
+ final InputMethodSubtype subtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ localeString, keyboardLayoutSetName);
+ if (subtype == null) {
+ throw new RuntimeException("Can't find subtype of " + localeString + " with "
+ + keyboardLayoutSetName);
+ }
+ return new RichInputMethodSubtype(subtype);
+ }
+
+ private static void enableSubtypes(final RichInputMethodSubtype ... subtypes) {
+ final ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>();
+ for (final RichInputMethodSubtype subtype : subtypes) {
+ enabledSubtypes.add(subtype.getRawSubtype());
+ }
+ LanguageOnSpacebarUtils.setEnabledSubtypes(enabledSubtypes);
+ }
+
+ private static void assertFormatType(final RichInputMethodSubtype subtype,
+ final boolean implicitlyEnabledSubtype, final Locale systemLocale,
+ final int expectedFormat) {
+ LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale);
+ assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype
+ + " in " + systemLocale, expectedFormat,
+ LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype));
+ }
+
+ public void testOneSubtypeImplicitlyEnabled() {
+ enableSubtypes(EN_US_QWERTY);
+ assertFormatType(EN_US_QWERTY, true, Locale.US, FORMAT_TYPE_NONE);
+
+ enableSubtypes(EN_GB_QWERTY);
+ assertFormatType(EN_GB_QWERTY, true, Locale.UK, FORMAT_TYPE_NONE);
+
+ enableSubtypes(FR_AZERTY);
+ assertFormatType(FR_AZERTY, true, Locale.FRANCE, FORMAT_TYPE_NONE);
+
+ enableSubtypes(FR_CA_QWERTY);
+ assertFormatType(FR_CA_QWERTY, true, Locale.CANADA_FRENCH, FORMAT_TYPE_NONE);
+ }
+
+ public void testOneSubtypeExplicitlyEnabled() {
+ enableSubtypes(EN_US_QWERTY);
+ assertFormatType(EN_US_QWERTY, false, Locale.UK, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ enableSubtypes(EN_GB_QWERTY);
+ assertFormatType(EN_GB_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(EN_GB_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ enableSubtypes(FR_AZERTY);
+ assertFormatType(FR_AZERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ enableSubtypes(FR_CA_QWERTY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ }
+
+ public void testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype() {
+ final Locale Locale_IW = new Locale("iw");
+ enableSubtypes(IW_HEBREW, ZZ_QWERTY);
+ // TODO: Should this be FORMAT_TYPE_NONE?
+ assertFormatType(IW_HEBREW, true, Locale_IW, FORMAT_TYPE_LANGUAGE_ONLY);
+ // TODO: Should this be FORMAT_TYPE_NONE?
+ assertFormatType(ZZ_QWERTY, true, Locale_IW, FORMAT_TYPE_FULL_LOCALE);
+ }
+
+ public void testTwoSubtypesExplicitlyEnabled() {
+ enableSubtypes(EN_US_QWERTY, FR_AZERTY);
+ assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_AZERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ enableSubtypes(EN_US_QWERTY, ZZ_QWERTY);
+ assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(ZZ_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(ZZ_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+
+ }
+
+ public void testMultiSubtypeWithSameLanuageAndSameLayout() {
+ // Explicitly enable en_US, en_GB, fr_FR, and no language keyboards.
+ enableSubtypes(EN_US_QWERTY, EN_GB_QWERTY, FR_CA_QWERTY, ZZ_QWERTY);
+
+ assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(EN_GB_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CA_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(ZZ_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE);
+
+ assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(EN_GB_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(ZZ_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+ }
+
+ public void testMultiSubtypesWithSameLanguageButHaveDifferentLayout() {
+ enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTZ);
+
+ assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_SWISS, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_SWISS, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_SWISS, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ }
+
+ public void testMultiSubtypesWithSameLanguageAndMayHaveSameLayout() {
+ enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ);
+
+ assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_SWISS, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_SWISS, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+ assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_SWISS, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ assertFormatType(FR_CH_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+ assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
index a3f2ce586..9b826839f 100644
--- a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
@@ -19,7 +19,7 @@ package com.android.inputmethod.latin.utils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
import java.util.Locale;
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
deleted file mode 100644
index fdde34251..000000000
--- a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
+++ /dev/null
@@ -1,251 +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.utils;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.RichInputMethodManager;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SmallTest
-public class SpacebarLanguagetUtilsTests extends AndroidTestCase {
- // All input method subtypes of LatinIME.
- private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<>();
-
- private RichInputMethodManager mRichImm;
- private Resources mRes;
-
- InputMethodSubtype EN_US;
- InputMethodSubtype EN_GB;
- InputMethodSubtype ES_US;
- InputMethodSubtype FR;
- InputMethodSubtype FR_CA;
- InputMethodSubtype FR_CH;
- InputMethodSubtype DE;
- InputMethodSubtype DE_CH;
- 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);
-
- final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
- final int subtypeCount = imi.getSubtypeCount();
- for (int index = 0; index < subtypeCount; index++) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(index);
- mSubtypesList.add(subtype);
- }
-
- 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");
- FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- "fr_CH", "swiss");
- DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- Locale.GERMAN.toString(), "qwertz");
- DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- "de_CH", "swiss");
- ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
- DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- Locale.GERMAN.toString(), "qwerty");
- FR_QWERTZ = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- Locale.FRENCH.toString(), "qwertz");
- EN_US_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- Locale.US.toString(), "azerty");
- EN_UK_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- Locale.UK.toString(), "dvorak");
- ES_US_COLEMAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- "es_US", "colemak");
- ZZ_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
- ZZ_PC = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
- SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty");
- }
-
- public void testAllFullDisplayNameForSpacebar() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocaleUtils
- .getSubtypeDisplayNameInSystemLocale(subtype);
- final String spacebarText = SpacebarLanguageUtils.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 = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
- if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
- assertEquals(subtypeName,
- SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText);
- } else {
- final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
- assertEquals(subtypeName,
- SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()),
- spacebarText);
- }
- }
- }
-
- // InputMethodSubtype's display name for spacebar text in its locale.
- // isAdditionalSubtype (T=true, F=false)
- // locale layout | Middle Full
- // ------ ------- - --------- ----------------------
- // en_US qwerty F English English (US) exception
- // en_GB qwerty F English English (UK) exception
- // es_US spanish F Español Español (EE.UU.) exception
- // fr azerty F Français Français
- // fr_CA qwerty F Français Français (Canada)
- // fr_CH swiss F Français Français (Suisse)
- // de qwertz F Deutsch Deutsch
- // de_CH swiss F Deutsch Deutsch (Schweiz)
- // zz qwerty F QWERTY QWERTY
- // fr qwertz T Français Français
- // de qwerty T Deutsch Deutsch
- // en_US azerty T 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)",
- SpacebarLanguageUtils.getFullDisplayName(EN_US));
- assertEquals("en_GB", "English (UK)",
- SpacebarLanguageUtils.getFullDisplayName(EN_GB));
- assertEquals("es_US", "Español (EE.UU.)",
- SpacebarLanguageUtils.getFullDisplayName(ES_US));
- assertEquals("fr", "Français",
- SpacebarLanguageUtils.getFullDisplayName(FR));
- assertEquals("fr_CA", "Français (Canada)",
- SpacebarLanguageUtils.getFullDisplayName(FR_CA));
- assertEquals("fr_CH", "Français (Suisse)",
- SpacebarLanguageUtils.getFullDisplayName(FR_CH));
- assertEquals("de", "Deutsch",
- SpacebarLanguageUtils.getFullDisplayName(DE));
- assertEquals("de_CH", "Deutsch (Schweiz)",
- SpacebarLanguageUtils.getFullDisplayName(DE_CH));
- assertEquals("zz", "QWERTY",
- SpacebarLanguageUtils.getFullDisplayName(ZZ));
-
- assertEquals("en_US", "English",
- SpacebarLanguageUtils.getMiddleDisplayName(EN_US));
- assertEquals("en_GB", "English",
- SpacebarLanguageUtils.getMiddleDisplayName(EN_GB));
- assertEquals("es_US", "Español",
- SpacebarLanguageUtils.getMiddleDisplayName(ES_US));
- assertEquals("fr", "Français",
- SpacebarLanguageUtils.getMiddleDisplayName(FR));
- assertEquals("fr_CA", "Français",
- SpacebarLanguageUtils.getMiddleDisplayName(FR_CA));
- assertEquals("fr_CH", "Français",
- SpacebarLanguageUtils.getMiddleDisplayName(FR_CH));
- assertEquals("de", "Deutsch",
- SpacebarLanguageUtils.getMiddleDisplayName(DE));
- assertEquals("de_CH", "Deutsch",
- SpacebarLanguageUtils.getMiddleDisplayName(DE_CH));
- assertEquals("zz", "QWERTY",
- SpacebarLanguageUtils.getMiddleDisplayName(ZZ));
- return null;
- }
- };
-
- private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
- @Override
- protected Void job(final Resources res) {
- assertEquals("fr qwertz", "Français",
- SpacebarLanguageUtils.getFullDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- SpacebarLanguageUtils.getFullDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English (US)",
- SpacebarLanguageUtils.getFullDisplayName(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English (UK)",
- SpacebarLanguageUtils.getFullDisplayName(EN_UK_DVORAK));
- assertEquals("es_US colemak", "Español (EE.UU.)",
- SpacebarLanguageUtils.getFullDisplayName(ES_US_COLEMAK));
- assertEquals("zz azerty", "AZERTY",
- SpacebarLanguageUtils.getFullDisplayName(ZZ_AZERTY));
- assertEquals("zz pc", "PC",
- SpacebarLanguageUtils.getFullDisplayName(ZZ_PC));
-
- assertEquals("fr qwertz", "Français",
- SpacebarLanguageUtils.getMiddleDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- SpacebarLanguageUtils.getMiddleDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English",
- SpacebarLanguageUtils.getMiddleDisplayName(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English",
- SpacebarLanguageUtils.getMiddleDisplayName(EN_UK_DVORAK));
- assertEquals("es_US colemak", "Español",
- SpacebarLanguageUtils.getMiddleDisplayName(ES_US_COLEMAK));
- assertEquals("zz azerty", "AZERTY",
- SpacebarLanguageUtils.getMiddleDisplayName(ZZ_AZERTY));
- assertEquals("zz pc", "PC",
- SpacebarLanguageUtils.getMiddleDisplayName(ZZ_PC));
- 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/utils/SpannableStringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
index fa6ad16c1..665d81ccd 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
@@ -20,9 +20,10 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
+import android.text.SpannableString;
import android.text.SpannableStringBuilder;
-import android.text.Spannable;
import android.text.Spanned;
+import android.text.SpannedString;
@SmallTest
public class SpannableStringUtilsTests extends AndroidTestCase {
@@ -34,8 +35,8 @@ public class SpannableStringUtilsTests extends AndroidTestCase {
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);
+ new String[] {"" + i}, Spanned.SPAN_PARAGRAPH),
+ i * 12, i * 12 + 12, Spanned.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.
@@ -51,8 +52,175 @@ public class SpannableStringUtilsTests extends AndroidTestCase {
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);
+ flags & Spanned.SPAN_PARAGRAPH, 0);
assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
}
}
+
+ private static void assertSpanCount(final int expectedCount, final CharSequence cs) {
+ final int actualCount;
+ if (cs instanceof Spanned) {
+ final Spanned spanned = (Spanned) cs;
+ actualCount = spanned.getSpans(0, spanned.length(), Object.class).length;
+ } else {
+ actualCount = 0;
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
+ private static void assertSpan(final CharSequence cs, final Object expectedSpan,
+ final int expectedStart, final int expectedEnd, final int expectedFlags) {
+ assertTrue(cs instanceof Spanned);
+ final Spanned spanned = (Spanned) cs;
+ final Object[] actualSpans = spanned.getSpans(0, spanned.length(), Object.class);
+ for (Object actualSpan : actualSpans) {
+ if (actualSpan == expectedSpan) {
+ final int actualStart = spanned.getSpanStart(actualSpan);
+ final int actualEnd = spanned.getSpanEnd(actualSpan);
+ final int actualFlags = spanned.getSpanFlags(actualSpan);
+ assertEquals(expectedStart, actualStart);
+ assertEquals(expectedEnd, actualEnd);
+ assertEquals(expectedFlags, actualFlags);
+ return;
+ }
+ }
+ assertTrue(false);
+ }
+
+ public void testSplitCharSequenceWithSpan() {
+ // text: " a bcd efg hij "
+ // span1: ^^^^^^^
+ // span2: ^^^^^
+ // span3: ^
+ final SpannableString spannableString = new SpannableString(" a bcd efg hij ");
+ final Object span1 = new Object();
+ final Object span2 = new Object();
+ final Object span3 = new Object();
+ final int SPAN1_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
+ final int SPAN2_FLAGS = Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
+ final int SPAN3_FLAGS = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
+ spannableString.setSpan(span1, 0, 7, SPAN1_FLAGS);
+ spannableString.setSpan(span2, 0, 5, SPAN2_FLAGS);
+ spannableString.setSpan(span3, 12, 13, SPAN3_FLAGS);
+ final CharSequence[] charSequencesFromSpanned = SpannableStringUtils.split(
+ spannableString, " ", true /* preserveTrailingEmptySegmengs */);
+ final CharSequence[] charSequencesFromString = SpannableStringUtils.split(
+ spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */);
+
+
+ assertEquals(7, charSequencesFromString.length);
+ assertEquals(7, charSequencesFromSpanned.length);
+
+ // text: ""
+ // span1: ^
+ // span2: ^
+ // span3:
+ assertEquals("", charSequencesFromString[0].toString());
+ assertSpanCount(0, charSequencesFromString[0]);
+ assertEquals("", charSequencesFromSpanned[0].toString());
+ assertSpanCount(2, charSequencesFromSpanned[0]);
+ assertSpan(charSequencesFromSpanned[0], span1, 0, 0, SPAN1_FLAGS);
+ assertSpan(charSequencesFromSpanned[0], span2, 0, 0, SPAN2_FLAGS);
+
+ // text: "a"
+ // span1: ^
+ // span2: ^
+ // span3:
+ assertEquals("a", charSequencesFromString[1].toString());
+ assertSpanCount(0, charSequencesFromString[1]);
+ assertEquals("a", charSequencesFromSpanned[1].toString());
+ assertSpanCount(2, charSequencesFromSpanned[1]);
+ assertSpan(charSequencesFromSpanned[1], span1, 0, 1, SPAN1_FLAGS);
+ assertSpan(charSequencesFromSpanned[1], span2, 0, 1, SPAN2_FLAGS);
+
+ // text: "bcd"
+ // span1: ^^^
+ // span2: ^^
+ // span3:
+ assertEquals("bcd", charSequencesFromString[2].toString());
+ assertSpanCount(0, charSequencesFromString[2]);
+ assertEquals("bcd", charSequencesFromSpanned[2].toString());
+ assertSpanCount(2, charSequencesFromSpanned[2]);
+ assertSpan(charSequencesFromSpanned[2], span1, 0, 3, SPAN1_FLAGS);
+ assertSpan(charSequencesFromSpanned[2], span2, 0, 2, SPAN2_FLAGS);
+
+ // text: "efg"
+ // span1:
+ // span2:
+ // span3:
+ assertEquals("efg", charSequencesFromString[3].toString());
+ assertSpanCount(0, charSequencesFromString[3]);
+ assertEquals("efg", charSequencesFromSpanned[3].toString());
+ assertSpanCount(0, charSequencesFromSpanned[3]);
+
+ // text: "hij"
+ // span1:
+ // span2:
+ // span3: ^
+ assertEquals("hij", charSequencesFromString[4].toString());
+ assertSpanCount(0, charSequencesFromString[4]);
+ assertEquals("hij", charSequencesFromSpanned[4].toString());
+ assertSpanCount(1, charSequencesFromSpanned[4]);
+ assertSpan(charSequencesFromSpanned[4], span3, 1, 2, SPAN3_FLAGS);
+
+ // text: ""
+ // span1:
+ // span2:
+ // span3:
+ assertEquals("", charSequencesFromString[5].toString());
+ assertSpanCount(0, charSequencesFromString[5]);
+ assertEquals("", charSequencesFromSpanned[5].toString());
+ assertSpanCount(0, charSequencesFromSpanned[5]);
+
+ // text: ""
+ // span1:
+ // span2:
+ // span3:
+ assertEquals("", charSequencesFromString[6].toString());
+ assertSpanCount(0, charSequencesFromString[6]);
+ assertEquals("", charSequencesFromSpanned[6].toString());
+ assertSpanCount(0, charSequencesFromSpanned[6]);
+ }
+
+ public void testSplitCharSequencePreserveTrailingEmptySegmengs() {
+ assertEquals(1, SpannableStringUtils.split("", " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(1, SpannableStringUtils.split("", " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(0, SpannableStringUtils.split(" ", " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(0, SpannableStringUtils.split(new SpannedString(" "), " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(2, SpannableStringUtils.split(" ", " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(2, SpannableStringUtils.split(new SpannedString(" "), " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(3, SpannableStringUtils.split("a b c ", " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(3, SpannableStringUtils.split(new SpannedString("a b c "), " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(5, SpannableStringUtils.split("a b c ", " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(5, SpannableStringUtils.split(new SpannedString("a b c "), " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(6, SpannableStringUtils.split("a b ", " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(6, SpannableStringUtils.split(new SpannedString("a b "), " ",
+ false /* preserveTrailingEmptySegmengs */).length);
+
+ assertEquals(7, SpannableStringUtils.split("a b ", " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+ assertEquals(7, SpannableStringUtils.split(new SpannedString("a b "), " ",
+ true /* preserveTrailingEmptySegmengs */).length);
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
deleted file mode 100644
index ba2e99802..000000000
--- a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2014 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.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
-
-import java.util.Locale;
-
-@SmallTest
-public class StringUtilsTests extends AndroidTestCase {
- private static final Locale US = Locale.US;
- private static final Locale GERMAN = Locale.GERMAN;
- private static final Locale TURKEY = new Locale("tr", "TR");
- private static final Locale GREECE = new Locale("el", "GR");
-
- private static void assert_toUpperCaseOfStringForLocale(final Locale locale,
- final String lowerCase, final String expected) {
- assertEquals(lowerCase + " in " + locale, expected,
- StringUtils.toUpperCaseOfStringForLocale(
- lowerCase, true /* needsToUpperCase */, locale));
- }
-
- public void test_toUpperCaseOfStringForLocale() {
- assert_toUpperCaseOfStringForLocale(US, null, null);
- assert_toUpperCaseOfStringForLocale(US, "", "");
- assert_toUpperCaseOfStringForLocale(US, "aeiou", "AEIOU");
- // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
- // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
- // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
- // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
- // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
- // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
- // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
- // U+00C0: "À" LATIN CAPITAL LETTER A WITH GRAVE
- // U+00C8: "È" LATIN CAPITAL LETTER E WITH GRAVE
- // U+00CE: "Î" LATIN CAPITAL LETTER I WITH CIRCUMFLEX
- // U+00D6: "Ö" LATIN CAPITAL LETTER O WITH DIAERESIS
- // U+016A: "Ū" LATIN CAPITAL LETTER U WITH MACRON
- // U+00D1: "Ñ" LATIN CAPITAL LETTER N WITH TILDE
- // U+00C7: "Ç" LATIN CAPITAL LETTER C WITH CEDILLA
- assert_toUpperCaseOfStringForLocale(US,
- "\u00E0\u00E8\u00EE\u00F6\u016B\u00F1\u00E7",
- "\u00C0\u00C8\u00CE\u00D6\u016A\u00D1\u00C7");
- // U+00DF: "ß" LATIN SMALL LETTER SHARP S
- // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
- // U+0161: "š" LATIN SMALL LETTER S WITH CARON
- // U+015A: "Ś" LATIN CAPITAL LETTER S WITH ACUTE
- // U+0160: "Š" LATIN CAPITAL LETTER S WITH CARONZ
- assert_toUpperCaseOfStringForLocale(GERMAN,
- "\u00DF\u015B\u0161",
- "SS\u015A\u0160");
- // U+0259: "ə" LATIN SMALL LETTER SCHWA
- // U+0069: "i" LATIN SMALL LETTER I
- // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
- // U+018F: "Ə" LATIN SMALL LETTER SCHWA
- // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
- // U+0049: "I" LATIN SMALL LETTER I
- assert_toUpperCaseOfStringForLocale(TURKEY,
- "\u0259\u0069\u0131",
- "\u018F\u0130\u0049");
- // U+03C3: "σ" GREEK SMALL LETTER SIGMA
- // U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA
- // U+03A3: "Σ" GREEK CAPITAL LETTER SIGMA
- assert_toUpperCaseOfStringForLocale(GREECE,
- "\u03C3\u03C2",
- "\u03A3\u03A3");
- // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
- // U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS
- // U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS
- // U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
- // U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS
- // U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
- // U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS
- // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
- // U+0388: "Έ" GREEK CAPITAL LETTER EPSILON WITH TONOS
- // U+0389: "Ή" GREEK CAPITAL LETTER ETA WITH TONOS
- // U+038A: "Ί" GREEK CAPITAL LETTER IOTA WITH TONOS
- // U+038C: "Ό" GREEK CAPITAL LETTER OMICRON WITH TONOS
- // U+038E: "Ύ" GREEK CAPITAL LETTER UPSILON WITH TONOS
- // U+038F: "Ώ" GREEK CAPITAL LETTER OMEGA WITH TONOS
- assert_toUpperCaseOfStringForLocale(GREECE,
- "\u03AC\u03AD\u03AE\u03AF\u03CC\u03CD\u03CE",
- "\u0386\u0388\u0389\u038A\u038C\u038E\u038F");
- // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
- // U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
- // U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
- // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
- // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
- // U+03AB: "Ϋ" GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
- // U+0399: "Ι" GREEK CAPITAL LETTER IOTA
- // U+03A5: "Υ" GREEK CAPITAL LETTER UPSILON
- // U+0308: COMBINING DIAERESIS
- // U+0301: COMBINING GRAVE ACCENT
- assert_toUpperCaseOfStringForLocale(GREECE,
- "\u03CA\u03CB\u0390\u03B0",
- "\u03AA\u03AB\u0399\u0308\u0301\u03A5\u0308\u0301");
- }
-
- private static void assert_toUpperCaseOfCodeForLocale(final Locale locale, final int lowerCase,
- final int expected) {
- assertEquals(lowerCase + " in " + locale, expected,
- StringUtils.toUpperCaseOfCodeForLocale(
- lowerCase, true /* needsToUpperCase */, locale));
- }
-
- public void test_toUpperCaseOfCodeForLocale() {
- assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_ENTER, Constants.CODE_ENTER);
- assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_SPACE, Constants.CODE_SPACE);
- assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_COMMA, Constants.CODE_COMMA);
- // U+0069: "i" LATIN SMALL LETTER I
- // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
- // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
- // U+0049: "I" LATIN SMALL LETTER I
- assert_toUpperCaseOfCodeForLocale(US, 0x0069, 0x0049); // i -> I
- assert_toUpperCaseOfCodeForLocale(US, 0x0131, 0x0049); // ı -> I
- assert_toUpperCaseOfCodeForLocale(TURKEY, 0x0069, 0x0130); // i -> İ
- assert_toUpperCaseOfCodeForLocale(TURKEY, 0x0131, 0x0049); // ı -> I
- // U+00DF: "ß" LATIN SMALL LETTER SHARP S
- // The title case of "ß" is "SS".
- assert_toUpperCaseOfCodeForLocale(US, 0x00DF, Constants.CODE_UNSPECIFIED);
- // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
- // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
- assert_toUpperCaseOfCodeForLocale(GREECE, 0x03AC, 0x0386);
- // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
- // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
- assert_toUpperCaseOfCodeForLocale(GREECE, 0x03CA, 0x03AA);
- // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
- // The title case of "ΰ" is "\u03A5\u0308\u0301".
- assert_toUpperCaseOfCodeForLocale(GREECE, 0x03B0, Constants.CODE_UNSPECIFIED);
- }
-
- private static void assert_capitalizeFirstCodePoint(final Locale locale, final String text,
- final String expected) {
- assertEquals(text + " in " + locale, expected,
- StringUtils.capitalizeFirstCodePoint(text, locale));
- }
-
- public void test_capitalizeFirstCodePoint() {
- assert_capitalizeFirstCodePoint(US, "", "");
- assert_capitalizeFirstCodePoint(US, "a", "A");
- assert_capitalizeFirstCodePoint(US, "à", "À");
- assert_capitalizeFirstCodePoint(US, "ß", "SS");
- assert_capitalizeFirstCodePoint(US, "text", "Text");
- assert_capitalizeFirstCodePoint(US, "iGoogle", "IGoogle");
- assert_capitalizeFirstCodePoint(TURKEY, "iyi", "İyi");
- assert_capitalizeFirstCodePoint(TURKEY, "ısırdı", "Isırdı");
- assert_capitalizeFirstCodePoint(GREECE, "ά", "Ά");
- assert_capitalizeFirstCodePoint(GREECE, "άνεση", "Άνεση");
- }
-
- private static void assert_capitalizeFirstAndDowncaseRest(final Locale locale,
- final String text, final String expected) {
- assertEquals(text + " in " + locale, expected,
- StringUtils.capitalizeFirstAndDowncaseRest(text, locale));
- }
-
- public void test_capitalizeFirstAndDowncaseRest() {
- assert_capitalizeFirstAndDowncaseRest(US, "", "");
- assert_capitalizeFirstAndDowncaseRest(US, "a", "A");
- assert_capitalizeFirstAndDowncaseRest(US, "à", "À");
- assert_capitalizeFirstAndDowncaseRest(US, "ß", "SS");
- assert_capitalizeFirstAndDowncaseRest(US, "text", "Text");
- assert_capitalizeFirstAndDowncaseRest(US, "iGoogle", "Igoogle");
- assert_capitalizeFirstAndDowncaseRest(US, "invite", "Invite");
- assert_capitalizeFirstAndDowncaseRest(US, "INVITE", "Invite");
- assert_capitalizeFirstAndDowncaseRest(TURKEY, "iyi", "İyi");
- assert_capitalizeFirstAndDowncaseRest(TURKEY, "İYİ", "İyi");
- assert_capitalizeFirstAndDowncaseRest(TURKEY, "ısırdı", "Isırdı");
- assert_capitalizeFirstAndDowncaseRest(TURKEY, "ISIRDI", "Isırdı");
- assert_capitalizeFirstAndDowncaseRest(GREECE, "ά", "Ά");
- assert_capitalizeFirstAndDowncaseRest(GREECE, "άνεση", "Άνεση");
- assert_capitalizeFirstAndDowncaseRest(GREECE, "ΆΝΕΣΗ", "Άνεση");
- }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index ce3df7dd6..2297cacf8 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -23,7 +23,9 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
import java.util.ArrayList;
import java.util.Locale;
@@ -31,10 +33,11 @@ import java.util.Locale;
@SmallTest
public class SubtypeLocaleUtilsTests extends AndroidTestCase {
// All input method subtypes of LatinIME.
- private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<>();
+ private final ArrayList<RichInputMethodSubtype> mSubtypesList = new ArrayList<>();
private RichInputMethodManager mRichImm;
private Resources mRes;
+ private InputMethodSubtype mSavedAddtionalSubtypes[];
InputMethodSubtype EN_US;
InputMethodSubtype EN_GB;
@@ -44,6 +47,8 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
InputMethodSubtype FR_CH;
InputMethodSubtype DE;
InputMethodSubtype DE_CH;
+ InputMethodSubtype HI;
+ InputMethodSubtype SR;
InputMethodSubtype ZZ;
InputMethodSubtype DE_QWERTY;
InputMethodSubtype FR_QWERTZ;
@@ -53,20 +58,33 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
InputMethodSubtype ZZ_AZERTY;
InputMethodSubtype ZZ_PC;
+ // These are preliminary subtypes and may not exist.
+ InputMethodSubtype HI_LATN; // Hinglish
+ InputMethodSubtype SR_LATN; // Serbian Latin
+ InputMethodSubtype HI_LATN_DVORAK; // Hinglis Dvorak
+ InputMethodSubtype SR_LATN_QWERTY; // Serbian Latin Qwerty
+
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getContext();
+ mRes = context.getResources();
RichInputMethodManager.init(context);
mRichImm = RichInputMethodManager.getInstance();
- mRes = context.getResources();
- SubtypeLocaleUtils.init(context);
+
+ // Save and reset additional subtypes
+ mSavedAddtionalSubtypes = mRichImm.getAdditionalSubtypes();
+ final InputMethodSubtype[] predefinedAddtionalSubtypes =
+ AdditionalSubtypeUtils.createAdditionalSubtypesArray(
+ AdditionalSubtypeUtils.createPrefSubtypes(
+ mRes.getStringArray(R.array.predefined_subtypes)));
+ mRichImm.setAdditionalInputMethodSubtypes(predefinedAddtionalSubtypes);
final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
final int subtypeCount = imi.getSubtypeCount();
for (int index = 0; index < subtypeCount; index++) {
final InputMethodSubtype subtype = imi.getSubtypeAt(index);
- mSubtypesList.add(subtype);
+ mSubtypesList.add(new RichInputMethodSubtype(subtype));
}
EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
@@ -85,6 +103,10 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
Locale.GERMAN.toString(), "qwertz");
DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
"de_CH", "swiss");
+ HI = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "hi", "hindi");
+ SR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "sr", "south_slavic");
ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
@@ -101,19 +123,37 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
ZZ_PC = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty");
+
+ HI_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("hi_ZZ", "qwerty");
+ if (HI_LATN != null) {
+ HI_LATN_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ "hi_ZZ", "dvorak");
+ }
+ SR_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("sr_ZZ", "serbian_qwertz");
+ if (SR_LATN != null) {
+ SR_LATN_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+ "sr_ZZ", "qwerty");
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Restore additional subtypes.
+ mRichImm.setAdditionalInputMethodSubtypes(mSavedAddtionalSubtypes);
+ super.tearDown();
}
public void testAllFullDisplayName() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
+ for (final RichInputMethodSubtype subtype : mSubtypesList) {
final String subtypeName = SubtypeLocaleUtils
- .getSubtypeDisplayNameInSystemLocale(subtype);
- if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+ if (subtype.isNoLanguage()) {
final String layoutName = SubtypeLocaleUtils
- .getKeyboardLayoutSetDisplayName(subtype);
+ .getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
assertTrue(subtypeName, subtypeName.contains(layoutName));
} else {
final String languageName = SubtypeLocaleUtils
- .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale());
+ .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale().toString());
assertTrue(subtypeName, subtypeName.contains(languageName));
}
}
@@ -128,6 +168,8 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH));
assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH));
+ assertEquals("hi", "hindi", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI));
+ assertEquals("sr", "south_slavic", SubtypeLocaleUtils.getKeyboardLayoutSetName(SR));
assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY));
@@ -140,27 +182,46 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US_COLEMAK));
assertEquals("zz azerty", "azerty",
SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ_AZERTY));
+
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN != null) {
+ assertEquals("hi_ZZ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN));
+ assertEquals("hi_ZZ dvorak", "dvorak",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN_DVORAK));
+ }
+ if (SR_LATN != null) {
+ assertEquals("sr_ZZ", "serbian_qwertz",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN));
+ assertEquals("sr_ZZ qwerty", "qwerty",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN_QWERTY));
+ }
}
// 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)
- // fr_CH swiss F French (Switzerland)
- // de qwertz F German
- // de_CH swiss F German (Switzerland)
- // 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)
+ // 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)
+ // fr_CH swiss F French (Switzerland)
+ // de qwertz F German
+ // de_CH swiss F German (Switzerland)
+ // hi hindi F Hindi
+ // hi_ZZ qwerty F Hinglish exception
+ // sr south_slavic F Serbian
+ // sr_ZZ serbian_qwertz F Serbian (Latin) exception
+ // 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
+ // hi_ZZ dvorak T Hinglish (Dvorka) exception
+ // sr_ZZ qwerty T Serbian (QWERTY) exception
+ // zz pc T Alphabet (PC)
public void testPredefinedSubtypesInEnglishSystemLocale() {
final RunInLocale<Void> tests = new RunInLocale<Void>() {
@@ -182,8 +243,21 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
assertEquals("de_CH", "German (Switzerland)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
+ assertEquals("hi", "Hindi",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+ assertEquals("sr", "Serbian",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
assertEquals("zz", "Alphabet (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN != null) {
+ assertEquals("hi_ZZ", "Hinglish",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+ }
+ if (SR_LATN != null) {
+ assertEquals("sr_ZZ", "Serbian (Latin)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+ }
return null;
}
};
@@ -208,6 +282,15 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
assertEquals("zz pc", "Alphabet (PC)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN_DVORAK != null) {
+ assertEquals("hi_ZZ", "Hinglish (Dvorak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+ }
+ if (SR_LATN_QWERTY != null) {
+ assertEquals("sr_ZZ", "Serbian (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+ }
return null;
}
};
@@ -218,21 +301,27 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
// 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)
- // fr_CH swiss F Français (Suisse)
- // de qwertz F Allemand
- // de_CH swiss F Allemand (Suisse)
- // zz qwerty F Alphabet latin (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 latin (PC)
+ // 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)
+ // fr_CH swiss F Français (Suisse)
+ // de qwertz F Allemand
+ // de_CH swiss F Allemand (Suisse)
+ // hi hindi F Hindi exception
+ // hi_ZZ qwerty F Hindi/Anglais exception
+ // sr south_slavic F Serbe exception
+ // sr_ZZ serbian_qwertz F Serbe (latin) exception
+ // zz qwerty F Alphabet latin (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
+ // hi_ZZ dvorak T Hindi/Anglais (Dvorka) exception
+ // sr_ZZ qwerty T Serbe (QWERTY) exception
+ // zz pc T Alphabet latin (PC)
public void testPredefinedSubtypesInFrenchSystemLocale() {
final RunInLocale<Void> tests = new RunInLocale<Void>() {
@@ -254,8 +343,21 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
assertEquals("de_CH", "Allemand (Suisse)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
+ assertEquals("hi", "Hindi",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+ assertEquals("sr", "Serbe",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
assertEquals("zz", "Alphabet latin (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN != null) {
+ assertEquals("hi_ZZ", "Hindi/Anglais",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+ }
+ if (SR_LATN != null) {
+ assertEquals("sr_ZZ", "Serbe (latin)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+ }
return null;
}
};
@@ -280,12 +382,75 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
assertEquals("zz pc", "Alphabet latin (PC)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN_DVORAK != null) {
+ assertEquals("hi_ZZ", "Hindi/Anglais (Dvorak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+ }
+ if (SR_LATN_QWERTY != null) {
+ assertEquals("sr_ZZ", "Serbe (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+ }
return null;
}
};
tests.runInLocale(mRes, Locale.FRENCH);
}
+ // InputMethodSubtype's display name in system locale (hi).
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | display name
+ // ------ ------- - ----------------------
+ // hi hindi F हिन्दी
+ // hi_ZZ qwerty F हिंग्लिश
+ // hi_ZZ dvorak T हिंग्लिश (Dvorak)
+
+ public void testHinglishSubtypesInHindiSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job (final Resources res) {
+ assertEquals("hi", "हिन्दी",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+ // These are preliminary subtypes and may not exist.
+ if (HI_LATN != null) {
+ assertEquals("hi_ZZ", "हिंग्लिश",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+ assertEquals("hi_ZZ", "हिंग्लिश (Dvorak)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+ }
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, new Locale("hi"));
+ }
+
+ // InputMethodSubtype's display name in system locale (sr).
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | display name
+ // ------ -------------- - ----------------------
+ // sr south_slavic F Српски
+ // sr_ZZ serbian_qwertz F Српски (латиница)
+ // sr_ZZ qwerty T Српски (QWERTY)
+
+ public void testSerbianLatinSubtypesInSerbianSystemLocale() {
+ final RunInLocale<Void> tests = new RunInLocale<Void>() {
+ @Override
+ protected Void job (final Resources res) {
+ assertEquals("sr", "Српски",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
+ // These are preliminary subtypes and may not exist.
+ if (SR_LATN != null) {
+ assertEquals("sr_ZZ", "Српски (латиница)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+ assertEquals("sr_ZZ", "Српски (QWERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+ }
+ return null;
+ }
+ };
+ tests.runInLocale(mRes, new Locale("sr"));
+ }
+
public void testIsRtlLanguage() {
// Known Right-to-Left language subtypes.
final InputMethodSubtype ARABIC = mRichImm
@@ -298,13 +463,15 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
.findSubtypeByLocaleAndKeyboardLayoutSet("iw", "hebrew");
assertNotNull("Hebrew", HEBREW);
- for (final InputMethodSubtype subtype : mSubtypesList) {
+ for (final RichInputMethodSubtype subtype : mSubtypesList) {
+ final InputMethodSubtype rawSubtype = subtype.getRawSubtype();
final String subtypeName = SubtypeLocaleUtils
- .getSubtypeDisplayNameInSystemLocale(subtype);
- if (subtype.equals(ARABIC) || subtype.equals(FARSI) || subtype.equals(HEBREW)) {
- assertTrue(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+ .getSubtypeDisplayNameInSystemLocale(rawSubtype);
+ if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI)
+ || rawSubtype.equals(HEBREW)) {
+ assertTrue(subtypeName, subtype.isRtlSubtype());
} else {
- assertFalse(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+ assertFalse(subtypeName, subtype.isRtlSubtype());
}
}
}