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; 18 19 import android.content.Context; 20 import android.test.AndroidTestCase; 21 import android.test.suitebuilder.annotation.LargeTest; 22 import android.util.Log; 23 24 import com.android.inputmethod.latin.UserHistoryDictIOUtils.BigramDictionaryInterface; 25 import com.android.inputmethod.latin.UserHistoryDictIOUtils.OnAddWordListener; 26 import com.android.inputmethod.latin.makedict.FormatSpec; 27 import com.android.inputmethod.latin.makedict.FusionDictionary; 28 import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; 29 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.HashMap; 38 39 /** 40 * Unit tests for UserHistoryDictIOUtils 41 */ 42 @LargeTest 43 public class UserHistoryDictIOUtilsTests extends AndroidTestCase 44 implements BigramDictionaryInterface { 45 46 private static final String TAG = UserHistoryDictIOUtilsTests.class.getSimpleName(); 47 private static final int UNIGRAM_FREQUENCY = 50; 48 private static final int BIGRAM_FREQUENCY = 100; 49 private static final ArrayList<String> NOT_HAVE_BIGRAM = new ArrayList<String>(); 50 private static final FormatSpec.FormatOptions FORMAT_OPTIONS = new FormatSpec.FormatOptions(2); 51 52 /** 53 * Return same frequency for all words and bigrams 54 */ 55 @Override 56 public int getFrequency(String word1, String word2) { 57 if (word1 == null) return UNIGRAM_FREQUENCY; 58 return BIGRAM_FREQUENCY; 59 } 60 61 // Utilities for Testing 62 63 private void addWord(final String word, 64 final HashMap<String, ArrayList<String> > addedWords) { 65 if (!addedWords.containsKey(word)) { 66 addedWords.put(word, new ArrayList<String>()); 67 } 68 } 69 70 private void addBigram(final String word1, final String word2, 71 final HashMap<String, ArrayList<String> > addedWords) { 72 addWord(word1, addedWords); 73 addWord(word2, addedWords); 74 addedWords.get(word1).add(word2); 75 } 76 77 private void addBigramToBigramList(final String word1, final String word2, 78 final HashMap<String, ArrayList<String> > addedWords, 79 final UserHistoryDictionaryBigramList bigramList) { 80 bigramList.addBigram(null, word1); 81 bigramList.addBigram(word1, word2); 82 83 addBigram(word1, word2, addedWords); 84 } 85 86 private void checkWordInFusionDict(final FusionDictionary dict, final String word, 87 final ArrayList<String> expectedBigrams) { 88 final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, word); 89 assertNotNull(group); 90 assertTrue(group.isTerminal()); 91 92 for (final String bigram : expectedBigrams) { 93 assertNotNull(group.getBigram(bigram)); 94 } 95 } 96 97 private void checkWordsInFusionDict(final FusionDictionary dict, 98 final HashMap<String, ArrayList<String> > bigrams) { 99 for (final String word : bigrams.keySet()) { 100 if (bigrams.containsKey(word)) { 101 checkWordInFusionDict(dict, word, bigrams.get(word)); 102 } else { 103 checkWordInFusionDict(dict, word, NOT_HAVE_BIGRAM); 104 } 105 } 106 } 107 108 private void checkWordInBigramList( 109 final UserHistoryDictionaryBigramList bigramList, final String word, 110 final ArrayList<String> expectedBigrams) { 111 // check unigram 112 final HashMap<String,Byte> unigramMap = bigramList.getBigrams(null); 113 assertTrue(unigramMap.containsKey(word)); 114 115 // check bigrams 116 final ArrayList<String> actualBigrams = new ArrayList<String>( 117 bigramList.getBigrams(word).keySet()); 118 119 Collections.sort(expectedBigrams); 120 Collections.sort(actualBigrams); 121 assertEquals(expectedBigrams, actualBigrams); 122 } 123 124 private void checkWordsInBigramList(final UserHistoryDictionaryBigramList bigramList, 125 final HashMap<String, ArrayList<String> > addedWords) { 126 for (final String word : addedWords.keySet()) { 127 if (addedWords.containsKey(word)) { 128 checkWordInBigramList(bigramList, word, addedWords.get(word)); 129 } else { 130 checkWordInBigramList(bigramList, word, NOT_HAVE_BIGRAM); 131 } 132 } 133 } 134 135 private void writeDictToFile(final File file, 136 final UserHistoryDictionaryBigramList bigramList) { 137 try { 138 final FileOutputStream out = new FileOutputStream(file); 139 UserHistoryDictIOUtils.writeDictionaryBinary(out, this, bigramList, FORMAT_OPTIONS); 140 out.flush(); 141 out.close(); 142 } catch (IOException e) { 143 Log.e(TAG, "IO exception while writing file", e); 144 } 145 } 146 147 private void readDictFromFile(final File file, final OnAddWordListener listener) { 148 FileInputStream inStream = null; 149 150 try { 151 inStream = new FileInputStream(file); 152 final byte[] buffer = new byte[(int)file.length()]; 153 inStream.read(buffer); 154 155 UserHistoryDictIOUtils.readDictionaryBinary( 156 new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener); 157 } catch (FileNotFoundException e) { 158 Log.e(TAG, "file not found", e); 159 } catch (IOException e) { 160 Log.e(TAG, "IOException", e); 161 } finally { 162 if (inStream != null) { 163 try { 164 inStream.close(); 165 } catch (IOException e) { 166 // do nothing 167 } 168 } 169 } 170 } 171 172 public void testGenerateFusionDictionary() { 173 final UserHistoryDictionaryBigramList originalList = new UserHistoryDictionaryBigramList(); 174 175 final HashMap<String, ArrayList<String> > addedWords = 176 new HashMap<String, ArrayList<String>>(); 177 addBigramToBigramList("this", "is", addedWords, originalList); 178 addBigramToBigramList("this", "was", addedWords, originalList); 179 addBigramToBigramList("hello", "world", addedWords, originalList); 180 181 final FusionDictionary fusionDict = 182 UserHistoryDictIOUtils.constructFusionDictionary(this, originalList); 183 184 checkWordsInFusionDict(fusionDict, addedWords); 185 } 186 187 public void testReadAndWrite() { 188 final Context context = getContext(); 189 190 File file = null; 191 try { 192 file = File.createTempFile("testReadAndWrite", ".dict", getContext().getCacheDir()); 193 } catch (IOException e) { 194 Log.d(TAG, "IOException while creating a temporary file", e); 195 } 196 assertNotNull(file); 197 198 // make original dictionary 199 final UserHistoryDictionaryBigramList originalList = new UserHistoryDictionaryBigramList(); 200 final HashMap<String, ArrayList<String>> addedWords = CollectionUtils.newHashMap(); 201 addBigramToBigramList("this" , "is" , addedWords, originalList); 202 addBigramToBigramList("this" , "was" , addedWords, originalList); 203 addBigramToBigramList("is" , "not" , addedWords, originalList); 204 addBigramToBigramList("hello", "world", addedWords, originalList); 205 206 // write to file 207 writeDictToFile(file, originalList); 208 209 // make result dict. 210 final UserHistoryDictionaryBigramList resultList = new UserHistoryDictionaryBigramList(); 211 final OnAddWordListener listener = new OnAddWordListener() { 212 @Override 213 public void setUnigram(final String word, 214 final String shortcutTarget, final int frequency) { 215 Log.d(TAG, "in: setUnigram: " + word + "," + frequency); 216 resultList.addBigram(null, word, (byte)frequency); 217 } 218 @Override 219 public void setBigram(final String word1, final String word2, final int frequency) { 220 Log.d(TAG, "in: setBigram: " + word1 + "," + word2 + "," + frequency); 221 resultList.addBigram(word1, word2, (byte)frequency); 222 } 223 }; 224 225 // load from file 226 readDictFromFile(file, listener); 227 checkWordsInBigramList(resultList, addedWords); 228 229 // add new bigram 230 addBigramToBigramList("hello", "java", addedWords, resultList); 231 232 // rewrite 233 writeDictToFile(file, resultList); 234 final UserHistoryDictionaryBigramList resultList2 = new UserHistoryDictionaryBigramList(); 235 final OnAddWordListener listener2 = new OnAddWordListener() { 236 @Override 237 public void setUnigram(final String word, 238 final String shortcutTarget, final int frequency) { 239 Log.d(TAG, "in: setUnigram: " + word + "," + frequency); 240 resultList2.addBigram(null, word, (byte)frequency); 241 } 242 @Override 243 public void setBigram(final String word1, final String word2, final int frequency) { 244 Log.d(TAG, "in: setBigram: " + word1 + "," + word2 + "," + frequency); 245 resultList2.addBigram(word1, word2, (byte)frequency); 246 } 247 }; 248 249 // load from file 250 readDictFromFile(file, listener2); 251 checkWordsInBigramList(resultList2, addedWords); 252 } 253 } 254