diff options
Diffstat (limited to 'tests/src/com/android/inputmethod/latin/personalization')
4 files changed, 239 insertions, 361 deletions
diff --git a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java deleted file mode 100644 index 565fadb2a..000000000 --- a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.DictionaryFacilitator; -import com.android.inputmethod.latin.ExpandableBinaryDictionary; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; - -/** - * Unit tests for contextual dictionary - */ -@LargeTest -public class ContextualDictionaryTests extends AndroidTestCase { - private static final String TAG = ContextualDictionaryTests.class.getSimpleName(); - - private static final Locale LOCALE_EN_US = new Locale("en", "US"); - - private DictionaryFacilitator getDictionaryFacilitator() { - final ArrayList<String> dictTypes = new ArrayList<>(); - dictTypes.add(Dictionary.TYPE_CONTEXTUAL); - final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(); - dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes, - new HashMap<String, File>(), new HashMap<String, Map<String, String>>()); - return dictionaryFacilitator; - } - - public void testAddPhrase() { - final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator(); - final String[] phrase = new String[] {"a", "b", "c", "d"}; - final int probability = 100; - final int bigramProbabilityForWords = 150; - final int bigramProbabilityForPhrases = 200; - dictionaryFacilitator.addPhraseToContextualDictionary( - phrase, probability, bigramProbabilityForWords, bigramProbabilityForPhrases); - final ExpandableBinaryDictionary contextualDictionary = - dictionaryFacilitator.getSubDictForTesting(Dictionary.TYPE_CONTEXTUAL); - contextualDictionary.waitAllTasksForTests(); - // Word - assertTrue(contextualDictionary.isInDictionary("a")); - assertTrue(contextualDictionary.isInDictionary("b")); - assertTrue(contextualDictionary.isInDictionary("c")); - assertTrue(contextualDictionary.isInDictionary("d")); - // Phrase - assertTrue(contextualDictionary.isInDictionary("a b c d")); - assertTrue(contextualDictionary.isInDictionary("b c d")); - assertTrue(contextualDictionary.isInDictionary("c d")); - assertFalse(contextualDictionary.isInDictionary("a b c")); - assertFalse(contextualDictionary.isInDictionary("abcd")); - // TODO: Add tests for probability. - // TODO: Add tests for n-grams. - } -} diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java deleted file mode 100644 index 0f2f9814b..000000000 --- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import com.android.inputmethod.latin.BinaryDictionary; -import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.DictionaryFacilitator; -import com.android.inputmethod.latin.ExpandableBinaryDictionary; -import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback; -import com.android.inputmethod.latin.makedict.CodePointUtils; -import com.android.inputmethod.latin.settings.SpacingAndPunctuations; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -/** - * Unit tests for personalization dictionary - */ -@LargeTest -public class PersonalizationDictionaryTests extends AndroidTestCase { - private static final String TAG = PersonalizationDictionaryTests.class.getSimpleName(); - - private static final Locale LOCALE_EN_US = new Locale("en", "US"); - private static final String DUMMY_PACKAGE_NAME = "test.package.name"; - private static final long TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS = 120; - - private DictionaryFacilitator getDictionaryFacilitator() { - final ArrayList<String> dictTypes = new ArrayList<>(); - dictTypes.add(Dictionary.TYPE_MAIN); - dictTypes.add(Dictionary.TYPE_PERSONALIZATION); - final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(); - dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes, - new HashMap<String, File>(), new HashMap<String, Map<String, String>>()); - return dictionaryFacilitator; - } - - public void testAddManyTokens() { - final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator(); - dictionaryFacilitator.clearPersonalizationDictionary(); - final int dataChunkCount = 20; - final int wordCountInOneChunk = 2000; - final Random random = new Random(System.currentTimeMillis()); - final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER; - - final SpacingAndPunctuations spacingAndPunctuations = - new SpacingAndPunctuations(getContext().getResources()); - - final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds( - System.currentTimeMillis()); - - for (int i = 0; i < dataChunkCount; i++) { - final ArrayList<String> tokens = new ArrayList<>(); - for (int j = 0; j < wordCountInOneChunk; j++) { - tokens.add(CodePointUtils.generateWord(random, codePointSet)); - } - final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk( - true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME); - final CountDownLatch countDownLatch = new CountDownLatch(1); - final AddMultipleDictionaryEntriesCallback callback = - new AddMultipleDictionaryEntriesCallback() { - @Override - public void onFinished() { - countDownLatch.countDown(); - } - }; - dictionaryFacilitator.addEntriesToPersonalizationDictionary(personalizationDataChunk, - spacingAndPunctuations, callback); - try { - countDownLatch.await(TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS, - TimeUnit.SECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e); - } - } - dictionaryFacilitator.flushPersonalizationDictionary(); - try { - dictionaryFacilitator.waitForLoadingDictionariesForTesting( - TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e); - } - final String dictName = ExpandableBinaryDictionary.getDictName( - PersonalizationDictionary.NAME, LOCALE_EN_US, null /* dictFile */); - final File dictFile = ExpandableBinaryDictionary.getDictFile( - getContext(), dictName, null /* dictFile */); - - final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), - 0 /* offset */, 0 /* size */, - true /* useFullEditDistance */, LOCALE_EN_US, Dictionary.TYPE_PERSONALIZATION, - true /* isUpdatable */); - assertTrue(binaryDictionary.isValidDictionary()); - } -} diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java index f87f3b494..559f28642 100644 --- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java @@ -21,19 +21,11 @@ import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; import com.android.inputmethod.latin.ExpandableBinaryDictionary; -import com.android.inputmethod.latin.PrevWordsInfo; -import com.android.inputmethod.latin.PrevWordsInfo.WordInfo; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; -import com.android.inputmethod.latin.utils.DistracterFilter; -import com.android.inputmethod.latin.utils.FileUtils; import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Random; -import java.util.concurrent.TimeUnit; /** * Unit tests for UserHistoryDictionary @@ -41,22 +33,47 @@ import java.util.concurrent.TimeUnit; @LargeTest public class UserHistoryDictionaryTests extends AndroidTestCase { private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName(); - - private static final String[] CHARACTERS = { - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" - }; + private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000; + private static final String TEST_ACCOUNT = "account@example.com"; private int mCurrentTime = 0; + private static void printAllFiles(final File dir) { + Log.d(TAG, dir.getAbsolutePath()); + for (final File file : dir.listFiles()) { + Log.d(TAG, " " + file.getName()); + } + } + + private static void assertDictionaryExists(final UserHistoryDictionary dict, + final File dictFile) { + Log.d(TAG, "waiting for writing ..."); + dict.waitAllTasksForTests(); + if (!dictFile.exists()) { + try { + Log.d(TAG, dictFile + " is not existing. Wait " + + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing."); + printAllFiles(dictFile.getParentFile()); + Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS); + } catch (final InterruptedException e) { + Log.e(TAG, "Interrupted during waiting for writing the dict file."); + } + } + assertTrue("Following dictionary file doesn't exist: " + dictFile, dictFile.exists()); + } + @Override protected void setUp() throws Exception { super.setUp(); resetCurrentTimeForTestMode(); + UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( + UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext); } @Override protected void tearDown() throws Exception { + UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( + UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext); stopTestModeInNativeCode(); super.tearDown(); } @@ -66,20 +83,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { setCurrentTimeForTestMode(mCurrentTime); } - private void forcePassingShortTime() { - // 3 days. - final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(3); - mCurrentTime += timeToElapse; - setCurrentTimeForTestMode(mCurrentTime); - } - - private void forcePassingLongTime() { - // 365 days. - final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(365); - mCurrentTime += timeToElapse; - setCurrentTimeForTestMode(mCurrentTime); - } - private static int setCurrentTimeForTestMode(final int currentTime) { return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime); } @@ -89,199 +92,122 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { } /** - * Generates a random word. - */ - private static String generateWord(final int value) { - final int lengthOfChars = CHARACTERS.length; - StringBuilder builder = new StringBuilder(); - long lvalue = Math.abs((long)value); - while (lvalue > 0) { - builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]); - lvalue /= lengthOfChars; - } - return builder.toString(); - } - - private static List<String> generateWords(final int number, final Random random) { - final HashSet<String> wordSet = new HashSet<>(); - while (wordSet.size() < number) { - wordSet.add(generateWord(random.nextInt())); - } - return new ArrayList<>(wordSet); - } - - private static void addToDict(final UserHistoryDictionary dict, final List<String> words) { - PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO; - for (String word : words) { - UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true, - (int)TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), - DistracterFilter.EMPTY_DISTRACTER_FILTER); - prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word)); - } - } - - /** - * @param checkContents if true, checks whether written words are actually in the dictionary - * or not. - */ - private void addAndWriteRandomWords(final Locale locale, final int numberOfWords, - final Random random, final boolean checkContents) { - final List<String> words = generateWords(numberOfWords, random); - final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( - mContext, locale); - // Add random words to the user history dictionary. - addToDict(dict, words); - if (checkContents) { - dict.waitAllTasksForTests(); - for (int i = 0; i < numberOfWords; ++i) { - final String word = words.get(i); - assertTrue(dict.isInDictionary(word)); - } - } - // write to file. - dict.close(); - } - - /** * Clear all entries in the user history dictionary. - * @param locale dummy locale for testing. + * @param dict the user history dictionary. */ - private void clearHistory(final Locale locale) { - final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( - mContext, locale); + private static void clearHistory(final UserHistoryDictionary dict) { dict.waitAllTasksForTests(); dict.clear(); dict.close(); dict.waitAllTasksForTests(); } - /** - * Shut down executer and wait until all operations of user history are done. - * @param locale dummy locale for testing. - */ - private void waitForWriting(final Locale locale) { - final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( - mContext, locale); - dict.waitAllTasksForTests(); - } - - public void testRandomWords() { + private void doTestRandomWords(final String testAccount) { Log.d(TAG, "This test can be used for profiling."); Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true."); - final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis()); - final String dictName = ExpandableBinaryDictionary.getDictName( - UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */); + final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("random_words"); + final String dictName = UserHistoryDictionary.getUserHistoryDictName( + UserHistoryDictionary.NAME, dummyLocale, + null /* dictFile */, + testAccount /* account */); final File dictFile = ExpandableBinaryDictionary.getDictFile( mContext, dictName, null /* dictFile */); + final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( + getContext(), dummyLocale, testAccount); + clearHistory(dict); final int numberOfWords = 1000; final Random random = new Random(123456); + assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords( + dict, numberOfWords, random, true /* checksContents */, mCurrentTime)); + assertDictionaryExists(dict, dictFile); + } - try { - clearHistory(dummyLocale); - addAndWriteRandomWords(dummyLocale, numberOfWords, random, - true /* checksContents */); - } finally { - Log.d(TAG, "waiting for writing ..."); - waitForWriting(dummyLocale); - assertTrue("check exisiting of " + dictFile, dictFile.exists()); - FileUtils.deleteRecursively(dictFile); - } + public void testRandomWords_NullAccount() { + doTestRandomWords(null /* testAccount */); + } + + public void testRandomWords() { + doTestRandomWords(TEST_ACCOUNT); } public void testStressTestForSwitchingLanguagesAndAddingWords() { + doTestStressTestForSwitchingLanguagesAndAddingWords(TEST_ACCOUNT); + } + + public void testStressTestForSwitchingLanguagesAndAddingWords_NullAccount() { + doTestStressTestForSwitchingLanguagesAndAddingWords(null /* testAccount */); + } + + private void doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount) { final int numberOfLanguages = 2; final int numberOfLanguageSwitching = 80; final int numberOfWordsInsertedForEachLanguageSwitch = 100; final File dictFiles[] = new File[numberOfLanguages]; - final Locale dummyLocales[] = new Locale[numberOfLanguages]; + final UserHistoryDictionary dicts[] = new UserHistoryDictionary[numberOfLanguages]; + try { final Random random = new Random(123456); // Create filename suffixes for this test. for (int i = 0; i < numberOfLanguages; i++) { - dummyLocales[i] = new Locale("test_switching_languages" + i); - final String dictName = ExpandableBinaryDictionary.getDictName( - UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */); + final Locale dummyLocale = + UserHistoryDictionaryTestsHelper.getDummyLocale("switching_languages" + i); + final String dictName = UserHistoryDictionary.getUserHistoryDictName( + UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, + testAccount /* account */); dictFiles[i] = ExpandableBinaryDictionary.getDictFile( mContext, dictName, null /* dictFile */); - clearHistory(dummyLocales[i]); + dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(), + dummyLocale, testAccount); + clearHistory(dicts[i]); } final long start = System.currentTimeMillis(); for (int i = 0; i < numberOfLanguageSwitching; i++) { final int index = i % numberOfLanguages; - // Switch languages to testFilenameSuffixes[index]. - addAndWriteRandomWords(dummyLocales[index], - numberOfWordsInsertedForEachLanguageSwitch, random, - false /* checksContents */); + // Switch to dicts[index]. + assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dicts[index], + numberOfWordsInsertedForEachLanguageSwitch, + random, + false /* checksContents */, + mCurrentTime)); } final long end = System.currentTimeMillis(); Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took " + (end - start) + " ms"); } finally { - Log.d(TAG, "waiting for writing ..."); for (int i = 0; i < numberOfLanguages; i++) { - waitForWriting(dummyLocales[i]); - } - for (final File dictFile : dictFiles) { - assertTrue("check exisiting of " + dictFile, dictFile.exists()); - FileUtils.deleteRecursively(dictFile); + assertDictionaryExists(dicts[i], dictFiles[i]); } } } public void testAddManyWords() { - final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis()); - final String dictName = ExpandableBinaryDictionary.getDictName( - UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */); + doTestAddManyWords(TEST_ACCOUNT); + } + + public void testAddManyWords_NullAccount() { + doTestAddManyWords(null /* testAccount */); + } + + private void doTestAddManyWords(final String testAccount) { + final Locale dummyLocale = + UserHistoryDictionaryTestsHelper.getDummyLocale("many_random_words"); + final String dictName = UserHistoryDictionary.getUserHistoryDictName( + UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, testAccount); final File dictFile = ExpandableBinaryDictionary.getDictFile( mContext, dictName, null /* dictFile */); final int numberOfWords = 10000; final Random random = new Random(123456); - clearHistory(dummyLocale); - try { - addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */); - } finally { - Log.d(TAG, "waiting for writing ..."); - waitForWriting(dummyLocale); - assertTrue("check exisiting of " + dictFile, dictFile.exists()); - FileUtils.deleteRecursively(dictFile); - } - } - - public void testDecaying() { - final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis()); - final int numberOfWords = 5000; - final Random random = new Random(123456); - resetCurrentTimeForTestMode(); - clearHistory(dummyLocale); - final List<String> words = generateWords(numberOfWords, random); - final UserHistoryDictionary dict = - PersonalizationHelper.getUserHistoryDictionary(getContext(), dummyLocale); - dict.waitAllTasksForTests(); - PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO; - for (final String word : words) { - UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true, mCurrentTime, - DistracterFilter.EMPTY_DISTRACTER_FILTER); - prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word)); - dict.waitAllTasksForTests(); - assertTrue(dict.isInDictionary(word)); - } - forcePassingShortTime(); - dict.runGCIfRequired(); - dict.waitAllTasksForTests(); - for (final String word : words) { - assertTrue(dict.isInDictionary(word)); - } - forcePassingLongTime(); - dict.runGCIfRequired(); - dict.waitAllTasksForTests(); - for (final String word : words) { - assertFalse(dict.isInDictionary(word)); - } + final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( + getContext(), dummyLocale, testAccount); + clearHistory(dict); + assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict, + numberOfWords, random, true /* checksContents */, mCurrentTime)); + assertDictionaryExists(dict, dictFile); } -} +}
\ No newline at end of file diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java new file mode 100644 index 000000000..4b7b9bc36 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.personalization; + +import android.content.Context; + +import com.android.inputmethod.latin.BinaryDictionary; +import com.android.inputmethod.latin.NgramContext; +import com.android.inputmethod.latin.NgramContext.WordInfo; +import com.android.inputmethod.latin.common.FileUtils; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Random; + +/** + * Utility class for helping while running tests involving {@link UserHistoryDictionary}. + */ +public class UserHistoryDictionaryTestsHelper { + + /** + * Locale prefix for generating dummy locales for tests. + */ + public static final String TEST_LOCALE_PREFIX = "test-"; + + /** + * Characters for generating random words. + */ + private static final String[] CHARACTERS = { + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", + "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" + }; + + /** + * Remove all the test dictionary files created for the given locale. + */ + public static void removeAllTestDictFiles(final String filter, final Context context) { + final FilenameFilter filenameFilter = new FilenameFilter() { + @Override + public boolean accept(final File dir, final String filename) { + return filename.startsWith(UserHistoryDictionary.NAME + "." + filter); + } + }; + FileUtils.deleteFilteredFiles(context.getFilesDir(), filenameFilter); + } + + /** + * Generates and writes random words to dictionary. Caller can be assured + * that the write tasks would be finished; and its success would be reflected + * in the returned boolean. + * + * @param dict {@link UserHistoryDictionary} to which words should be added. + * @param numberOfWords number of words to be added. + * @param random helps generate random words. + * @param checkContents if true, checks whether written words are actually in the dictionary. + * @param currentTime timestamp that would be used for adding the words. + * @returns true if all words have been written to dictionary successfully. + */ + public static boolean addAndWriteRandomWords(final UserHistoryDictionary dict, + final int numberOfWords, final Random random, final boolean checkContents, + final int currentTime) { + final List<String> words = generateWords(numberOfWords, random); + // Add random words to the user history dictionary. + addWordsToDictionary(dict, words, currentTime); + boolean success = true; + if (checkContents) { + dict.waitAllTasksForTests(); + for (int i = 0; i < numberOfWords; ++i) { + final String word = words.get(i); + if (!dict.isInDictionary(word)) { + success = false; + break; + } + } + } + // write to file. + dict.close(); + dict.waitAllTasksForTests(); + return success; + } + + private static void addWordsToDictionary(final UserHistoryDictionary dict, + final List<String> words, final int timestamp) { + NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext( + BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM); + for (final String word : words) { + UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, timestamp); + ngramContext = ngramContext.getNextNgramContext(new WordInfo(word)); + } + } + + /** + * Creates unique test locale for using within tests. + */ + public static Locale getDummyLocale(final String name) { + return new Locale(TEST_LOCALE_PREFIX + name + System.currentTimeMillis()); + } + + /** + * Generates random words. + * + * @param numberOfWords number of words to generate. + * @param random salt used for generating random words. + */ + public static List<String> generateWords(final int numberOfWords, final Random random) { + final HashSet<String> wordSet = new HashSet<>(); + while (wordSet.size() < numberOfWords) { + wordSet.add(generateWord(random.nextInt())); + } + return new ArrayList<>(wordSet); + } + + /** + * Generates a random word. + */ + private static String generateWord(final int value) { + final int lengthOfChars = CHARACTERS.length; + final StringBuilder builder = new StringBuilder(); + long lvalue = Math.abs((long)value); + while (lvalue > 0) { + builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]); + lvalue /= lengthOfChars; + } + return builder.toString(); + } +} |