112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani/*
212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * Copyright (C) 2014 The Android Open Source Project
312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani *
412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * Licensed under the Apache License, Version 2.0 (the "License");
512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * you may not use this file except in compliance with the License.
612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * You may obtain a copy of the License at
712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani *
812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani *      http://www.apache.org/licenses/LICENSE-2.0
912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani *
1012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * Unless required by applicable law or agreed to in writing, software
1112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * distributed under the License is distributed on an "AS IS" BASIS,
1212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * See the License for the specific language governing permissions and
1412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * limitations under the License.
1512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani */
1612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
1712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matanipackage com.android.inputmethod.latin.personalization;
1812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
1912d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport android.content.Context;
2012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
21f4686092232588781910cc4e64406c4958577e86Mohammadinamul Sheikimport com.android.inputmethod.latin.BinaryDictionary;
2212d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport com.android.inputmethod.latin.NgramContext;
2312d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport com.android.inputmethod.latin.NgramContext.WordInfo;
2412d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport com.android.inputmethod.latin.common.FileUtils;
2512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
2612d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.io.File;
2712d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.io.FilenameFilter;
2812d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.util.ArrayList;
2912d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.util.HashSet;
3012d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.util.List;
3112d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.util.Locale;
3212d63820d459edd71a46fa2495fea98b3c785f2dJatin Mataniimport java.util.Random;
3312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
3412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani/**
3512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani * Utility class for helping while running tests involving {@link UserHistoryDictionary}.
3612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani */
3712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matanipublic class UserHistoryDictionaryTestsHelper {
3812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
3912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
4012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Locale prefix for generating dummy locales for tests.
4112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
4212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    public static final String TEST_LOCALE_PREFIX = "test-";
4312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
4412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
4512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Characters for generating random words.
4612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
4712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    private static final String[] CHARACTERS = {
4812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
4912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
5012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    };
5112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
5212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
5312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Remove all the test dictionary files created for the given locale.
5412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
5512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    public static void removeAllTestDictFiles(final String filter, final Context context) {
5612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        final FilenameFilter filenameFilter = new FilenameFilter() {
5712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            @Override
5812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            public boolean accept(final File dir, final String filename) {
5912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                return filename.startsWith(UserHistoryDictionary.NAME + "." + filter);
6012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            }
6112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        };
6212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        FileUtils.deleteFilteredFiles(context.getFilesDir(), filenameFilter);
6312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
6412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
6512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
6612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Generates and writes random words to dictionary. Caller can be assured
6712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * that the write tasks would be finished; and its success would be reflected
6812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * in the returned boolean.
6912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     *
7012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param dict {@link UserHistoryDictionary} to which words should be added.
7112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param numberOfWords number of words to be added.
7212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param random helps generate random words.
7312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param checkContents if true, checks whether written words are actually in the dictionary.
7412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param currentTime timestamp that would be used for adding the words.
7512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @returns true if all words have been written to dictionary successfully.
7612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
7712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    public static boolean addAndWriteRandomWords(final UserHistoryDictionary dict,
7812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            final int numberOfWords, final Random random, final boolean checkContents,
7912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            final int currentTime) {
8012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        final List<String> words = generateWords(numberOfWords, random);
8112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        // Add random words to the user history dictionary.
8212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        addWordsToDictionary(dict, words, currentTime);
8312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        boolean success = true;
8412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        if (checkContents) {
8512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            dict.waitAllTasksForTests();
8612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            for (int i = 0; i < numberOfWords; ++i) {
8712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                final String word = words.get(i);
8812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                if (!dict.isInDictionary(word)) {
8912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                    success = false;
9012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                    break;
9112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani                }
9212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            }
9312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        }
9412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        // write to file.
9512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        dict.close();
9612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        dict.waitAllTasksForTests();
9712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        return success;
9812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
9912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
10012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    private static void addWordsToDictionary(final UserHistoryDictionary dict,
10112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            final List<String> words, final int timestamp) {
102f4686092232588781910cc4e64406c4958577e86Mohammadinamul Sheik        NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext(
103f4686092232588781910cc4e64406c4958577e86Mohammadinamul Sheik                BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM);
10412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        for (final String word : words) {
105644a709a5fec65c3ac1c96f18af397458fac7658Dan Zivkovic            UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, timestamp);
10612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
10712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        }
10812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
10912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
11012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
11112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Creates unique test locale for using within tests.
11212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
11312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    public static Locale getDummyLocale(final String name) {
11412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        return new Locale(TEST_LOCALE_PREFIX + name + System.currentTimeMillis());
11512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
11612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
11712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
11812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Generates random words.
11912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     *
12012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param numberOfWords number of words to generate.
12112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * @param random salt used for generating random words.
12212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
12312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    public static List<String> generateWords(final int numberOfWords, final Random random) {
12412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        final HashSet<String> wordSet = new HashSet<>();
12512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        while (wordSet.size() < numberOfWords) {
12612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            wordSet.add(generateWord(random.nextInt()));
12712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        }
12812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        return new ArrayList<>(wordSet);
12912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
13012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani
13112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    /**
13212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     * Generates a random word.
13312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani     */
13412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    private static String generateWord(final int value) {
13512d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        final int lengthOfChars = CHARACTERS.length;
13612d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        final StringBuilder builder = new StringBuilder();
13712d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        long lvalue = Math.abs((long)value);
13812d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        while (lvalue > 0) {
13912d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
14012d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani            lvalue /= lengthOfChars;
14112d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        }
14212d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani        return builder.toString();
14312d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani    }
14412d63820d459edd71a46fa2495fea98b3c785f2dJatin Matani}
145