UserHistoryDictionaryTests.java revision a328f538c34ad2dafdfa53642085cb1072224d80
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
17package com.android.inputmethod.latin.personalization;
18
19import android.content.SharedPreferences;
20import android.preference.PreferenceManager;
21import android.test.AndroidTestCase;
22import android.test.suitebuilder.annotation.LargeTest;
23import android.util.Log;
24
25import com.android.inputmethod.latin.ExpandableBinaryDictionary;
26import com.android.inputmethod.latin.utils.CollectionUtils;
27
28import java.io.File;
29import java.util.ArrayList;
30import java.util.List;
31import java.util.Random;
32import java.util.Set;
33import java.util.concurrent.TimeUnit;
34
35/**
36 * Unit tests for UserHistoryDictionary
37 */
38@LargeTest
39public class UserHistoryDictionaryTests extends AndroidTestCase {
40    private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
41    private SharedPreferences mPrefs;
42
43    private static final String[] CHARACTERS = {
44        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
45        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
46    };
47
48    private static final int MIN_USER_HISTORY_DICTIONARY_FILE_SIZE = 1000;
49    private static final int WAIT_TERMINATING_IN_MILLISECONDS = 100;
50
51    @Override
52    public void setUp() {
53        mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
54    }
55
56    /**
57     * Generates a random word.
58     */
59    private String generateWord(final int value) {
60        final int lengthOfChars = CHARACTERS.length;
61        StringBuilder builder = new StringBuilder();
62        long lvalue = Math.abs((long)value);
63        while (lvalue > 0) {
64            builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
65            lvalue /= lengthOfChars;
66        }
67        return builder.toString();
68    }
69
70    private List<String> generateWords(final int number, final Random random) {
71        final Set<String> wordSet = CollectionUtils.newHashSet();
72        while (wordSet.size() < number) {
73            wordSet.add(generateWord(random.nextInt()));
74        }
75        return new ArrayList<String>(wordSet);
76    }
77
78    private void addToDict(final UserHistoryPredictionDictionary dict, final List<String> words) {
79        String prevWord = null;
80        for (String word : words) {
81            dict.addToPersonalizationPredictionDictionary(prevWord, word, true);
82            prevWord = word;
83        }
84    }
85
86    /**
87     * @param checkContents if true, checks whether written words are actually in the dictionary
88     * or not.
89     */
90    private void addAndWriteRandomWords(final String testFilenameSuffix, final int numberOfWords,
91            final Random random, final boolean checkContents) {
92        final List<String> words = generateWords(numberOfWords, random);
93        final UserHistoryPredictionDictionary dict =
94                PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
95                        testFilenameSuffix /* locale */, mPrefs);
96        // Add random words to the user history dictionary.
97        addToDict(dict, words);
98        if (checkContents) {
99            try {
100                Thread.sleep(TimeUnit.MILLISECONDS.convert(5L, TimeUnit.SECONDS));
101            } catch (InterruptedException e) {
102            }
103            for (int i = 0; i < numberOfWords; ++i) {
104                final String word = words.get(i);
105                assertTrue(dict.isInDictionaryForTests(word));
106            }
107        }
108        // write to file.
109        dict.close();
110    }
111
112    public void testRandomWords() {
113        File dictFile = null;
114        Log.d(TAG, "This test can be used for profiling.");
115        Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
116        final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis();
117        final int numberOfWords = 1000;
118        final Random random = new Random(123456);
119
120        try {
121            addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random,
122                    true /* checksContents */);
123        } finally {
124            try {
125                final UserHistoryPredictionDictionary dict =
126                        PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
127                                testFilenameSuffix, mPrefs);
128                Log.d(TAG, "waiting for writing ...");
129                dict.shutdownExecutorForTests();
130                while (!dict.isTerminatedForTests()) {
131                    Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
132                }
133            } catch (InterruptedException e) {
134                Log.d(TAG, "InterruptedException: " + e);
135            }
136
137            final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix
138                    + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
139            dictFile = new File(getContext().getFilesDir(), fileName);
140
141            if (dictFile != null) {
142                assertTrue(dictFile.exists());
143                assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
144                dictFile.delete();
145            }
146        }
147    }
148
149    public void testStressTestForSwitchingLanguagesAndAddingWords() {
150        final int numberOfLanguages = 2;
151        final int numberOfLanguageSwitching = 80;
152        final int numberOfWordsInsertedForEachLanguageSwitch = 100;
153
154        final File dictFiles[] = new File[numberOfLanguages];
155        final String testFilenameSuffixes[] = new String[numberOfLanguages];
156        try {
157            final Random random = new Random(123456);
158
159            // Create filename suffixes for this test.
160            for (int i = 0; i < numberOfLanguages; i++) {
161                testFilenameSuffixes[i] = "testSwitchingLanguages" + i;
162                final String fileName = UserHistoryPredictionDictionary.NAME + "." +
163                        testFilenameSuffixes[i] + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
164                dictFiles[i] = new File(getContext().getFilesDir(), fileName);
165            }
166
167            final long start = System.currentTimeMillis();
168
169            for (int i = 0; i < numberOfLanguageSwitching; i++) {
170                final int index = i % numberOfLanguages;
171                // Switch languages to testFilenameSuffixes[index].
172                addAndWriteRandomWords(testFilenameSuffixes[index],
173                        numberOfWordsInsertedForEachLanguageSwitch, random,
174                        false /* checksContents */);
175            }
176
177            final long end = System.currentTimeMillis();
178            Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
179                    + (end - start) + " ms");
180        } finally {
181            try {
182                Log.d(TAG, "waiting for writing ...");
183                for (int i = 0; i < numberOfLanguages; i++) {
184                    final UserHistoryPredictionDictionary dict =
185                            PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
186                                    testFilenameSuffixes[i], mPrefs);
187                    dict.shutdownExecutorForTests();
188                    while (!dict.isTerminatedForTests()) {
189                        Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
190                    }
191                }
192            } catch (InterruptedException e) {
193                Log.d(TAG, "InterruptedException: " + e);
194            }
195            for (final File file : dictFiles) {
196                if (file != null) {
197                    assertTrue(file.exists());
198                    assertTrue(file.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
199                    file.delete();
200                }
201            }
202        }
203    }
204
205    public void testAddManyWords() {
206        File dictFile = null;
207        final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis();
208        final int numberOfWords =
209                ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ?
210                        10000 : 1000;
211        final Random random = new Random(123456);
212
213        UserHistoryPredictionDictionary dict =
214                PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(),
215                        testFilenameSuffix, mPrefs);
216        try {
217            addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random,
218                    true /* checksContents */);
219            dict.close();
220        } finally {
221            try {
222                Log.d(TAG, "waiting for writing ...");
223                dict.shutdownExecutorForTests();
224                while (!dict.isTerminatedForTests()) {
225                    Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS);
226                }
227            } catch (InterruptedException e) {
228                Log.d(TAG, "InterruptedException: ", e);
229            }
230            final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix
231                    + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
232            dictFile = new File(getContext().getFilesDir(), fileName);
233            if (dictFile != null) {
234                assertTrue(dictFile.exists());
235                assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE);
236                dictFile.delete();
237            }
238        }
239    }
240
241}
242