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.java594
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java691
-rw-r--r--tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java25
-rw-r--r--tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java81
-rw-r--r--tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java12
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java178
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java216
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java6
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java35
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java14
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java112
-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.java67
-rw-r--r--tests/src/com/android/inputmethod/latin/PunctuationTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java98
-rw-r--r--tests/src/com/android/inputmethod/latin/ShiftModeTests.java6
-rw-r--r--tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java51
-rw-r--r--tests/src/com/android/inputmethod/latin/WordComposerTests.java3
-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/makedict/BinaryDictDecoderEncoderTests.java104
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java67
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java192
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java12
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java16
-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.java89
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java36
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java120
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java90
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java22
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java27
-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.java7
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java38
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java157
-rw-r--r--tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java148
-rw-r--r--tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java11
-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.java8
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java24
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java85
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/DistracterFilterTest.java (renamed from tests/src/com/android/inputmethod/latin/DistracterFilterTest.java)36
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java99
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java36
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtilsTests.java318
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java251
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java7
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java40
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java276
58 files changed, 3423 insertions, 1768 deletions
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index ae184268c..039330c87 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -20,9 +20,9 @@ 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.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.CodePointUtils;
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;
@@ -32,13 +32,14 @@ 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 com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Locale;
-import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@@ -48,7 +49,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 };
+ new int[] { FormatSpec.VERSION402, FormatSpec.VERSION403, FormatSpec.VERSION4_DEV };
+ private static final String DICTIONARY_ID = "TestDecayingBinaryDictionary";
private int mCurrentTime = 0;
@@ -56,35 +58,64 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
mCurrentTime = 0;
+ mDictFilesToBeDeleted.clear();
+ setCurrentTimeForTestMode(mCurrentTime);
}
@Override
protected void tearDown() throws Exception {
+ for (final File dictFile : mDictFilesToBeDeleted) {
+ dictFile.delete();
+ }
+ mDictFilesToBeDeleted.clear();
stopTestModeInNativeCode();
super.tearDown();
}
- private static boolean supportsBeginningOfSentence(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
+ private static boolean supportsCountBasedNgram(final int formatVersion) {
+ return formatVersion >= FormatSpec.VERSION403;
}
- 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 static boolean supportsNgram(final int formatVersion) {
+ return formatVersion >= FormatSpec.VERSION403;
}
- private void addBigramWords(final BinaryDictionary binaryDictionary, final String word0,
- final String word1, final int probability) {
- binaryDictionary.addNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1, probability,
+ private void onInputWord(final BinaryDictionary binaryDictionary, final String word,
+ final boolean isValidWord) {
+ binaryDictionary.updateEntriesForWordWithNgramContext(NgramContext.EMPTY_PREV_WORDS_INFO,
+ word, isValidWord, 1 /* count */, mCurrentTime /* timestamp */);
+ }
+
+ private void onInputWordWithPrevWord(final BinaryDictionary binaryDictionary, final String word,
+ final boolean isValidWord, final String prevWord) {
+ binaryDictionary.updateEntriesForWordWithNgramContext(
+ new NgramContext(new WordInfo(prevWord)), word, isValidWord, 1 /* count */,
mCurrentTime /* timestamp */);
}
+ private void onInputWordWithPrevWords(final BinaryDictionary binaryDictionary,
+ final String word, final boolean isValidWord, final String prevWord,
+ final String prevPrevWord) {
+ binaryDictionary.updateEntriesForWordWithNgramContext(
+ new NgramContext(new WordInfo(prevWord), new WordInfo(prevPrevWord)), word,
+ isValidWord, 1 /* count */, mCurrentTime /* timestamp */);
+ }
+
+ private void onInputWordWithBeginningOfSentenceContext(
+ final BinaryDictionary binaryDictionary, final String word, final boolean isValidWord) {
+ binaryDictionary.updateEntriesForWordWithNgramContext(NgramContext.BEGINNING_OF_SENTENCE,
+ word, isValidWord, 1 /* count */, mCurrentTime /* timestamp */);
+ }
+
private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
final String word0, final String word1) {
- return binaryDictionary.isValidNgram(new PrevWordsInfo(new WordInfo(word0)), word1);
+ return binaryDictionary.isValidNgram(new NgramContext(new WordInfo(word0)), word1);
+ }
+
+ private static boolean isValidTrigram(final BinaryDictionary binaryDictionary,
+ final String word0, final String word1, final String word2) {
+ return binaryDictionary.isValidNgram(
+ new NgramContext(new WordInfo(word1), new WordInfo(word0)), word2);
}
private void forcePassingShortTime(final BinaryDictionary binaryDictionary) {
@@ -103,25 +134,33 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 HashSet<File> mDictFilesToBeDeleted = new HashSet<>();
+
+ private File createEmptyDictionaryAndGetFile(final int formatVersion) {
+ return createEmptyDictionaryWithAttributeMapAndGetFile(formatVersion,
+ new HashMap<String, String>());
}
- private File createEmptyVer4DictionaryAndGetFile(final String dictId, final int formatVersion)
+ private File createEmptyDictionaryWithAttributeMapAndGetFile(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 int formatVersion,
+ final HashMap<String, String> attributeMap)
throws IOException {
- final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
+ final File file = File.createTempFile(DICTIONARY_ID, 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_ID_KEY, DICTIONARY_ID);
attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
@@ -131,10 +170,15 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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);
}
+ throw new IOException("Empty dictionary " + file.getAbsolutePath()
+ + " cannot be created. Foramt version: " + 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 static int setCurrentTimeForTestMode(final int currentTime) {
@@ -153,19 +197,11 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWord(binaryDictionary, "ab", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "aaa", true /* isValidWord */, "a");
binaryDictionary.flushWithGC();
binaryDictionary.close();
@@ -189,7 +225,6 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
} catch (UnsupportedFormatException e) {
fail("Unsupported format: " + e);
}
- dictFile.delete();
}
public void testControlCurrentTime() {
@@ -214,42 +249,43 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
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 */);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
+ onInputWord(binaryDictionary, "a", false /* isValidWord */);
assertFalse(binaryDictionary.isValidWord("a"));
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
+ onInputWord(binaryDictionary, "a", false /* isValidWord */);
+ onInputWord(binaryDictionary, "a", false /* isValidWord */);
assertTrue(binaryDictionary.isValidWord("a"));
- addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
- assertTrue(binaryDictionary.isValidWord("b"));
-
- addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "b", false /* isValidWord */, "a");
assertFalse(isValidBigram(binaryDictionary, "a", "b"));
- addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "b", false /* isValidWord */, "a");
+ assertTrue(binaryDictionary.isValidWord("b"));
assertTrue(isValidBigram(binaryDictionary, "a", "b"));
- addUnigramWord(binaryDictionary, "c", DUMMY_PROBABILITY);
- addBigramWords(binaryDictionary, "a", "c", DUMMY_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "c", true /* isValidWord */, "a");
assertTrue(isValidBigram(binaryDictionary, "a", "c"));
// Add bigrams of not valid unigrams.
- addBigramWords(binaryDictionary, "x", "y", Dictionary.NOT_A_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "y", false /* isValidWord */, "x");
assertFalse(isValidBigram(binaryDictionary, "x", "y"));
- addBigramWords(binaryDictionary, "x", "y", DUMMY_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "y", true /* isValidWord */, "x");
assertFalse(isValidBigram(binaryDictionary, "x", "y"));
- binaryDictionary.close();
- dictFile.delete();
+ if (!supportsNgram(formatVersion)) {
+ return;
+ }
+
+ onInputWordWithPrevWords(binaryDictionary, "c", true /* isValidWord */, "b", "a");
+ assertTrue(isValidTrigram(binaryDictionary, "a", "b", "c"));
+ assertTrue(isValidBigram(binaryDictionary, "b", "c"));
+ onInputWordWithPrevWords(binaryDictionary, "d", false /* isValidWord */, "c", "b");
+ assertFalse(isValidTrigram(binaryDictionary, "b", "c", "d"));
+ assertFalse(isValidBigram(binaryDictionary, "c", "d"));
+
+ onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "b", "a");
+ assertTrue(isValidTrigram(binaryDictionary, "a", "b", "cd"));
}
public void testDecayingProbability() {
@@ -259,54 +295,80 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
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 */);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
assertTrue(binaryDictionary.isValidWord("a"));
forcePassingShortTime(binaryDictionary);
+ if (supportsCountBasedNgram(formatVersion)) {
+ // Count based ngram language model doesn't support decaying based on the elapsed time.
+ assertTrue(binaryDictionary.isValidWord("a"));
+ } else {
+ assertFalse(binaryDictionary.isValidWord("a"));
+ }
+ forcePassingLongTime(binaryDictionary);
assertFalse(binaryDictionary.isValidWord("a"));
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
- addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
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);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "b", true /* isValidWord */, "a");
assertTrue(isValidBigram(binaryDictionary, "a", "b"));
forcePassingShortTime(binaryDictionary);
+ if (supportsCountBasedNgram(formatVersion)) {
+ assertTrue(isValidBigram(binaryDictionary, "a", "b"));
+ } else {
+ assertFalse(isValidBigram(binaryDictionary, "a", "b"));
+ }
+ forcePassingLongTime(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);
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "b", true /* isValidWord */, "a");
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "b", true /* isValidWord */, "a");
+ onInputWord(binaryDictionary, "a", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "b", true /* isValidWord */, "a");
assertTrue(isValidBigram(binaryDictionary, "a", "b"));
forcePassingShortTime(binaryDictionary);
assertTrue(isValidBigram(binaryDictionary, "a", "b"));
forcePassingLongTime(binaryDictionary);
assertFalse(isValidBigram(binaryDictionary, "a", "b"));
+ if (!supportsNgram(formatVersion)) {
+ return;
+ }
+
+ onInputWord(binaryDictionary, "ab", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "bc", true /* isValidWord */, "ab");
+ onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "bc", "ab");
+ assertTrue(isValidTrigram(binaryDictionary, "ab", "bc", "cd"));
+ forcePassingLongTime(binaryDictionary);
+ assertFalse(isValidTrigram(binaryDictionary, "ab", "bc", "cd"));
+
+ onInputWord(binaryDictionary, "ab", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "bc", true /* isValidWord */, "ab");
+ onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "bc", "ab");
+ onInputWord(binaryDictionary, "ab", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "bc", true /* isValidWord */, "ab");
+ onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "bc", "ab");
+ onInputWord(binaryDictionary, "ab", true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, "bc", true /* isValidWord */, "ab");
+ onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "bc", "ab");
+ forcePassingShortTime(binaryDictionary);
+ assertTrue(isValidTrigram(binaryDictionary, "ab", "bc", "cd"));
+ forcePassingLongTime(binaryDictionary);
+ assertFalse(isValidTrigram(binaryDictionary, "ab", "bc", "cd"));
+
binaryDictionary.close();
- dictFile.delete();
}
public void testAddManyUnigramsToDecayingDict() {
@@ -321,16 +383,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
setCurrentTimeForTestMode(mCurrentTime);
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
@@ -342,31 +396,32 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
final int maxUnigramCount = Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
+ binaryDictionary.getPropertyForGettingStats(
+ 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);
+ onInputWord(binaryDictionary, word, true /* isValidWord */);
if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
final int unigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY));
while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
forcePassingShortTime(binaryDictionary);
}
final int unigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY));
assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
}
}
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
+ assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY)) > 0);
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
+ assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY)) <= maxUnigramCount);
forcePassingLongTime(binaryDictionary);
- assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
+ assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY)));
}
@@ -384,26 +439,18 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
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);
+ onInputWord(binaryDictionary, strong, true /* isValidWord */);
}
for (int j = 0; j < weakUnigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, weak, DUMMY_PROBABILITY);
+ onInputWord(binaryDictionary, weak, true /* isValidWord */);
}
assertTrue(binaryDictionary.isValidWord(strong));
assertTrue(binaryDictionary.isValidWord(weak));
@@ -411,17 +458,17 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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);
+ onInputWord(binaryDictionary, word, true /* isValidWord */);
}
if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
final int unigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY));
assertTrue(binaryDictionary.isValidWord(strong));
assertTrue(binaryDictionary.isValidWord(weak));
binaryDictionary.flushWithGC();
final int unigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.UNIGRAM_COUNT_QUERY));
assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
assertFalse(binaryDictionary.isValidWord(weak));
@@ -438,6 +485,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
private void testAddManyBigramsToDecayingDict(final int 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));
+
final int unigramCount = 5000;
final int bigramCount = 30000;
final int bigramTypedCount = 100000;
@@ -445,16 +498,10 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 File dictFile = createEmptyDictionaryWithAttributeMapAndGetFile(formatVersion,
+ attributeMap);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
final ArrayList<String> words = new ArrayList<>();
@@ -476,34 +523,32 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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);
+ onInputWord(binaryDictionary, bigram.first, true /* isValidWord */);
+ onInputWordWithPrevWord(binaryDictionary, bigram.second, true /* isValidWord */,
+ bigram.first);
if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
final int bigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY));
while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
forcePassingShortTime(binaryDictionary);
}
final int bigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY));
assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
}
}
-
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
+ forcePassingShortTime(binaryDictionary);
+ assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY)) > 0);
- assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
+ assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY)) <= maxBigramCount);
forcePassingLongTime(binaryDictionary);
- assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
+ assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY)));
}
@@ -514,6 +559,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
}
private void testOverflowBigrams(final int 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));
+
final int bigramCount = 20000;
final int unigramCount = 1000;
final int unigramTypedCount = 20;
@@ -523,17 +574,10 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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 File dictFile = createEmptyDictionaryWithAttributeMapAndGetFile(formatVersion,
+ attributeMap);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
final ArrayList<String> words = new ArrayList<>();
@@ -541,23 +585,22 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
final String word = CodePointUtils.generateWord(random, codePointSet);
words.add(word);
for (int j = 0; j < unigramTypedCount; j++) {
- addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
+ onInputWord(binaryDictionary, word, true /* isValidWord */);
}
}
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);
+ onInputWord(binaryDictionary, weak, true /* isValidWord */);
+ onInputWord(binaryDictionary, strong, true /* isValidWord */);
}
binaryDictionary.flushWithGC();
for (int j = 0; j < strongBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, strong, target, DUMMY_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, target, true /* isValidWord */, strong);
}
for (int j = 0; j < weakBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, weak, target, DUMMY_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, target, true /* isValidWord */, weak);
}
assertTrue(isValidBigram(binaryDictionary, strong, target));
assertTrue(isValidBigram(binaryDictionary, weak, target));
@@ -570,15 +613,15 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
final String word1 = words.get(word1Index);
for (int j = 0; j < eachBigramTypedCount; j++) {
- addBigramWords(binaryDictionary, word0, word1, DUMMY_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, word1, true /* isValidWord */, word0);
}
if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
final int bigramCountBeforeGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY));
binaryDictionary.flushWithGC();
final int bigramCountAfterGC =
- Integer.parseInt(binaryDictionary.getPropertyForTest(
+ Integer.parseInt(binaryDictionary.getPropertyForGettingStats(
BinaryDictionary.BIGRAM_COUNT_QUERY));
assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
assertTrue(isValidBigram(binaryDictionary, strong, target));
@@ -596,97 +639,182 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
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);
+ final File dictFile = createEmptyDictionaryAndGetFile(fromFormatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
+ onInputWord(binaryDictionary, "aaa", true /* isValidWord */);
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);
+ onInputWord(binaryDictionary, "ccc", true /* isValidWord */);
+ onInputWord(binaryDictionary, "ccc", true /* isValidWord */);
+ onInputWord(binaryDictionary, "ccc", true /* isValidWord */);
+ onInputWord(binaryDictionary, "ccc", true /* isValidWord */);
+ onInputWord(binaryDictionary, "ccc", true /* isValidWord */);
+
+ onInputWordWithPrevWord(binaryDictionary, "abc", true /* isValidWord */, "aaa");
assertTrue(isValidBigram(binaryDictionary, "aaa", "abc"));
- addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
+ onInputWordWithPrevWord(binaryDictionary, "bbb", false /* isValidWord */, "aaa");
+ assertFalse(binaryDictionary.isValidWord("bbb"));
assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb"));
+ if (supportsNgram(toFormatVersion)) {
+ onInputWordWithPrevWords(binaryDictionary, "xyz", true, "abc", "aaa");
+ assertTrue(isValidTrigram(binaryDictionary, "aaa", "abc", "xyz"));
+ onInputWordWithPrevWords(binaryDictionary, "def", false, "abc", "aaa");
+ assertFalse(isValidTrigram(binaryDictionary, "aaa", "abc", "def"));
+ }
+
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"));
+ if (supportsCountBasedNgram(toFormatVersion)) {
+ assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc"));
+ onInputWord(binaryDictionary, "bbb", false /* isValidWord */);
+ 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"));
+ if (supportsCountBasedNgram(toFormatVersion)) {
+ onInputWordWithPrevWord(binaryDictionary, "bbb", false /* isValidWord */, "aaa");
+ assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
+ }
+ if (supportsNgram(toFormatVersion)) {
+ assertTrue(isValidTrigram(binaryDictionary, "aaa", "abc", "xyz"));
+ assertFalse(isValidTrigram(binaryDictionary, "aaa", "abc", "def"));
+ onInputWordWithPrevWords(binaryDictionary, "def", false, "abc", "aaa");
+ assertTrue(isValidTrigram(binaryDictionary, "aaa", "abc", "def"));
+ }
+
binaryDictionary.close();
- dictFile.delete();
}
public void testBeginningOfSentence() {
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- if (supportsBeginningOfSentence(formatVersion)) {
- testBeginningOfSentence(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 */);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
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"));
-
+ Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+ true /* isBeginningOfSentence */, true /* isNotAWord */,
+ false /* isPossiblyOffensive */, mCurrentTime);
+ final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */);
+ assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa"));
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */);
+ assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa"));
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */);
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */);
+ assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb"));
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */);
+ assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa"));
+ assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "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"));
+ assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa"));
+ assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb"));
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */);
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */);
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */);
+ onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */);
+ assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa"));
+ assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb"));
binaryDictionary.close();
- dictFile.delete();
+ }
+
+ public void testRemoveUnigrams() {
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRemoveUnigrams(formatVersion);
+ }
+ }
+
+ private void testRemoveUnigrams(final int formatVersion) {
+ final int unigramInputCount = 20;
+ setCurrentTimeForTestMode(mCurrentTime);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
+
+ onInputWord(binaryDictionary, "aaa", false /* isValidWord */);
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+ for (int i = 0; i < unigramInputCount; i++) {
+ onInputWord(binaryDictionary, "aaa", false /* isValidWord */);
+ }
+ assertTrue(binaryDictionary.isValidWord("aaa"));
+ assertTrue(binaryDictionary.removeUnigramEntry("aaa"));
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+ onInputWord(binaryDictionary, "aaa", false /* isValidWord */);
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+ onInputWord(binaryDictionary, "aaa", false /* isValidWord */);
+ assertTrue(binaryDictionary.isValidWord("aaa"));
+ assertTrue(binaryDictionary.removeUnigramEntry("aaa"));
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+ binaryDictionary.close();
+ }
+
+ public void testUpdateEntriesForInputEvents() {
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testUpdateEntriesForInputEvents(formatVersion);
+ }
+ }
+
+ private void testUpdateEntriesForInputEvents(final int formatVersion) {
+ setCurrentTimeForTestMode(mCurrentTime);
+ final int codePointSetSize = 20;
+ final int EVENT_COUNT = 1000;
+ final double CONTINUE_RATE = 0.9;
+ final long seed = System.currentTimeMillis();
+ final Random random = new Random(seed);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+
+ final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
+ final ArrayList<String> unigrams = new ArrayList<>();
+ final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
+ final ArrayList<Pair<Pair<String, String>, String>> trigrams = new ArrayList<>();
+
+ final WordInputEventForPersonalization[] inputEvents =
+ new WordInputEventForPersonalization[EVENT_COUNT];
+ NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+ int prevWordCount = 0;
+ for (int i = 0; i < inputEvents.length; i++) {
+ final String word = CodePointUtils.generateWord(random, codePointSet);
+ inputEvents[i] = new WordInputEventForPersonalization(word, ngramContext,
+ true /* isValid */, mCurrentTime);
+ unigrams.add(word);
+ if (prevWordCount >= 2) {
+ final Pair<String, String> prevWordsPair = bigrams.get(bigrams.size() - 1);
+ trigrams.add(new Pair<>(prevWordsPair, word));
+ }
+ if (prevWordCount >= 1) {
+ bigrams.add(new Pair<>(ngramContext.getNthPrevWord(1 /* n */).toString(), word));
+ }
+ if (random.nextDouble() > CONTINUE_RATE) {
+ ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+ prevWordCount = 0;
+ } else {
+ ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
+ prevWordCount++;
+ }
+ }
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
+ binaryDictionary.updateEntriesForInputEvents(inputEvents);
+
+ for (final String word : unigrams) {
+ assertTrue(binaryDictionary.isInDictionary(word));
+ }
+ for (final Pair<String, String> bigram : bigrams) {
+ assertTrue(isValidBigram(binaryDictionary, bigram.first, bigram.second));
+ }
+ if (!supportsNgram(formatVersion)) {
+ return;
+ }
+ for (final Pair<Pair<String, String>, String> trigram : trigrams) {
+ assertTrue(isValidTrigram(binaryDictionary, trigram.first.first, trigram.first.second,
+ trigram.second));
+ }
}
}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 6ba18d665..fcaa8cdca 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -21,14 +21,15 @@ 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.Constants;
+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,7 +37,6 @@ 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.
@@ -45,42 +45,73 @@ 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 };
+ new int[] { FormatSpec.VERSION402, FormatSpec.VERSION403, FormatSpec.VERSION4_DEV };
+ private static final String DICTIONARY_ID = "TestBinaryDictionary";
- private static boolean canCheckBigramProbability(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
+ private static boolean supportsNgram(final int formatVersion) {
+ return formatVersion >= FormatSpec.VERSION403;
}
- private static boolean supportsBeginningOfSentence(final int formatVersion) {
- return formatVersion > FormatSpec.VERSION401;
+ private HashSet<File> mDictFilesToBeDeleted = new HashSet<>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDictFilesToBeDeleted.clear();
}
- 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.");
+ @Override
+ protected void tearDown() throws Exception {
+ for (final File dictFile : mDictFilesToBeDeleted) {
+ dictFile.delete();
}
+ mDictFilesToBeDeleted.clear();
+ super.tearDown();
+ }
+
+ private File createEmptyDictionaryAndGetFile(final int formatVersion) {
+ return createEmptyDictionaryWithAttributesAndGetFile(formatVersion,
+ new HashMap<String, String>());
+ }
+
+ 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);
+ }
+
+ 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 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() {
@@ -90,24 +121,15 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(),
- 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
- Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+ final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+ 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();
@@ -120,15 +142,10 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(formatVersion);
FileUtils.deleteRecursively(dictFile);
assertFalse(dictFile.exists());
- BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE, formatVersion,
new HashMap<String, String>());
assertTrue(binaryDictionary.isValidDictionary());
@@ -143,7 +160,6 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(formatVersion, binaryDictionary.getFormatVersion());
assertEquals(probability, binaryDictionary.getFrequency("word"));
binaryDictionary.close();
- dictFile.delete();
}
public void testAddTooLongWord() {
@@ -153,16 +169,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(formatVersion);
final StringBuffer stringBuilder = new StringBuffer();
for (int i = 0; i < Constants.DICTIONARY_MAX_WORD_LENGTH; i++) {
stringBuilder.append('a');
@@ -177,7 +184,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
// Too long short cut.
binaryDictionary.addUnigramEntry("a", probability, invalidLongWord,
10 /* shortcutProbability */, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */,
+ false /* isNotAWord */, false /* isPossiblyOffensive */,
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
addUnigramWord(binaryDictionary, "abc", probability);
final int updatedProbability = 200;
@@ -188,39 +195,60 @@ 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 */,
+ Dictionary.NOT_A_PROBABILITY /* shortcutProbability */,
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 void addTrigramEntry(final BinaryDictionary binaryDictionary, final String word0,
+ final String word1, final String word2, final int probability) {
+ final NgramContext ngramContext =
+ new NgramContext(new WordInfo[] { new WordInfo(word1), new WordInfo(word0) } );
+ binaryDictionary.addNgramEntry(ngramContext, word2, 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);
+ return binaryDictionary.isValidNgram(new NgramContext(new WordInfo(word0)), word1);
}
private static void removeBigramEntry(final BinaryDictionary binaryDictionary,
final String word0, final String word1) {
- binaryDictionary.removeNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1);
+ binaryDictionary.removeNgramEntry(new NgramContext(new WordInfo(word0)), word1);
+ }
+
+ private static void removeTrigramEntry(final BinaryDictionary binaryDictionary,
+ final String word0, final String word1, final String word2) {
+ final NgramContext ngramContext =
+ new NgramContext(new WordInfo[] { new WordInfo(word1), new WordInfo(word0) } );
+ binaryDictionary.removeNgramEntry(ngramContext, word2);
}
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);
+ }
+
+ private static int getTrigramProbability(final BinaryDictionary binaryDictionary,
+ final String word0, final String word1, final String word2) {
+ final NgramContext ngramContext =
+ new NgramContext(new WordInfo[] { new WordInfo(word1), new WordInfo(word0) } );
+ return binaryDictionary.getNgramProbability(ngramContext, word2);
}
public void testAddUnigramWord() {
@@ -230,16 +258,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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 */);
-
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
final int probability = 100;
addUnigramWord(binaryDictionary, "aaa", probability);
// Reallocate and create.
@@ -263,8 +282,6 @@ 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() {
@@ -277,16 +294,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
final HashMap<String, Integer> probabilityMap = new HashMap<>();
// Test a word that isn't contained within the dictionary.
@@ -302,7 +310,6 @@ public class BinaryDictionaryTests extends AndroidTestCase {
for (String word : probabilityMap.keySet()) {
assertEquals(word, (int)probabilityMap.get(word), binaryDictionary.getFrequency(word));
}
- dictFile.delete();
}
public void testAddBigramWords() {
@@ -312,15 +319,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(formatVersion);
final int unigramProbability = 100;
final int bigramProbability = 150;
@@ -337,18 +336,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,19 +363,12 @@ 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() {
@@ -395,16 +383,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
final ArrayList<String> words = new ArrayList<>();
final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -439,13 +418,9 @@ 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));
- }
+ assertEquals(bigramProbability,
+ getBigramProbability(binaryDictionary, bigram.first, bigram.second));
}
-
- dictFile.delete();
}
public void testRemoveBigramWords() {
@@ -455,15 +430,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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 */);
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
final int unigramProbability = 100;
final int bigramProbability = 150;
addUnigramWord(binaryDictionary, "aaa", unigramProbability);
@@ -496,8 +463,45 @@ public class BinaryDictionaryTests extends AndroidTestCase {
// Test remove non-existing bigram operation.
removeBigramEntry(binaryDictionary, "aaa", "abb");
removeBigramEntry(binaryDictionary, "bcc", "aaa");
+ }
+
+ public void testAddTrigramWords() {
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ if (supportsNgram(formatVersion)) {
+ testAddTrigramWords(formatVersion);
+ }
+ }
+ }
+
+ private void testAddTrigramWords(final int formatVersion) {
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
+ final int unigramProbability = 100;
+ final int trigramProbability = 150;
+ final int updatedTrigramProbability = 200;
+ addUnigramWord(binaryDictionary, "aaa", unigramProbability);
+ addUnigramWord(binaryDictionary, "abb", unigramProbability);
+ addUnigramWord(binaryDictionary, "bcc", unigramProbability);
+
+ addBigramWords(binaryDictionary, "abb", "bcc", 10);
+ addBigramWords(binaryDictionary, "abb", "aaa", 10);
+
+ addTrigramEntry(binaryDictionary, "aaa", "abb", "bcc", trigramProbability);
+ addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", trigramProbability);
+
+ assertEquals(trigramProbability,
+ getTrigramProbability(binaryDictionary, "aaa", "abb", "bcc"));
+ assertEquals(trigramProbability,
+ getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
+ assertFalse(isValidBigram(binaryDictionary, "aaa", "abb"));
+
+ addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", updatedTrigramProbability);
+ assertEquals(updatedTrigramProbability,
+ getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
- dictFile.delete();
+ removeTrigramEntry(binaryDictionary, "aaa", "abb", "bcc");
+ assertEquals(Dictionary.NOT_A_PROBABILITY,
+ getTrigramProbability(binaryDictionary, "aaa", "abb", "bcc"));
+ assertTrue(isValidBigram(binaryDictionary, "abb", "bcc"));
}
public void testFlushDictionary() {
@@ -507,15 +511,8 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(formatVersion);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int probability = 100;
addUnigramWord(binaryDictionary, "aaa", probability);
@@ -535,23 +532,16 @@ 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() {
@@ -561,16 +551,8 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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(formatVersion);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final int unigramProbability = 100;
final int bigramProbability = 150;
addUnigramWord(binaryDictionary, "aaa", unigramProbability);
@@ -583,25 +565,19 @@ 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() {
@@ -618,16 +594,8 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
+ BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final ArrayList<String> words = new ArrayList<>();
final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -660,22 +628,15 @@ 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() {
@@ -685,6 +646,12 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
private void testRandomOperationsAndFlashWithGC(final int 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));
+
final int flashWithGCIterationCount = 50;
final int operationCountInEachIteration = 200;
final int initialUnigramCount = 100;
@@ -695,17 +662,10 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final long seed = System.currentTimeMillis();
final Random random = new Random(seed);
+ final File dictFile = createEmptyDictionaryWithAttributesAndGetFile(formatVersion,
+ 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 +682,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) {
@@ -781,18 +739,14 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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() {
@@ -808,12 +762,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
final ArrayList<String> words = new ArrayList<>();
final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
@@ -821,9 +770,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,8 +788,6 @@ public class BinaryDictionaryTests extends AndroidTestCase {
binaryDictionary.flushWithGC();
binaryDictionary.close();
}
-
- dictFile.delete();
}
public void testUnigramAndBigramCount() {
@@ -852,19 +797,20 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
private void testUnigramAndBigramCount(final int 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));
+
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(formatVersion,
+ attributeMap);
final ArrayList<String> words = new ArrayList<>();
final HashSet<Pair<String, String>> bigrams = new HashSet<>();
@@ -872,9 +818,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,83 +836,20 @@ 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() {
@@ -984,16 +865,8 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
+ final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
false /* isBeginningOfSentence */);
@@ -1008,11 +881,11 @@ 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,
+ null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY,
+ false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
binaryDictionary.flushWithGC();
@@ -1024,8 +897,8 @@ 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(isPossiblyOffensive, wordProperty.mIsPossiblyOffensive);
+ assertEquals(false, wordProperty.mHasNgrams);
assertEquals(false, wordProperty.mHasShortcuts);
assertEquals(unigramProbability, wordProperty.mProbabilityInfo.mProbability);
assertTrue(wordProperty.mShortcutTargets.isEmpty());
@@ -1062,14 +935,13 @@ 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());
}
}
}
@@ -1087,16 +959,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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(formatVersion);
final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
false /* isBeginningOfSentence */);
@@ -1155,15 +1018,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);
@@ -1178,21 +1042,13 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
final int unigramProbability = 100;
final int shortcutProbability = 10;
binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
shortcutProbability, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
+ false /* isNotAWord */, false /* isPossiblyOffensive */, 0 /* timestamp */);
WordProperty wordProperty = binaryDictionary.getWordProperty("aaa",
false /* isBeginningOfSentence */);
assertEquals(1, wordProperty.mShortcutTargets.size());
@@ -1201,7 +1057,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final int updatedShortcutProbability = 2;
binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
updatedShortcutProbability, false /* isBeginningOfSentence */,
- false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
+ false /* isNotAWord */, false /* isPossiblyOffensive */, 0 /* timestamp */);
wordProperty = binaryDictionary.getWordProperty("aaa",
false /* isBeginningOfSentence */);
assertEquals(1, wordProperty.mShortcutTargets.size());
@@ -1210,7 +1066,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
wordProperty.mShortcutTargets.get(0).getProbability());
binaryDictionary.addUnigramEntry("aaa", unigramProbability, "yyy",
shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
+ false /* isPossiblyOffensive */, 0 /* timestamp */);
final HashMap<String, Integer> shortcutTargets = new HashMap<>();
shortcutTargets.put("zzz", updatedShortcutProbability);
shortcutTargets.put("yyy", shortcutProbability);
@@ -1254,16 +1110,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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 */);
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
for (int i = 0; i < UNIGRAM_COUNT; i++) {
final String word = CodePointUtils.generateWord(random, codePointSet);
@@ -1282,7 +1129,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final int unigramProbability = unigramProbabilities.get(word);
binaryDictionary.addUnigramEntry(word, unigramProbability, shortcutTarget,
shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
+ false /* isPossiblyOffensive */, 0 /* timestamp */);
if (shortcutTargets.containsKey(word)) {
final HashMap<String, Integer> shortcutTargetsOfWord = shortcutTargets.get(word);
shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
@@ -1314,6 +1161,15 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
}
+ public void testPossiblyOffensiveAttributeMaintained() {
+ final BinaryDictionary binaryDictionary =
+ getEmptyBinaryDictionary(FormatSpec.VERSION403);
+ binaryDictionary.addUnigramEntry("ddd", 100, null, Dictionary.NOT_A_PROBABILITY,
+ false, true, true, 0);
+ WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
+ assertEquals(true, wordProperty.mIsPossiblyOffensive);
+ }
+
public void testDictMigration() {
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
@@ -1321,15 +1177,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(fromFormatVersion);
final int unigramProbability = 100;
addUnigramWord(binaryDictionary, "aaa", unigramProbability);
addUnigramWord(binaryDictionary, "bbb", unigramProbability);
@@ -1338,11 +1186,11 @@ public class BinaryDictionaryTests extends AndroidTestCase {
final int shortcutProbability = 10;
binaryDictionary.addUnigramEntry("ccc", unigramProbability, "xxx", shortcutProbability,
false /* isBeginningOfSentence */, false /* isNotAWord */,
- false /* isBlacklisted */, 0 /* timestamp */);
+ false /* isPossiblyOffensive */, 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,
+ true /* isNotAWord */, true /* isPossiblyOffensive */, 0 /* timestamp */);
+ binaryDictionary.addNgramEntry(NgramContext.BEGINNING_OF_SENTENCE,
"aaa", bigramProbability, 0 /* timestamp */);
assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
@@ -1353,11 +1201,9 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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"));
- }
+ assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bbb"));
+ assertEquals(bigramProbability, binaryDictionary.getNgramProbability(
+ NgramContext.BEGINNING_OF_SENTENCE, "aaa"));
assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
WordProperty wordProperty = binaryDictionary.getWordProperty("ccc",
false /* isBeginningOfSentence */);
@@ -1365,7 +1211,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
wordProperty = binaryDictionary.getWordProperty("ddd",
false /* isBeginningOfSentence */);
- assertTrue(wordProperty.mIsBlacklistEntry);
+ assertTrue(wordProperty.mIsPossiblyOffensive);
assertTrue(wordProperty.mIsNotAWord);
}
@@ -1381,16 +1227,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
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 BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(fromFormatVersion);
final ArrayList<String> words = new ArrayList<>();
final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
@@ -1434,55 +1271,43 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals((int)unigramProbabilities.get(word), binaryDictionary.getFrequency(word));
}
assertEquals(unigramProbabilities.size(), Integer.parseInt(
- binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+ binaryDictionary.getPropertyForGettingStats(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));
- }
+ 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)));
+ binaryDictionary.getPropertyForGettingStats(BinaryDictionary.BIGRAM_COUNT_QUERY)));
}
public void testBeginningOfSentence() {
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
- if (supportsBeginningOfSentence(formatVersion)) {
- testBeginningOfSentence(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(formatVersion);
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"));
+ binaryDictionary.getNgramProbability(beginningOfSentenceContext, "bbb"));
}
public void testGetMaxFrequencyOfExactMatches() {
@@ -1492,15 +1317,7 @@ public class BinaryDictionaryTests extends AndroidTestCase {
}
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 */);
+ final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
addUnigramWord(binaryDictionary, "abc", 10);
addUnigramWord(binaryDictionary, "aBc", 15);
assertEquals(15, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 6e894decf..1c8a2f242 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);
@@ -42,7 +44,7 @@ public class BlueUnderlineTests extends InputTestsBase {
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/DictionaryFacilitatorLruCacheTests.java b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
new file mode 100644
index 000000000..3ad659a99
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
@@ -0,0 +1,81 @@
+/*
+ * 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 {
+ static final int MAX_CACHE_SIZE = 2;
+ static final int MAX_CACHE_SIZE_LARGE = 5;
+
+ public void testCacheSize() {
+ final DictionaryFacilitatorLruCache cache =
+ new DictionaryFacilitatorLruCache(getContext(), MAX_CACHE_SIZE, "");
+
+ assertEquals(0, cache.getCachedLocalesForTesting().size());
+ assertNotNull(cache.get(Locale.US));
+ assertEquals(1, cache.getCachedLocalesForTesting().size());
+ assertNotNull(cache.get(Locale.UK));
+ assertEquals(2, cache.getCachedLocalesForTesting().size());
+ assertNotNull(cache.get(Locale.FRENCH));
+ assertEquals(2, cache.getCachedLocalesForTesting().size());
+ cache.evictAll();
+ assertEquals(0, cache.getCachedLocalesForTesting().size());
+ }
+
+ public void testGetFacilitator() {
+ testGetFacilitator(new DictionaryFacilitatorLruCache(getContext(), MAX_CACHE_SIZE, ""));
+ testGetFacilitator(new DictionaryFacilitatorLruCache(
+ getContext(), MAX_CACHE_SIZE_LARGE, ""));
+ }
+
+ private static void testGetFacilitator(final DictionaryFacilitatorLruCache cache) {
+ final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
+ assertNotNull(dictionaryFacilitatorEnUs);
+ assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
+
+ final DictionaryFacilitator dictionaryFacilitatorFr = cache.get(Locale.FRENCH);
+ assertNotNull(dictionaryFacilitatorEnUs);
+ assertTrue(dictionaryFacilitatorFr.isForLocales(new Locale[] { Locale.FRENCH }));
+
+ final DictionaryFacilitator dictionaryFacilitatorDe = cache.get(Locale.GERMANY);
+ assertNotNull(dictionaryFacilitatorDe);
+ assertTrue(dictionaryFacilitatorDe.isForLocales(new Locale[] { Locale.GERMANY }));
+ }
+
+ public void testSetUseContactsDictionary() {
+ testSetUseContactsDictionary(new DictionaryFacilitatorLruCache(
+ getContext(), MAX_CACHE_SIZE, ""));
+ testSetUseContactsDictionary(new DictionaryFacilitatorLruCache(
+ getContext(), MAX_CACHE_SIZE_LARGE, ""));
+ }
+
+ private static void testSetUseContactsDictionary(final DictionaryFacilitatorLruCache cache) {
+ assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ cache.setUseContactsDictionary(true /* useContactsDictionary */);
+ assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ assertNotNull(cache.get(Locale.FRENCH).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ assertNotNull(cache.get(Locale.GERMANY).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ cache.setUseContactsDictionary(false /* useContactsDictionary */);
+ assertNull(cache.get(Locale.GERMANY).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
index 09309bcc0..07d7c3225 100644
--- a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
@@ -35,16 +35,20 @@ public class FusionDictionaryTests extends AndroidTestCase {
FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new DictionaryOptions(new HashMap<String,String>()));
- dict.add("abc", new ProbabilityInfo(10), null, false /* isNotAWord */);
+ dict.add("abc", new ProbabilityInfo(10), null, false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
- dict.add("aa", new ProbabilityInfo(10), null, false /* isNotAWord */);
+ dict.add("aa", new ProbabilityInfo(10), null, false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
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 */);
+ dict.add("babcd", new ProbabilityInfo(10), null, false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
+ dict.add("bacde", new ProbabilityInfo(10), null, false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
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..c76f6f446 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -16,10 +16,12 @@
package com.android.inputmethod.latin;
+import android.test.MoreAsserts;
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.settings.Settings;
@LargeTest
@@ -36,7 +38,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 +51,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 +65,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 +80,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 +95,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 +116,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,27 +156,45 @@ 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());
@@ -276,10 +298,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 +312,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());
@@ -394,7 +414,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()));
@@ -466,7 +486,7 @@ public class InputLogicTests extends InputTestsBase {
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();
@@ -478,17 +498,17 @@ 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();
// No need to test here, testPredictionsAfterSpace is testing it already
type(" ");
- sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
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 = mLatinIME.getSuggestedWordsForTest();
@@ -501,7 +521,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,13 +533,13 @@ 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);
+ sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
runMessages();
suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("Beginning-of-Sentence prediction after inputting 2 times.", "Barack",
@@ -535,27 +555,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 +619,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,7 +631,7 @@ 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,
@@ -631,10 +647,94 @@ public class InputLogicTests extends InputTestsBase {
changeLanguage("fr");
runMessages();
type(WORD_TO_TYPE_SECOND_PART);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ 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);
}
+
+ public void testBasicGesture() {
+ gesture("this");
+ assertEquals("gesture \"this\"", "this", mEditText.getText().toString());
+ }
+
+ public void testGestureGesture() {
+ gesture("this");
+ gesture("is");
+ assertEquals("gesture \"this is\"", "this is", mEditText.getText().toString());
+ }
+
+ public void testGestureBackspaceGestureAgain() {
+ gesture("this");
+ type(Constants.CODE_DELETE);
+ assertEquals("gesture then backspace", "", mEditText.getText().toString());
+ gesture("this");
+ MoreAsserts.assertNotEqual("gesture twice the same thing", "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();
+ ensureComposingSpanPos("move cursor inside word leaves composing span in the right place",
+ startPos, END_OF_WORD);
+ }
+
+ 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("space 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);
+ ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1);
+ }
}
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..6e6f551cc 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()));
@@ -91,7 +93,7 @@ public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
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
index 866f8894c..3cfd0e2a6 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
@@ -18,6 +18,9 @@ package com.android.inputmethod.latin;
import android.test.suitebuilder.annotation.LargeTest;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.settings.Settings;
+
@LargeTest
public class InputLogicTestsNonEnglish extends InputTestsBase {
final String NEXT_WORD_PREDICTION_OPTION = "next_word_prediction";
@@ -68,7 +71,7 @@ public class InputLogicTestsNonEnglish extends InputTestsBase {
try {
changeLanguage("fr");
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());
@@ -93,7 +96,7 @@ public class InputLogicTestsNonEnglish extends InputTestsBase {
try {
changeLanguage("fr");
type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
runMessages();
final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
assertEquals("type word then type space yields predictions for French",
@@ -121,4 +124,32 @@ public class InputLogicTestsNonEnglish extends InputTestsBase {
assertEquals("auto-correct with umlaut for German", EXPECTED_RESULT,
mEditText.getText().toString());
}
+
+ // Corresponds to InputLogicTests#testDoubleSpace
+ public void testDoubleSpaceHindi() {
+ changeLanguage("hi");
+ // 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) {
+ mEditText.setText("");
+ type(STRINGS_TO_TYPE[i]);
+ assertEquals("double space processing", EXPECTED_RESULTS[i],
+ mEditText.getText().toString());
+ }
+ }
+
+ // Corresponds to InputLogicTests#testCancelDoubleSpace
+ public void testCancelDoubleSpaceHindi() {
+ changeLanguage("hi");
+ 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());
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
index ab69c8592..1372514da 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
@@ -80,7 +80,6 @@ import android.util.Pair;
@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.
@@ -90,7 +89,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
// member is stored the string that should be in the text view after this
// key press.
- private static final Pair[][] TESTS = {
+ private static final Pair<?, ?>[][] TESTS = {
// Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
@@ -206,13 +205,12 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
*/
};
- @SuppressWarnings("unchecked")
- private void doMyanmarTest(final int testNumber, final Pair[] test) {
+ private void doMyanmarTest(final int testNumber, final Pair<?, ?>[] test) {
int stepNumber = 0;
- for (final Pair<int[], String> step : test) {
+ for (final Pair<?, ?> step : test) {
++stepNumber;
- final int[] input = step.first;
- final String expectedResult = step.second;
+ final int[] input = (int[]) step.first;
+ final String expectedResult = (String) step.second;
if (input.length > 1) {
mLatinIME.onTextInput(new String(input, 0, input.length));
} else {
@@ -226,7 +224,7 @@ public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
public void testMyanmarReordering() {
int testNumber = 0;
changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
- for (final Pair[] test : TESTS) {
+ 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("");
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 986fb1097..926a2d3e1 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,9 +37,14 @@ 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.StringUtils;
import com.android.inputmethod.latin.settings.DebugSettings;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.utils.LocaleUtils;
@@ -55,11 +61,17 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
private static final String DEFAULT_AUTO_CORRECTION_THRESHOLD = "1";
// 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;
+ 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;
private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
+ // 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;
@@ -182,6 +194,10 @@ 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);
@@ -207,7 +223,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();
}
@@ -236,7 +252,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 +279,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 +307,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 +387,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
false /* isAuxiliary */,
false /* overridesImplicitlyEnabledSubtype */,
0 /* id */);
- SubtypeSwitcher.getInstance().forceSubtype(subtype);
+ SubtypeSwitcher.forceSubtype(subtype);
mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
runMessages();
mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
@@ -347,7 +405,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
protected void pickSuggestionManually(final String suggestion) {
mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion, 1,
- SuggestedWordInfo.KIND_CORRECTION, null /* sourceDict */,
+ SuggestedWordInfo.KIND_CORRECTION, DICTIONARY_TEST,
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
@@ -358,4 +416,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..ab1819d0b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
@@ -0,0 +1,67 @@
+/*
+ * 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 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));
+ }
+}
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..bcf016ae9 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).isNthPrevWordBeginningOfSontence(2));
// The following tests reflect the current behavior of the function
// RichInputConnection#getNthPreviousWord.
@@ -186,33 +185,33 @@ 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);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc? def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc! def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
+ assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+ "abc 'def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
}
public void testGetWordRangeAtCursor() {
@@ -223,7 +222,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/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..90db75e39 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -59,42 +59,8 @@ public class SuggestedWordsTests extends AndroidTestCase {
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)));
- }
-
- 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));
- }
-
// 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 =
@@ -141,13 +107,18 @@ public class SuggestedWordsTests extends AndroidTestCase {
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 */,
+ false /* typedWordValid */,
+ false /* willAutoCorrect */,
+ false /* isObsoleteSuggestions */,
+ SuggestedWords.INPUT_STYLE_NONE);
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 */,
@@ -157,6 +128,6 @@ public class SuggestedWordsTests extends AndroidTestCase {
SuggestedWords.INPUT_STYLE_NONE);
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..20256e670 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.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.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/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 406046a74..d239f8dac 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -23,6 +23,7 @@ import android.util.Pair;
import android.util.SparseArray;
import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.common.CodePointUtils;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
@@ -117,7 +118,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
super.tearDown();
}
- private void generateWords(final int number, final Random random) {
+ private static 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<>();
@@ -138,7 +139,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
/**
* Adds unigrams to the dictionary.
*/
- private void addUnigrams(final int number, final FusionDictionary dict,
+ private static 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);
@@ -149,11 +150,12 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
}
dict.add(word, new ProbabilityInfo(UNIGRAM_FREQ),
- (shortcutMap == null) ? null : shortcuts, false /* isNotAWord */);
+ (shortcutMap == null) ? null : shortcuts, false /* isNotAWord */,
+ false /* isPossiblyOffensive */);
}
}
- private void addBigrams(final FusionDictionary dict,
+ private static void addBigrams(final FusionDictionary dict,
final List<String> words,
final SparseArray<List<Integer>> bigrams) {
for (int i = 0; i < bigrams.size(); ++i) {
@@ -172,7 +174,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
// new java.io.FileWriter(new File(filename)), dict);
// }
- private long timeWritingDictToFile(final File file, final FusionDictionary dict,
+ private static long timeWritingDictToFile(final File file, final FusionDictionary dict,
final FormatSpec.FormatOptions formatOptions) {
long now = -1, diff = -1;
@@ -195,7 +197,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
return diff;
}
- private void checkDictionary(final FusionDictionary dict, final List<String> words,
+ private static void checkDictionary(final FusionDictionary dict, final List<String> words,
final SparseArray<List<Integer>> bigrams,
final HashMap<String, List<String>> shortcutMap) {
assertNotNull(dict);
@@ -230,16 +232,16 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
}
- private String outputOptions(final int bufferType,
+ private static String outputOptions(final int bufferType,
final FormatSpec.FormatOptions formatOptions) {
- String result = " : buffer type = "
+ final 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,
+ private static 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;
@@ -304,6 +306,40 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
"unigram with various code points"));
}
+ public void testCharacterTableIsPresent() throws IOException, UnsupportedFormatException {
+ final String[] wordSource = {"words", "used", "for", "testing", "a", "code point", "table"};
+ final List<String> words = Arrays.asList(wordSource);
+ final String correctCodePointTable = "toesdrniawuplgfcb ";
+ final String dictName = "codePointTableTest";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+ final String codePointTableAttribute = DictionaryHeader.CODE_POINT_TABLE_KEY;
+ final File file = BinaryDictUtils.getDictFile(dictName, dictVersion,
+ BinaryDictUtils.STATIC_OPTIONS, getContext().getCacheDir());
+
+ // Write a test dictionary
+ final DictEncoder dictEncoder = new Ver2DictEncoder(file,
+ Ver2DictEncoder.CODE_POINT_TABLE_ON);
+ final FormatSpec.FormatOptions formatOptions =
+ new FormatSpec.FormatOptions(
+ FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION);
+ final FusionDictionary sourcedict = new FusionDictionary(new PtNodeArray(),
+ BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
+ addUnigrams(words.size(), sourcedict, words, null /* shortcutMap */);
+ dictEncoder.writeDictionary(sourcedict, formatOptions);
+
+ // Read the dictionary
+ final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
+ DictDecoder.USE_BYTEARRAY);
+ final DictionaryHeader fileHeader = dictDecoder.readHeader();
+ // Check if codePointTable is present
+ assertTrue("codePointTable is not present",
+ fileHeader.mDictionaryOptions.mAttributes.containsKey(codePointTableAttribute));
+ final String codePointTable =
+ fileHeader.mDictionaryOptions.mAttributes.get(codePointTableAttribute);
+ // Check if codePointTable is correct
+ assertEquals("codePointTable is incorrect", codePointTable, correctCodePointTable);
+ }
+
// Unit test for CharEncoding.readString and CharEncoding.writeString.
public void testCharEncoding() {
// the max length of a word in sWords is less than 50.
@@ -312,7 +348,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final DictBuffer dictBuffer = new ByteArrayDictBuffer(buffer);
for (final String word : sWords) {
Arrays.fill(buffer, (byte) 0);
- CharEncoding.writeString(buffer, 0, word);
+ CharEncoding.writeString(buffer, 0, word, null);
dictBuffer.position(0);
final String str = CharEncoding.readString(dictBuffer);
assertEquals(word, str);
@@ -323,11 +359,11 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final List<String> results = new ArrayList<>();
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
+ BinaryDictUtils.DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP);
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
+ BinaryDictUtils.DYNAMIC_OPTIONS_WITH_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
}
@@ -337,11 +373,11 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final List<String> results = new ArrayList<>();
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
+ BinaryDictUtils.DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP);
runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
+ BinaryDictUtils.DYNAMIC_OPTIONS_WITH_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -350,7 +386,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
// Tests for readUnigramsAndBigramsBinary
- private void checkWordMap(final List<String> expectedWords,
+ private static void checkWordMap(final List<String> expectedWords,
final SparseArray<List<Integer>> expectedBigrams,
final TreeMap<Integer, String> resultWords,
final TreeMap<Integer, Integer> resultFrequencies,
@@ -399,9 +435,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
assertEquals(actBigrams, expBigrams);
}
- private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final int bufferType,
- final boolean checkProbability) {
+ private static 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<>();
@@ -465,7 +501,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final ArrayList<String> results = new ArrayList<>();
runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
for (final String result : results) {
Log.d(TAG, result);
@@ -476,7 +512,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final ArrayList<String> results = new ArrayList<>();
runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
for (final String result : results) {
Log.d(TAG, result);
@@ -484,7 +520,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
// Tests for getTerminalPosition
- private String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
+ private static String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
DictionaryHeader fileHeader = null;
@@ -500,7 +536,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
address).mWord;
}
- private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
+ private static long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
final boolean contained) {
long diff = -1;
int position = -1;
@@ -587,9 +623,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final ArrayList<String> results = new ArrayList<>();
runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
- BinaryDictUtils.VERSION2_OPTIONS);
+ BinaryDictUtils.STATIC_OPTIONS);
for (final String result : results) {
Log.d(TAG, result);
@@ -597,7 +633,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
public void testVer2DictGetWordProperty() {
- final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
+ final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS;
final ArrayList<String> words = sWords;
final HashMap<String, List<String>> shortcuts = sShortcuts;
final String dictName = "testGetWordProperty";
@@ -633,7 +669,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
public void testVer2DictIteration() {
- final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
+ final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS;
final ArrayList<String> words = sWords;
final HashMap<String, List<String>> shortcuts = sShortcuts;
final SparseArray<List<Integer>> bigrams = sEmptyBigrams;
@@ -682,11 +718,13 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
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);
+ if (wordProperty.mHasNgrams) {
+ for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+ final String word1 = bigramTarget.mWord;
+ final Pair<String, String> bigram = new Pair<>(word0, word1);
+ assertTrue(bigramSet.contains(bigram));
+ bigramSet.remove(bigram);
+ }
}
token = result.mNextToken;
} while (token != 0);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 96604a197..120b96bc6 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -17,11 +17,11 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
-
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.HashMap;
/**
* Decodes binary files for a FusionDictionary.
@@ -109,15 +109,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 +142,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 +153,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 +165,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 +200,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 +233,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 +277,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 +295,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();
}
/**
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index eabd8d722..ce905c499 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -27,6 +27,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 +61,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 +77,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);
}
/**
@@ -90,13 +94,14 @@ public class BinaryDictEncoderUtils {
/**
* Compute the size of a shortcut in bytes.
*/
- private static int getShortcutSize(final WeightedString shortcut) {
+ private static int getShortcutSize(final WeightedString shortcut,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
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 += CharEncoding.getCharSize(codePoint, codePointToOneByteCodeMap);
}
size += FormatSpec.PTNODE_TERMINATOR_SIZE;
return size;
@@ -108,11 +113,12 @@ public class BinaryDictEncoderUtils {
* 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) {
+ static int getShortcutListSize(final ArrayList<WeightedString> shortcutList,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
if (null == shortcutList || shortcutList.isEmpty()) return 0;
int size = FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
for (final WeightedString shortcut : shortcutList) {
- size += getShortcutSize(shortcut);
+ size += getShortcutSize(shortcut, codePointToOneByteCodeMap);
}
return size;
}
@@ -123,14 +129,16 @@ public class BinaryDictEncoderUtils {
* @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);
+ // TODO: Use codePointToOneByteCodeMap for shortcuts.
+ size += getShortcutListSize(ptNode.mShortcutTargets, null /* codePointToOneByteCodeMap */);
if (null != ptNode.mBigrams) {
size += (FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE
+ FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE)
@@ -146,10 +154,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 +170,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 +199,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);
@@ -313,11 +325,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 +355,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 +374,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 +383,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 +391,9 @@ public class BinaryDictEncoderUtils {
nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
nodeSize + size, ptNode.mChildren));
}
- nodeSize += getShortcutListSize(ptNode.mShortcutTargets);
+ // TODO: Use codePointToOneByteCodeMap for shortcuts.
+ nodeSize += getShortcutListSize(ptNode.mShortcutTargets,
+ null /* codePointToOneByteCodeMap */);
if (null != ptNode.mBigrams) {
for (WeightedString bigram : ptNode.mBigrams) {
final int offset = getOffsetToTargetPtNodeDuringUpdate(ptNodeArray,
@@ -452,10 +464,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 +483,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 +535,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,28 +563,6 @@ 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.
@@ -578,12 +571,12 @@ public class BinaryDictEncoderUtils {
* @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 boolean isNotAWord, final boolean isPossiblyOffensive) {
byte flags = 0;
if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
if (isTerminal) flags |= FormatSpec.FLAG_IS_TERMINAL;
@@ -606,7 +599,7 @@ public class BinaryDictEncoderUtils {
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;
}
@@ -615,7 +608,7 @@ public class BinaryDictEncoderUtils {
getByteSize(childrenOffset),
node.mShortcutTargets != null && !node.mShortcutTargets.isEmpty(),
node.mBigrams != null && !node.mBigrams.isEmpty(),
- node.mIsNotAWord, node.mIsBlacklistEntry);
+ node.mIsNotAWord, node.mIsPossiblyOffensive);
}
/**
@@ -629,7 +622,7 @@ public class BinaryDictEncoderUtils {
* @return the flags
*/
/* package */ static final int makeBigramFlags(final boolean more, final int offset,
- int bigramFrequency, final int unigramFrequency, final String word) {
+ 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 +638,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;
}
@@ -706,9 +702,10 @@ public class BinaryDictEncoderUtils {
+ (frequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY);
}
- /* package */ static final int getChildrenPosition(final PtNode ptNode) {
+ /* package */ static final 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 +722,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 +745,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 +811,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 +858,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 +880,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..b104a21f9 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.common.Constants;
import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
import java.io.File;
@@ -44,7 +44,7 @@ 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);
+ return new Ver4DictDecoder(dictFile);
} else if (dictFile.isFile()) {
return new Ver2DictDecoder(dictFile, offset, length, bufferType);
}
@@ -54,7 +54,7 @@ public final class BinaryDictIOUtils {
public static DictDecoder getDictDecoder(final File dictFile, final long offset,
final long length, final DictionaryBufferFactory factory) {
if (dictFile.isDirectory()) {
- return new Ver4DictDecoder(dictFile, factory);
+ return new Ver4DictDecoder(dictFile);
} else if (dictFile.isFile()) {
return new Ver2DictDecoder(dictFile, offset, length, factory);
}
@@ -206,11 +206,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
index 5a3eba801..9c1e4cf84 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
@@ -28,11 +28,11 @@ public class BinaryDictUtils {
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 =
+ public static final FormatSpec.FormatOptions STATIC_OPTIONS =
+ new FormatSpec.FormatOptions(FormatSpec.VERSION202);
+ public static final FormatSpec.FormatOptions DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP =
new FormatSpec.FormatOptions(FormatSpec.VERSION4, false /* hasTimestamp */);
- public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITH_TIMESTAMP =
+ public static final FormatSpec.FormatOptions DYNAMIC_OPTIONS_WITH_TIMESTAMP =
new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* hasTimestamp */);
public static DictionaryOptions makeDictionaryOptions(final String id, final String version,
@@ -52,7 +52,9 @@ public class BinaryDictUtils {
public static File getDictFile(final String name, final String version,
final FormatOptions formatOptions, final File directory) {
- if (formatOptions.mVersion == FormatSpec.VERSION2) {
+ if (formatOptions.mVersion == FormatSpec.VERSION2
+ || formatOptions.mVersion == FormatSpec.VERSION201
+ || formatOptions.mVersion == FormatSpec.VERSION202) {
return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION);
} else if (formatOptions.mVersion == FormatSpec.VERSION4) {
return new File(directory, name + "." + version);
@@ -68,8 +70,8 @@ public class BinaryDictUtils {
file.mkdir();
}
return new Ver4DictEncoder(file);
- } else if (formatOptions.mVersion == FormatSpec.VERSION2) {
- return new Ver2DictEncoder(file);
+ } else if (formatOptions.mVersion == FormatSpec.VERSION202) {
+ return new Ver2DictEncoder(file, Ver2DictEncoder.CODE_POINT_TABLE_OFF);
} 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..3cffd001c 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.common.Constants;
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
import java.util.ArrayList;
@@ -89,7 +89,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
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
@@ -102,7 +102,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
- final boolean isNotAWord, final boolean isBlacklistEntry) {
+ final boolean isNotAWord, final boolean isPossiblyOffensive) {
mChars = chars;
mProbabilityInfo = probabilityInfo;
mTerminalId = probabilityInfo == null ? NOT_A_TERMINAL : probabilityInfo.mProbability;
@@ -110,12 +110,12 @@ public final class FusionDictionary implements Iterable<WordProperty> {
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 boolean isNotAWord, final boolean isPossiblyOffensive,
final PtNodeArray children) {
mChars = chars;
mProbabilityInfo = probabilityInfo;
@@ -123,7 +123,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
mBigrams = bigrams;
mChildren = children;
mIsNotAWord = isNotAWord;
- mIsBlacklistEntry = isBlacklistEntry;
+ mIsPossiblyOffensive = isPossiblyOffensive;
}
public void addChild(PtNode n) {
@@ -142,19 +142,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 boolean getIsPossiblyOffensive() {
+ return mIsPossiblyOffensive;
}
public ArrayList<WeightedString> getShortcutTargets() {
@@ -235,10 +231,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,
+ void update(final ProbabilityInfo probabilityInfo,
final ArrayList<WeightedString> shortcutTargets,
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) {
@@ -275,7 +271,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
}
}
mIsNotAWord = isNotAWord;
- mIsBlacklistEntry = isBlacklistEntry;
+ mIsPossiblyOffensive = isPossiblyOffensive;
}
}
@@ -323,24 +319,12 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* @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 ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord,
+ final boolean isPossiblyOffensive) {
+ add(getCodePoints(word), probabilityInfo, shortcutTargets, isNotAWord, isPossiblyOffensive);
}
/**
@@ -349,15 +333,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;
}
}
@@ -375,7 +359,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
final PtNode ptNode1 = findWordInTree(mRootNodeArray, word1);
if (ptNode1 == null) {
add(getCodePoints(word1), new ProbabilityInfo(0), null, false /* isNotAWord */,
- false /* isBlacklistEntry */);
+ 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.
@@ -397,11 +381,11 @@ public final class FusionDictionary implements Iterable<WordProperty> {
* @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) {
MakedictLog.w("Ignoring a word that is too long: word.length = " + word.length);
@@ -431,7 +415,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
final int insertionIndex = findInsertionIndex(currentNodeArray, word[charIndex]);
final PtNode newPtNode = new PtNode(Arrays.copyOfRange(word, charIndex, word.length),
shortcutTargets, null /* bigrams */, probabilityInfo, isNotAWord,
- isBlacklistEntry);
+ isPossiblyOffensive);
currentNodeArray.mData.add(insertionIndex, newPtNode);
if (DBG) checkStack(currentNodeArray);
} else {
@@ -442,14 +426,14 @@ public final class FusionDictionary implements Iterable<WordProperty> {
// 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);
+ 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);
+ isNotAWord, isPossiblyOffensive);
currentPtNode.mChildren = new PtNodeArray();
currentPtNode.mChildren.mData.add(newNode);
}
@@ -459,7 +443,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
// new shortcuts to the existing shortcut list if it already exists.
currentPtNode.update(probabilityInfo, shortcutTargets, 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.
@@ -468,7 +452,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
Arrays.copyOfRange(currentPtNode.mChars, differentCharIndex,
currentPtNode.mChars.length), currentPtNode.mShortcutTargets,
currentPtNode.mBigrams, currentPtNode.mProbabilityInfo,
- currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry,
+ currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive,
currentPtNode.mChildren);
newChildren.mData.add(newOldWord);
@@ -477,17 +461,17 @@ public final class FusionDictionary implements Iterable<WordProperty> {
newParent = new PtNode(
Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
shortcutTargets, null /* bigrams */, probabilityInfo,
- isNotAWord, isBlacklistEntry, newChildren);
+ isNotAWord, isPossiblyOffensive, newChildren);
} else {
newParent = new PtNode(
Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
null /* shortcutTargets */, null /* bigrams */,
null /* probabilityInfo */, false /* isNotAWord */,
- false /* isBlacklistEntry */, newChildren);
+ false /* isPossiblyOffensive */, newChildren);
final PtNode newWord = new PtNode(Arrays.copyOfRange(word,
charIndex + differentCharIndex, word.length),
shortcutTargets, null /* bigrams */, probabilityInfo,
- isNotAWord, isBlacklistEntry);
+ isNotAWord, isPossiblyOffensive);
final int addIndex = word[charIndex + differentCharIndex]
> currentPtNode.mChars[differentCharIndex] ? 1 : 0;
newChildren.mData.add(addIndex, newWord);
@@ -533,14 +517,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.
@@ -549,7 +533,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
final ArrayList<PtNode> data = nodeArray.mData;
final PtNode reference = new PtNode(new int[] { character },
null /* shortcutTargets */, null /* bigrams */, null /* probabilityInfo */,
- false /* isNotAWord */, false /* isBlacklistEntry */);
+ false /* isNotAWord */, false /* isPossiblyOffensive */);
int result = Collections.binarySearch(data, reference, PTNODE_COMPARATOR);
return result >= 0 ? result : -result - 1;
}
@@ -571,7 +555,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);
@@ -686,7 +671,7 @@ public final class FusionDictionary implements Iterable<WordProperty> {
return new WordProperty(mCurrentString.toString(),
currentPtNode.mProbabilityInfo,
currentPtNode.mShortcutTargets, currentPtNode.mBigrams,
- currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry);
+ 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
index 65b84d5f7..5c261a94d 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
@@ -36,17 +36,17 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
/**
* A utility class for reading a PtNode.
*/
- protected static class PtNodeReader {
- private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
+ static class PtNodeReader {
+ 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) {
+ static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
return dictBuffer.readUnsignedByte();
}
- protected static int readChildrenAddress(final DictBuffer dictBuffer,
+ static int readChildrenAddress(final DictBuffer dictBuffer,
final int ptNodeFlags) {
switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
@@ -62,7 +62,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
}
// Reads shortcuts and returns the read length.
- protected static int readShortcut(final DictBuffer dictBuffer,
+ static int readShortcut(final DictBuffer dictBuffer,
final ArrayList<WeightedString> shortcutTargets) {
final int pointerBefore = dictBuffer.position();
dictBuffer.readUnsignedShort(); // skip the size
@@ -76,7 +76,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
return dictBuffer.position() - pointerBefore;
}
- protected static int readBigramAddresses(final DictBuffer dictBuffer,
+ static int readBigramAddresses(final DictBuffer dictBuffer,
final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
int readLength = 0;
int bigramCount = 0;
@@ -177,7 +177,9 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
if (header == null) {
throw new IOException("Cannot read the dictionary header.");
}
- if (header.mFormatOptions.mVersion != FormatSpec.VERSION2) {
+ if (header.mFormatOptions.mVersion != FormatSpec.VERSION2 &&
+ header.mFormatOptions.mVersion != FormatSpec.VERSION201 &&
+ header.mFormatOptions.mVersion != FormatSpec.VERSION202) {
throw new UnsupportedFormatException("File header has a wrong version : "
+ header.mFormatOptions.mVersion);
}
@@ -200,19 +202,19 @@ public class Ver2DictDecoder extends AbstractDictDecoder {
if (0 != (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS)) {
int index = 0;
int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
+ addressPointer += CharEncoding.getCharSize(character, null);
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);
+ addressPointer += CharEncoding.getCharSize(character, null);
}
characters = Arrays.copyOfRange(mCharacterBuffer, 0, index);
} else {
final int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
+ addressPointer += CharEncoding.getCharSize(character, null);
characters = new int[] { character };
}
final ProbabilityInfo probabilityInfo;
@@ -282,21 +284,17 @@ public class Ver2DictDecoder 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.mShortcutTargets, wordProperty.mIsNotAWord,
+ wordProperty.mIsPossiblyOffensive);
}
// Insert bigrams into the fusion dictionary.
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/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
index a286190cb..b52b8c485 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
@@ -18,6 +18,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.BinaryDictEncoderUtils.CodePointTable;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
@@ -28,7 +29,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map.Entry;
/**
* An implementation of DictEncoder for version 2 binary dictionary.
@@ -40,12 +45,16 @@ public class Ver2DictEncoder implements DictEncoder {
private OutputStream mOutStream;
private byte[] mBuffer;
private int mPosition;
+ private final int mCodePointTableMode;
+ public static final int CODE_POINT_TABLE_OFF = 0;
+ public static final int CODE_POINT_TABLE_ON = 1;
@UsedForTesting
- public Ver2DictEncoder(final File dictFile) {
+ public Ver2DictEncoder(final File dictFile, final int codePointTableMode) {
mDictFile = dictFile;
mOutStream = null;
mBuffer = null;
+ mCodePointTableMode = codePointTableMode;
}
// This constructor is used only by BinaryDictOffdeviceUtilsTests.
@@ -55,6 +64,7 @@ public class Ver2DictEncoder implements DictEncoder {
public Ver2DictEncoder(final OutputStream outStream) {
mDictFile = null;
mOutStream = outStream;
+ mCodePointTableMode = CODE_POINT_TABLE_OFF;
}
private void openStream() throws FileNotFoundException {
@@ -68,10 +78,54 @@ public class Ver2DictEncoder implements DictEncoder {
}
}
+ // Package for testing
+ static CodePointTable makeCodePointTable(final FusionDictionary dict) {
+ final HashMap<Integer, Integer> codePointOccurrenceCounts = new HashMap<>();
+ for (final WordProperty word : dict) {
+ // Store per code point occurrence
+ final String wordString = word.mWord;
+ for (int i = 0; i < wordString.length(); ++i) {
+ final int codePoint = Character.codePointAt(wordString, i);
+ if (codePointOccurrenceCounts.containsKey(codePoint)) {
+ codePointOccurrenceCounts.put(codePoint,
+ codePointOccurrenceCounts.get(codePoint) + 1);
+ } else {
+ codePointOccurrenceCounts.put(codePoint, 1);
+ }
+ }
+ }
+ final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray =
+ new ArrayList<>(codePointOccurrenceCounts.entrySet());
+ // Descending order sort by occurrence (value side)
+ Collections.sort(codePointOccurrenceArray, new Comparator<Entry<Integer, Integer>>() {
+ @Override
+ public int compare(final Entry<Integer, Integer> a, final Entry<Integer, Integer> b) {
+ if (a.getValue() != b.getValue()) {
+ return b.getValue().compareTo(a.getValue());
+ }
+ return b.getKey().compareTo(a.getKey());
+ }
+ });
+ int currentCodePointTableIndex = FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE;
+ // Temporary map for writing of nodes
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap = new HashMap<>();
+ for (final Entry<Integer, Integer> entry : codePointOccurrenceArray) {
+ // Put a relation from the original code point to the one byte code.
+ codePointToOneByteCodeMap.put(entry.getKey(), currentCodePointTableIndex);
+ if (FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE < ++currentCodePointTableIndex) {
+ break;
+ }
+ }
+ // codePointToOneByteCodeMap for writing the trie
+ // codePointOccurrenceArray for writing the header
+ return new CodePointTable(codePointToOneByteCodeMap, codePointOccurrenceArray);
+ }
+
@Override
public void writeDictionary(final FusionDictionary dict, final FormatOptions formatOptions)
throws IOException, UnsupportedFormatException {
- if (formatOptions.mVersion > FormatSpec.VERSION2) {
+ // We no longer support anything but the latest version of v2.
+ if (formatOptions.mVersion != FormatSpec.VERSION202) {
throw new UnsupportedFormatException(
"The given format options has wrong version number : "
+ formatOptions.mVersion);
@@ -80,7 +134,19 @@ public class Ver2DictEncoder implements DictEncoder {
if (mOutStream == null) {
openStream();
}
- BinaryDictEncoderUtils.writeDictionaryHeader(mOutStream, dict, formatOptions);
+
+ // Make code point conversion table ordered by occurrence of code points
+ // Version 201 or later have codePointTable
+ final CodePointTable codePointTable;
+ if (mCodePointTableMode == CODE_POINT_TABLE_OFF || formatOptions.mVersion
+ < FormatSpec.MINIMUM_SUPPORTED_VERSION_OF_CODE_POINT_TABLE) {
+ codePointTable = new CodePointTable();
+ } else {
+ codePointTable = makeCodePointTable(dict);
+ }
+
+ BinaryDictEncoderUtils.writeDictionaryHeader(mOutStream, dict, formatOptions,
+ codePointTable.mCodePointOccurrenceArray);
// 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
@@ -94,7 +160,8 @@ public class Ver2DictEncoder implements DictEncoder {
ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
MakedictLog.i("Computing addresses...");
- BinaryDictEncoderUtils.computeAddresses(dict, flatNodes);
+ BinaryDictEncoderUtils.computeAddresses(dict, flatNodes,
+ codePointTable.mCodePointToOneByteCodeMap);
MakedictLog.i("Checking PtNode array...");
if (MakedictLog.DBG) BinaryDictEncoderUtils.checkFlatPtNodeArrayList(flatNodes);
@@ -106,7 +173,8 @@ public class Ver2DictEncoder implements DictEncoder {
MakedictLog.i("Writing file...");
for (PtNodeArray nodeArray : flatNodes) {
- BinaryDictEncoderUtils.writePlacedPtNodeArray(dict, this, nodeArray);
+ BinaryDictEncoderUtils.writePlacedPtNodeArray(dict, this, nodeArray,
+ codePointTable.mCodePointToOneByteCodeMap);
}
if (MakedictLog.DBG) BinaryDictEncoderUtils.showStatistics(flatNodes);
mOutStream.write(mBuffer, 0, mPosition);
@@ -138,15 +206,19 @@ public class Ver2DictEncoder implements DictEncoder {
countSize);
}
- private void writePtNodeFlags(final PtNode ptNode) {
- final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
+ private void writePtNodeFlags(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode,
+ codePointToOneByteCodeMap);
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);
+ private void writeCharacters(final int[] codePoints, final boolean hasSeveralChars,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ mPosition = CharEncoding.writeCharArray(codePoints, mBuffer, mPosition,
+ codePointToOneByteCodeMap);
if (hasSeveralChars) {
mBuffer[mPosition++] = FormatSpec.PTNODE_CHARACTERS_TERMINATOR;
}
@@ -159,8 +231,10 @@ public class Ver2DictEncoder implements DictEncoder {
}
}
- private void writeChildrenPosition(final PtNode ptNode) {
- final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
+ private void writeChildrenPosition(final PtNode ptNode,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode,
+ codePointToOneByteCodeMap);
mPosition += BinaryDictEncoderUtils.writeChildrenPosition(mBuffer, mPosition,
childrenPos);
}
@@ -170,7 +244,8 @@ public class Ver2DictEncoder implements DictEncoder {
*
* @param shortcuts the shortcut attributes list.
*/
- private void writeShortcuts(final ArrayList<WeightedString> shortcuts) {
+ private void writeShortcuts(final ArrayList<WeightedString> shortcuts,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
if (null == shortcuts || shortcuts.isEmpty()) return;
final int indexOfShortcutByteSize = mPosition;
@@ -183,7 +258,8 @@ public class Ver2DictEncoder implements DictEncoder {
target.getProbability());
mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, shortcutFlags,
FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
- final int shortcutShift = CharEncoding.writeString(mBuffer, mPosition, target.mWord);
+ final int shortcutShift = CharEncoding.writeString(mBuffer, mPosition, target.mWord,
+ codePointToOneByteCodeMap);
mPosition += shortcutShift;
}
final int shortcutByteSize = mPosition - indexOfShortcutByteSize;
@@ -223,18 +299,14 @@ public class Ver2DictEncoder implements DictEncoder {
}
@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());
+ public void writePtNode(final PtNode ptNode, final FusionDictionary dict,
+ final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+ writePtNodeFlags(ptNode, codePointToOneByteCodeMap);
+ writeCharacters(ptNode.mChars, ptNode.hasSeveralChars(), codePointToOneByteCodeMap);
writeFrequency(ptNode.getProbability());
- writeChildrenPosition(ptNode);
- writeShortcuts(ptNode.mShortcutTargets);
+ writeChildrenPosition(ptNode, codePointToOneByteCodeMap);
+ // TODO: Use codePointToOneByteCodeMap for shortcuts.
+ writeShortcuts(ptNode.mShortcutTargets, null /* codePointToOneByteCodeMap */);
writeBigrams(ptNode.mBigrams, dict);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
new file mode 100644
index 000000000..7d858760e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoderTests.java
@@ -0,0 +1,90 @@
+/*
+ * 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.makedict;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import com.android.inputmethod.latin.makedict.BinaryDictEncoderUtils.CodePointTable;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit tests for Ver2DictEncoder
+ */
+@LargeTest
+public class Ver2DictEncoderTests extends AndroidTestCase {
+ private static final int UNIGRAM_FREQ = 10;
+
+ public void testCodePointTable() {
+ final String[] wordSource = {"words", "used", "for", "testing", "a", "code point", "table"};
+ final List<String> words = Arrays.asList(wordSource);
+ final String correctCodePointTable = "eotdsanirfg bclwup";
+ final String correctCodePointOccurrenceArrayString =
+ "11641114101411531003114211021052972119111711121108110311021991981321";
+ final String correctCodePointExpectedMapString = "343332363540383937464549484744414243";
+ final String dictName = "codePointTableTest";
+ final String dictVersion = Long.toString(System.currentTimeMillis());
+
+ final FormatSpec.FormatOptions formatOptions =
+ new FormatSpec.FormatOptions(FormatSpec.VERSION2);
+ final FusionDictionary sourcedict = new FusionDictionary(new PtNodeArray(),
+ BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
+ addUnigrams(sourcedict, words, null /* shortcutMap */);
+ final CodePointTable codePointTable = Ver2DictEncoder.makeCodePointTable(sourcedict);
+
+ // Check if mCodePointOccurrenceArray is correct
+ final StringBuilder codePointOccurrenceArrayString = new StringBuilder();
+ for (Entry<Integer, Integer> entry : codePointTable.mCodePointOccurrenceArray) {
+ codePointOccurrenceArrayString.append(entry.getKey());
+ codePointOccurrenceArrayString.append(entry.getValue());
+ }
+ assertEquals(correctCodePointOccurrenceArrayString,
+ codePointOccurrenceArrayString.toString());
+
+ // Check if mCodePointToOneByteCodeMap is correct
+ final StringBuilder codePointExpectedMapString = new StringBuilder();
+ for (int i = 0; i < correctCodePointTable.length(); ++i) {
+ codePointExpectedMapString.append(codePointTable.mCodePointToOneByteCodeMap.get(
+ correctCodePointTable.codePointAt(i)));
+ }
+ assertEquals(correctCodePointExpectedMapString, codePointExpectedMapString.toString());
+ }
+
+ /**
+ * Adds unigrams to the dictionary.
+ */
+ private static void addUnigrams(final FusionDictionary dict, final List<String> words,
+ final HashMap<String, List<String>> shortcutMap) {
+ for (final String word : words) {
+ 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 */,
+ false /* isPossiblyOffensive */);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 5e8417ed6..7e54ce986 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -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.mShortcutTargets, 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
index 76eaef431..155421922 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -19,7 +19,7 @@ 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.NgramContext;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
@@ -27,6 +27,7 @@ import com.android.inputmethod.latin.utils.LocaleUtils;
import java.io.File;
import java.io.IOException;
+import java.util.HashMap;
/**
* An implementation of DictEncoder for version 4 binary dictionary.
@@ -78,7 +79,7 @@ public class Ver4DictEncoder implements DictEncoder {
if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
null /* shortcutTarget */, 0 /* shortcutProbability */,
wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
- wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
+ wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
}
} else {
@@ -87,7 +88,7 @@ public class Ver4DictEncoder implements DictEncoder {
wordProperty.getProbability(),
shortcutTarget.mWord, shortcutTarget.getProbability(),
wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
- wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
+ wordProperty.mIsPossiblyOffensive, 0 /* timestamp */)) {
MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord
+ ", shortcutTarget: " + shortcutTarget.mWord);
return;
@@ -102,14 +103,15 @@ public class Ver4DictEncoder implements DictEncoder {
}
}
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,
+ if (!word0Property.mHasNgrams) continue;
+ // TODO: Support ngram.
+ for (final WeightedString word1 : word0Property.getBigrams()) {
+ final NgramContext ngramContext =
+ new NgramContext(new NgramContext.WordInfo(word0Property.mWord));
+ if (!binaryDict.addNgramEntry(ngramContext, word1.mWord,
word1.getProbability(), 0 /* timestamp */)) {
MakedictLog.e("Cannot add n-gram entry for "
- + prevWordsInfo + " -> " + word1.mWord);
+ + ngramContext + " -> " + word1.mWord);
return;
}
if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
@@ -141,10 +143,7 @@ public class Ver4DictEncoder implements DictEncoder {
}
@Override
- public void writeForwardLinkAddress(int forwardLinkAddress) {
- }
-
- @Override
- public void writePtNode(PtNode ptNode, FusionDictionary dict) {
+ public void writePtNode(PtNode ptNode, FusionDictionary dict,
+ HashMap<Integer, Integer> codePointToOneByteCodeMap) {
}
}
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
index 565fadb2a..f07dac7c0 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
@@ -34,16 +34,15 @@ import android.test.suitebuilder.annotation.LargeTest;
*/
@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>>());
+ dictionaryFacilitator.resetDictionariesForTesting(getContext(),
+ new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
+ new HashMap<String, Map<String, String>>());
return dictionaryFacilitator;
}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
index 0f2f9814b..dc6fb0075 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
@@ -29,13 +29,15 @@ 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.RichInputMethodManager;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback;
+import com.android.inputmethod.latin.common.CodePointUtils;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
/**
* Unit tests for personalization dictionary
@@ -52,19 +54,32 @@ public class PersonalizationDictionaryTests extends AndroidTestCase {
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>>());
+ final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext());
+ dictionaryFacilitator.resetDictionariesForTesting(getContext(),
+ new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
+ new HashMap<String, Map<String, String>>());
+ // Set subtypes.
+ RichInputMethodManager.init(getContext());
+ final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ LOCALE_EN_US.toString(), "qwerty"));
+ dictionaryFacilitator.updateEnabledSubtypes(subtypes);
return dictionaryFacilitator;
}
public void testAddManyTokens() {
final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
dictionaryFacilitator.clearPersonalizationDictionary();
- final int dataChunkCount = 20;
- final int wordCountInOneChunk = 2000;
+ final int dataChunkCount = 100;
+ final int wordCountInOneChunk = 200;
+ final int uniqueWordCount = 100;
final Random random = new Random(System.currentTimeMillis());
final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
+ final ArrayList<String> words = new ArrayList<>();
+ for (int i = 0; i < uniqueWordCount; i++) {
+ words.add(CodePointUtils.generateWord(random, codePointSet));
+ }
final SpacingAndPunctuations spacingAndPunctuations =
new SpacingAndPunctuations(getContext().getResources());
@@ -75,13 +90,14 @@ public class PersonalizationDictionaryTests extends AndroidTestCase {
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));
+ tokens.add(words.get(random.nextInt(words.size())));
}
final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk(
- true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME);
+ true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME,
+ LOCALE_EN_US.getLanguage());
final CountDownLatch countDownLatch = new CountDownLatch(1);
- final AddMultipleDictionaryEntriesCallback callback =
- new AddMultipleDictionaryEntriesCallback() {
+ final UpdateEntriesForInputEventsCallback callback =
+ new UpdateEntriesForInputEventsCallback() {
@Override
public void onFinished() {
countDownLatch.countDown();
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index f87f3b494..778f6e800 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -21,13 +21,14 @@ 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.NgramContext;
+import com.android.inputmethod.latin.NgramContext.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.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -41,6 +42,8 @@ import java.util.concurrent.TimeUnit;
@LargeTest
public class UserHistoryDictionaryTests extends AndroidTestCase {
private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
+ private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000;
+ private static final String TEST_LOCALE_PREFIX = "test_";
private static final String[] CHARACTERS = {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
@@ -49,14 +52,60 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
private int mCurrentTime = 0;
+ private void removeAllTestDictFiles() {
+ final Locale dummyLocale = new Locale(TEST_LOCALE_PREFIX);
+ final String dictName = ExpandableBinaryDictionary.getDictName(
+ UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+ final File dictFile = ExpandableBinaryDictionary.getDictFile(
+ mContext, dictName, null /* dictFile */);
+ final FilenameFilter filenameFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String filename) {
+ return filename.startsWith(UserHistoryDictionary.NAME + "." + TEST_LOCALE_PREFIX);
+ }
+ };
+ FileUtils.deleteFilteredFiles(dictFile.getParentFile(), filenameFilter);
+ }
+
+ 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 checkExistenceAndRemoveDictFile(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("check exisiting of " + dictFile, dictFile.exists());
+ FileUtils.deleteRecursively(dictFile);
+ }
+
+ private static Locale getDummyLocale(final String name) {
+ return new Locale(TEST_LOCALE_PREFIX + name + System.currentTimeMillis());
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
resetCurrentTimeForTestMode();
+ removeAllTestDictFiles();
}
@Override
protected void tearDown() throws Exception {
+ removeAllTestDictFiles();
stopTestModeInNativeCode();
super.tearDown();
}
@@ -110,13 +159,13 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
return new ArrayList<>(wordSet);
}
- private static void addToDict(final UserHistoryDictionary dict, final List<String> words) {
- PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
+ private static void addToDict(final UserHistoryDictionary dict, final List<String> words,
+ final int timestamp) {
+ NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
for (String word : words) {
- UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true,
- (int)TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()),
+ UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, timestamp,
DistracterFilter.EMPTY_DISTRACTER_FILTER);
- prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
+ ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
}
}
@@ -124,13 +173,11 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
* @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) {
+ private void addAndWriteRandomWords(final UserHistoryDictionary dict,
+ 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);
+ addToDict(dict, words, mCurrentTime);
if (checkContents) {
dict.waitAllTasksForTests();
for (int i = 0; i < numberOfWords; ++i) {
@@ -144,49 +191,31 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
/**
* 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() {
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 Locale dummyLocale = getDummyLocale("random_words");
final String dictName = ExpandableBinaryDictionary.getDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
+ final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+ getContext(), dummyLocale);
final int numberOfWords = 1000;
final Random random = new Random(123456);
-
- 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);
- }
+ clearHistory(dict);
+ addAndWriteRandomWords(dict, numberOfWords, random, true /* checksContents */);
+ checkExistenceAndRemoveDictFile(dict, dictFile);
}
public void testStressTestForSwitchingLanguagesAndAddingWords() {
@@ -195,79 +224,75 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
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 Locale dummyLocale = getDummyLocale("switching_languages" + i);
final String dictName = ExpandableBinaryDictionary.getDictName(
- UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */);
+ UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
- clearHistory(dummyLocales[i]);
+ dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(),
+ dummyLocale);
+ 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].
+ addAndWriteRandomWords(dicts[index], numberOfWordsInsertedForEachLanguageSwitch,
+ random, false /* checksContents */);
}
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);
+ checkExistenceAndRemoveDictFile(dicts[i], dictFiles[i]);
}
}
}
public void testAddManyWords() {
- final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
+ final Locale dummyLocale = getDummyLocale("many_random_words");
final String dictName = ExpandableBinaryDictionary.getDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */);
final int numberOfWords = 10000;
final Random random = new Random(123456);
- clearHistory(dummyLocale);
+ final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+ getContext(), dummyLocale);
+ clearHistory(dict);
try {
- addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */);
+ addAndWriteRandomWords(dict, numberOfWords, random, true /* checksContents */);
} finally {
- Log.d(TAG, "waiting for writing ...");
- waitForWriting(dummyLocale);
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
+ checkExistenceAndRemoveDictFile(dict, dictFile);
}
}
public void testDecaying() {
- final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis());
+ final Locale dummyLocale = getDummyLocale("decaying");
+ final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+ getContext(), dummyLocale);
final int numberOfWords = 5000;
final Random random = new Random(123456);
resetCurrentTimeForTestMode();
- clearHistory(dummyLocale);
+ clearHistory(dict);
final List<String> words = generateWords(numberOfWords, random);
- final UserHistoryDictionary dict =
- PersonalizationHelper.getUserHistoryDictionary(getContext(), dummyLocale);
dict.waitAllTasksForTests();
- PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
+ NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
for (final String word : words) {
- UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true, mCurrentTime,
+ UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, mCurrentTime,
DistracterFilter.EMPTY_DISTRACTER_FILTER);
- prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
+ ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
dict.waitAllTasksForTests();
assertTrue(dict.isInDictionary(word));
}
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..36e967275
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -0,0 +1,148 @@
+/*
+ * 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 android.app.AlertDialog;
+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 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;
+
+ public AccountsSettingsFragmentTests() {
+ super(TestFragmentActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Intent intent = new Intent();
+ intent.putExtra(TestFragmentActivity.EXTRA_SHOW_FRAGMENT, FRAG_NAME);
+ setActivityIntent(intent);
+ }
+
+ public void testEmptyAccounts() {
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ try {
+ fragment.createAccountPicker(new String[0], null);
+ fail("Expected IllegalArgumentException, never thrown");
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
+ private static class DialogHolder {
+ AlertDialog mDialog;
+ DialogHolder() {}
+ }
+
+ public void testMultipleAccounts_noCurrentAccount() {
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ 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"},
+ null);
+ dialog.show();
+ dialogHolder.mDialog = dialog;
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await(TEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ex) {
+ fail();
+ }
+ getInstrumentation().waitForIdleSync();
+ final AlertDialog dialog = dialogHolder.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() {
+ final AccountsSettingsFragment fragment =
+ (AccountsSettingsFragment) getActivity().mFragment;
+ 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"},
+ "3@example.com");
+ dialog.show();
+ dialogHolder.mDialog = dialog;
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await(TEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ex) {
+ fail();
+ }
+ getInstrumentation().waitForIdleSync();
+ final AlertDialog dialog = dialogHolder.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());
+ }
+}
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/touchinputconsumer/NullGestureConsumerTests.java b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
new file mode 100644
index 000000000..ca1039bd9
--- /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);
+ }
+
+ /**
+ * 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
index a333ee9bc..131865ab2 100644
--- a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
@@ -39,10 +39,8 @@ public class BinaryDictionaryUtilsTests extends AndroidTestCase {
final int formatVersion) throws IOException {
if (formatVersion == FormatSpec.VERSION4) {
return createEmptyVer4DictionaryAndGetFile(dictId);
- } else {
- throw new IOException("Dictionary format version " + formatVersion
- + " is not supported.");
}
+ throw new IOException("Dictionary format version " + formatVersion + " is not supported.");
}
private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
@@ -59,10 +57,8 @@ public class BinaryDictionaryUtilsTests extends AndroidTestCase {
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.");
}
+ throw new IOException("Empty dictionary " + file.getAbsolutePath() + " cannot be created.");
}
private File getDictFile(final String dictId) {
diff --git a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
index c746c8345..4646a823d 100644
--- a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
@@ -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..dc4e2e4bb
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -0,0 +1,85 @@
+/*
+ * 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.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/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/utils/DistracterFilterTest.java
index e6fb28260..8360d53fb 100644
--- a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
+++ b/tests/src/com/android/inputmethod/latin/utils/DistracterFilterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.latin.utils;
import java.util.ArrayList;
import java.util.Locale;
@@ -24,7 +24,9 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType;
/**
* Unit test for DistracterFilter
@@ -50,8 +52,13 @@ public class DistracterFilterTest extends AndroidTestCase {
mDistracterFilter.updateEnabledSubtypes(subtypes);
}
- public void testIsDistractorToWordsInDictionaries() {
- final PrevWordsInfo EMPTY_PREV_WORDS_INFO = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
+ @Override
+ protected void tearDown() {
+ mDistracterFilter.close();
+ }
+
+ public void testIsDistracterToWordsInDictionaries() {
+ final NgramContext EMPTY_PREV_WORDS_INFO = NgramContext.EMPTY_PREV_WORDS_INFO;
final Locale localeEnUs = new Locale("en", "US");
String typedWord;
@@ -194,4 +201,25 @@ public class DistracterFilterTest extends AndroidTestCase {
assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
}
+
+ public void testGetWordHandlingType() {
+ final Locale localeEnUs = new Locale("en", "US");
+ final NgramContext EMPTY_PREV_WORDS_INFO = NgramContext.EMPTY_PREV_WORDS_INFO;
+ int handlingType = 0;
+
+ handlingType = mDistracterFilter.getWordHandlingType(EMPTY_PREV_WORDS_INFO,
+ "this", localeEnUs);
+ assertFalse(HandlingType.shouldBeLowerCased(handlingType));
+ assertFalse(HandlingType.shouldBeHandledAsOov(handlingType));
+
+ handlingType = mDistracterFilter.getWordHandlingType(EMPTY_PREV_WORDS_INFO,
+ "This", localeEnUs);
+ assertTrue(HandlingType.shouldBeLowerCased(handlingType));
+ assertFalse(HandlingType.shouldBeHandledAsOov(handlingType));
+
+ handlingType = mDistracterFilter.getWordHandlingType(EMPTY_PREV_WORDS_INFO,
+ "thibk", localeEnUs);
+ assertFalse(HandlingType.shouldBeLowerCased(handlingType));
+ assertTrue(HandlingType.shouldBeHandledAsOov(handlingType));
+ }
}
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/ImportantNoticeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
index 819d76328..cbabf7e8d 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
@@ -16,18 +16,18 @@
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 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 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;
@@ -112,6 +112,28 @@ 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 imortant notice after fresh install", true,
+ ImportantNoticeUtils.hasNewImportantNotice(getContext()));
+ assertEquals("Next important norice 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()));
+ }
+
public void testUpdateVersion() {
mImportantNoticePreferences.clear();
@@ -163,7 +185,7 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
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())));
@@ -180,7 +202,7 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
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())));
@@ -196,7 +218,7 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
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())));
@@ -212,7 +234,7 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
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())));
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/SpacebarLanguageUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtilsTests.java
new file mode 100644
index 000000000..83afd782d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtilsTests.java
@@ -0,0 +1,318 @@
+/*
+ * 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.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+@SmallTest
+public class SpacebarLanguageUtilsTests 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(context);
+ 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 Locale[] locales = subtype.getLocales();
+ if (1 == locales.length) {
+ final String languageName = SubtypeLocaleUtils
+ .getSubtypeLocaleDisplayName(locales[0].toString());
+ if (subtype.isNoLanguage()) {
+ assertFalse(subtypeName, spacebarText.contains(languageName));
+ } else {
+ assertTrue(subtypeName, spacebarText.contains(languageName));
+ }
+ } else {
+ // TODO: test multi-lingual subtype spacebar display
+ }
+ }
+ }
+
+ public void testAllMiddleDisplayNameForSpacebar() {
+ for (final RichInputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+ final Locale[] locales = subtype.getLocales();
+ if (locales.length > 1) {
+ // TODO: test multi-lingual subtype spacebar display
+ continue;
+ }
+ final Locale locale = locales[0];
+ 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);
+ }
+}
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..11d10aa2f 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
@@ -21,7 +21,6 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
import android.text.SpannableStringBuilder;
-import android.text.Spannable;
import android.text.Spanned;
@SmallTest
@@ -34,8 +33,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,7 +50,7 @@ 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);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
index 637ae10ee..0389fefb0 100644
--- a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
@@ -22,7 +22,9 @@ import android.text.SpannableString;
import android.text.Spanned;
import android.text.SpannedString;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.utils.SpannableStringUtils;
import java.util.Arrays;
import java.util.List;
@@ -375,9 +377,9 @@ public class StringAndJsonUtilsTests extends AndroidTestCase {
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(
+ final CharSequence[] charSequencesFromSpanned = SpannableStringUtils.split(
spannableString, " ", true /* preserveTrailingEmptySegmengs */);
- final CharSequence[] charSequencesFromString = StringUtils.split(
+ final CharSequence[] charSequencesFromString = SpannableStringUtils.split(
spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */);
@@ -456,44 +458,44 @@ public class StringAndJsonUtilsTests extends AndroidTestCase {
}
public void testSplitCharSequencePreserveTrailingEmptySegmengs() {
- assertEquals(1, StringUtils.split("", " ",
+ assertEquals(1, SpannableStringUtils.split("", " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(1, StringUtils.split(new SpannedString(""), " ",
+ assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(1, StringUtils.split("", " ",
+ assertEquals(1, SpannableStringUtils.split("", " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(1, StringUtils.split(new SpannedString(""), " ",
+ assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(0, StringUtils.split(" ", " ",
+ assertEquals(0, SpannableStringUtils.split(" ", " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(0, StringUtils.split(new SpannedString(" "), " ",
+ assertEquals(0, SpannableStringUtils.split(new SpannedString(" "), " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(2, StringUtils.split(" ", " ",
+ assertEquals(2, SpannableStringUtils.split(" ", " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(2, StringUtils.split(new SpannedString(" "), " ",
+ assertEquals(2, SpannableStringUtils.split(new SpannedString(" "), " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(3, StringUtils.split("a b c ", " ",
+ assertEquals(3, SpannableStringUtils.split("a b c ", " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(3, StringUtils.split(new SpannedString("a b c "), " ",
+ assertEquals(3, SpannableStringUtils.split(new SpannedString("a b c "), " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(5, StringUtils.split("a b c ", " ",
+ assertEquals(5, SpannableStringUtils.split("a b c ", " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(5, StringUtils.split(new SpannedString("a b c "), " ",
+ assertEquals(5, SpannableStringUtils.split(new SpannedString("a b c "), " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(6, StringUtils.split("a b ", " ",
+ assertEquals(6, SpannableStringUtils.split("a b ", " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(6, StringUtils.split(new SpannedString("a b "), " ",
+ assertEquals(6, SpannableStringUtils.split(new SpannedString("a b "), " ",
false /* preserveTrailingEmptySegmengs */).length);
- assertEquals(7, StringUtils.split("a b ", " ",
+ assertEquals(7, SpannableStringUtils.split("a b ", " ",
true /* preserveTrailingEmptySegmengs */).length);
- assertEquals(7, StringUtils.split(new SpannedString("a b "), " ",
+ assertEquals(7, SpannableStringUtils.split(new SpannedString("a b "), " ",
true /* preserveTrailingEmptySegmengs */).length);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index ce3df7dd6..54f478f5a 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(context);
+ 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,20 +123,43 @@ 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)) {
- final String layoutName = SubtypeLocaleUtils
- .getKeyboardLayoutSetDisplayName(subtype);
- assertTrue(subtypeName, subtypeName.contains(layoutName));
+ .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+ final Locale[] locales = subtype.getLocales();
+ if (1 == locales.length) {
+ if (subtype.isNoLanguage()) {
+ final String layoutName = SubtypeLocaleUtils
+ .getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
+ assertTrue(subtypeName, subtypeName.contains(layoutName));
+ } else {
+ final String languageName = SubtypeLocaleUtils
+ .getSubtypeLocaleDisplayNameInSystemLocale(locales[0].toString());
+ assertTrue(subtypeName, subtypeName.contains(languageName));
+ }
} else {
- final String languageName = SubtypeLocaleUtils
- .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale());
- assertTrue(subtypeName, subtypeName.contains(languageName));
+ // TODO: test multi-lingual subtype spacebar display
}
}
}
@@ -128,6 +173,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 +187,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 +248,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 +287,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 +306,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 +348,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 +387,77 @@ 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) {
+ // TODO: Uncommented because of the current translation of these strings
+ // in Seriban are described in Latin script.
+// 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 +470,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());
}
}
}