1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.latin.personalization; 18 19 import static org.junit.Assert.assertTrue; 20 21 import android.content.Context; 22 import android.util.Log; 23 24 import androidx.test.InstrumentationRegistry; 25 import androidx.test.filters.LargeTest; 26 import androidx.test.runner.AndroidJUnit4; 27 28 import com.android.inputmethod.latin.ExpandableBinaryDictionary; 29 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; 30 31 import org.junit.After; 32 import org.junit.Before; 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 36 import java.io.File; 37 import java.util.Locale; 38 import java.util.Random; 39 40 /** 41 * Unit tests for UserHistoryDictionary 42 */ 43 @LargeTest 44 @RunWith(AndroidJUnit4.class) 45 public class UserHistoryDictionaryTests { 46 private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName(); 47 private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000; 48 private static final String TEST_ACCOUNT = "account@example.com"; 49 50 private int mCurrentTime = 0; 51 getContext()52 private Context getContext() { 53 return InstrumentationRegistry.getTargetContext(); 54 } 55 printAllFiles(final File dir)56 private static void printAllFiles(final File dir) { 57 Log.d(TAG, dir.getAbsolutePath()); 58 for (final File file : dir.listFiles()) { 59 Log.d(TAG, " " + file.getName()); 60 } 61 } 62 assertDictionaryExists(final UserHistoryDictionary dict, final File dictFile)63 private static void assertDictionaryExists(final UserHistoryDictionary dict, 64 final File dictFile) { 65 Log.d(TAG, "waiting for writing ..."); 66 dict.waitAllTasksForTests(); 67 if (!dictFile.exists()) { 68 try { 69 Log.d(TAG, dictFile + " is not existing. Wait " 70 + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing."); 71 printAllFiles(dictFile.getParentFile()); 72 Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS); 73 } catch (final InterruptedException e) { 74 Log.e(TAG, "Interrupted during waiting for writing the dict file."); 75 } 76 } 77 assertTrue("Following dictionary file doesn't exist: " + dictFile, dictFile.exists()); 78 } 79 80 @Before setUp()81 public void setUp() throws Exception { 82 resetCurrentTimeForTestMode(); 83 UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( 84 UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, getContext()); 85 } 86 87 @After tearDown()88 public void tearDown() throws Exception { 89 UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( 90 UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, getContext()); 91 stopTestModeInNativeCode(); 92 } 93 resetCurrentTimeForTestMode()94 private void resetCurrentTimeForTestMode() { 95 mCurrentTime = 0; 96 setCurrentTimeForTestMode(mCurrentTime); 97 } 98 setCurrentTimeForTestMode(final int currentTime)99 private static int setCurrentTimeForTestMode(final int currentTime) { 100 return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime); 101 } 102 stopTestModeInNativeCode()103 private static int stopTestModeInNativeCode() { 104 return BinaryDictionaryUtils.setCurrentTimeForTest(-1); 105 } 106 107 /** 108 * Clear all entries in the user history dictionary. 109 * @param dict the user history dictionary. 110 */ clearHistory(final UserHistoryDictionary dict)111 private static void clearHistory(final UserHistoryDictionary dict) { 112 dict.waitAllTasksForTests(); 113 dict.clear(); 114 dict.close(); 115 dict.waitAllTasksForTests(); 116 } 117 doTestRandomWords(final String testAccount)118 private void doTestRandomWords(final String testAccount) { 119 Log.d(TAG, "This test can be used for profiling."); 120 Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true."); 121 final Locale fakeLocale = UserHistoryDictionaryTestsHelper.getFakeLocale("random_words"); 122 final String dictName = UserHistoryDictionary.getUserHistoryDictName( 123 UserHistoryDictionary.NAME, fakeLocale, 124 null /* dictFile */, 125 testAccount /* account */); 126 final File dictFile = ExpandableBinaryDictionary.getDictFile( 127 getContext(), dictName, null /* dictFile */); 128 final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( 129 getContext(), fakeLocale, testAccount); 130 clearHistory(dict); 131 132 final int numberOfWords = 1000; 133 final Random random = new Random(123456); 134 assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords( 135 dict, numberOfWords, random, true /* checksContents */, mCurrentTime)); 136 assertDictionaryExists(dict, dictFile); 137 } 138 139 @Test testRandomWords_NullAccount()140 public void testRandomWords_NullAccount() { 141 doTestRandomWords(null /* testAccount */); 142 } 143 144 @Test testRandomWords()145 public void testRandomWords() { 146 doTestRandomWords(TEST_ACCOUNT); 147 } 148 149 @Test testStressTestForSwitchingLanguagesAndAddingWords()150 public void testStressTestForSwitchingLanguagesAndAddingWords() { 151 doTestStressTestForSwitchingLanguagesAndAddingWords(TEST_ACCOUNT); 152 } 153 154 @Test testStressTestForSwitchingLanguagesAndAddingWords_NullAccount()155 public void testStressTestForSwitchingLanguagesAndAddingWords_NullAccount() { 156 doTestStressTestForSwitchingLanguagesAndAddingWords(null /* testAccount */); 157 } 158 doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount)159 private void doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount) { 160 final int numberOfLanguages = 2; 161 final int numberOfLanguageSwitching = 80; 162 final int numberOfWordsInsertedForEachLanguageSwitch = 100; 163 164 final File dictFiles[] = new File[numberOfLanguages]; 165 final UserHistoryDictionary dicts[] = new UserHistoryDictionary[numberOfLanguages]; 166 167 try { 168 final Random random = new Random(123456); 169 170 // Create filename suffixes for this test. 171 for (int i = 0; i < numberOfLanguages; i++) { 172 final Locale fakeLocale = 173 UserHistoryDictionaryTestsHelper.getFakeLocale("switching_languages" + i); 174 final String dictName = UserHistoryDictionary.getUserHistoryDictName( 175 UserHistoryDictionary.NAME, fakeLocale, null /* dictFile */, 176 testAccount /* account */); 177 dictFiles[i] = ExpandableBinaryDictionary.getDictFile( 178 getContext(), dictName, null /* dictFile */); 179 dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(), 180 fakeLocale, testAccount); 181 clearHistory(dicts[i]); 182 } 183 184 final long start = System.currentTimeMillis(); 185 186 for (int i = 0; i < numberOfLanguageSwitching; i++) { 187 final int index = i % numberOfLanguages; 188 // Switch to dicts[index]. 189 assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dicts[index], 190 numberOfWordsInsertedForEachLanguageSwitch, 191 random, 192 false /* checksContents */, 193 mCurrentTime)); 194 } 195 196 final long end = System.currentTimeMillis(); 197 Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took " 198 + (end - start) + " ms"); 199 } finally { 200 for (int i = 0; i < numberOfLanguages; i++) { 201 assertDictionaryExists(dicts[i], dictFiles[i]); 202 } 203 } 204 } 205 206 @Test testAddManyWords()207 public void testAddManyWords() { 208 doTestAddManyWords(TEST_ACCOUNT); 209 } 210 211 @Test testAddManyWords_NullAccount()212 public void testAddManyWords_NullAccount() { 213 doTestAddManyWords(null /* testAccount */); 214 } 215 doTestAddManyWords(final String testAccount)216 private void doTestAddManyWords(final String testAccount) { 217 final Locale fakeLocale = 218 UserHistoryDictionaryTestsHelper.getFakeLocale("many_random_words"); 219 final String dictName = UserHistoryDictionary.getUserHistoryDictName( 220 UserHistoryDictionary.NAME, fakeLocale, null /* dictFile */, testAccount); 221 final File dictFile = ExpandableBinaryDictionary.getDictFile( 222 getContext(), dictName, null /* dictFile */); 223 final int numberOfWords = 10000; 224 final Random random = new Random(123456); 225 final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( 226 getContext(), fakeLocale, testAccount); 227 clearHistory(dict); 228 assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict, 229 numberOfWords, random, true /* checksContents */, mCurrentTime)); 230 assertDictionaryExists(dict, dictFile); 231 } 232 } 233