1/*
2 * Copyright (C) 2014 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 java.io.File;
20import java.util.ArrayList;
21import java.util.HashMap;
22import java.util.Locale;
23import java.util.Map;
24import java.util.Random;
25import java.util.concurrent.CountDownLatch;
26import java.util.concurrent.TimeUnit;
27
28import com.android.inputmethod.latin.BinaryDictionary;
29import com.android.inputmethod.latin.Dictionary;
30import com.android.inputmethod.latin.DictionaryFacilitator;
31import com.android.inputmethod.latin.ExpandableBinaryDictionary;
32import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
33import com.android.inputmethod.latin.makedict.CodePointUtils;
34import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
35
36import android.test.AndroidTestCase;
37import android.test.suitebuilder.annotation.LargeTest;
38import android.util.Log;
39
40/**
41 * Unit tests for personalization dictionary
42 */
43@LargeTest
44public class PersonalizationDictionaryTests extends AndroidTestCase {
45    private static final String TAG = PersonalizationDictionaryTests.class.getSimpleName();
46
47    private static final Locale LOCALE_EN_US = new Locale("en", "US");
48    private static final String DUMMY_PACKAGE_NAME = "test.package.name";
49    private static final long TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS = 120;
50
51    private DictionaryFacilitator getDictionaryFacilitator() {
52        final ArrayList<String> dictTypes = new ArrayList<>();
53        dictTypes.add(Dictionary.TYPE_MAIN);
54        dictTypes.add(Dictionary.TYPE_PERSONALIZATION);
55        final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
56        dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
57                new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
58        return dictionaryFacilitator;
59    }
60
61    public void testAddManyTokens() {
62        final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
63        dictionaryFacilitator.clearPersonalizationDictionary();
64        final int dataChunkCount = 20;
65        final int wordCountInOneChunk = 2000;
66        final Random random = new Random(System.currentTimeMillis());
67        final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
68
69        final SpacingAndPunctuations spacingAndPunctuations =
70                new SpacingAndPunctuations(getContext().getResources());
71
72        final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
73                System.currentTimeMillis());
74
75        for (int i = 0; i < dataChunkCount; i++) {
76            final ArrayList<String> tokens = new ArrayList<>();
77            for (int j = 0; j < wordCountInOneChunk; j++) {
78                tokens.add(CodePointUtils.generateWord(random, codePointSet));
79            }
80            final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk(
81                    true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME);
82            final CountDownLatch countDownLatch = new CountDownLatch(1);
83            final AddMultipleDictionaryEntriesCallback callback =
84                    new AddMultipleDictionaryEntriesCallback() {
85                        @Override
86                        public void onFinished() {
87                            countDownLatch.countDown();
88                        }
89                    };
90            dictionaryFacilitator.addEntriesToPersonalizationDictionary(personalizationDataChunk,
91                    spacingAndPunctuations, callback);
92            try {
93                countDownLatch.await(TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS,
94                        TimeUnit.SECONDS);
95            } catch (InterruptedException e) {
96                Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
97            }
98        }
99        dictionaryFacilitator.flushPersonalizationDictionary();
100        try {
101            dictionaryFacilitator.waitForLoadingDictionariesForTesting(
102                    TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS, TimeUnit.SECONDS);
103        } catch (InterruptedException e) {
104            Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
105        }
106        final String dictName = ExpandableBinaryDictionary.getDictName(
107                PersonalizationDictionary.NAME, LOCALE_EN_US, null /* dictFile */);
108        final File dictFile = ExpandableBinaryDictionary.getDictFile(
109                getContext(), dictName, null /* dictFile */);
110
111        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
112                0 /* offset */, 0 /* size */,
113                true /* useFullEditDistance */, LOCALE_EN_US, Dictionary.TYPE_PERSONALIZATION,
114                true /* isUpdatable */);
115        assertTrue(binaryDictionary.isValidDictionary());
116    }
117}
118