• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.makedict;
18 
19 import com.android.inputmethod.latin.CollectionUtils;
20 import com.android.inputmethod.latin.UserHistoryDictIOUtils;
21 import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
22 import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
23 import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
24 import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
25 import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
26 
27 import android.test.AndroidTestCase;
28 import android.test.MoreAsserts;
29 import android.util.Log;
30 import android.util.SparseArray;
31 
32 import java.io.File;
33 import java.io.FileInputStream;
34 import java.io.FileOutputStream;
35 import java.io.IOException;
36 import java.nio.ByteBuffer;
37 import java.nio.channels.FileChannel;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Map.Entry;
44 import java.util.Random;
45 import java.util.Set;
46 
47 /**
48  * Unit tests for BinaryDictInputOutput
49  */
50 public class BinaryDictIOTests extends AndroidTestCase {
51     private static final String TAG = BinaryDictIOTests.class.getSimpleName();
52     private static final int MAX_UNIGRAMS = 1000;
53     private static final int UNIGRAM_FREQ = 10;
54     private static final int BIGRAM_FREQ = 50;
55     private static final int TOLERANCE_OF_BIGRAM_FREQ = 5;
56 
57     private static final int USE_BYTE_ARRAY = 1;
58     private static final int USE_BYTE_BUFFER = 2;
59 
60     private static final List<String> sWords = CollectionUtils.newArrayList();
61     private static final SparseArray<List<Integer>> sEmptyBigrams =
62             CollectionUtils.newSparseArray();
63     private static final SparseArray<List<Integer>> sStarBigrams = CollectionUtils.newSparseArray();
64     private static final SparseArray<List<Integer>> sChainBigrams =
65             CollectionUtils.newSparseArray();
66 
67     private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
68     private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
69             new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
70     private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
71             new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
72 
73     private static final String[] CHARACTERS = {
74         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
75         "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
76     };
77 
BinaryDictIOTests()78     public BinaryDictIOTests() {
79         super();
80 
81         final Random random = new Random(123456);
82         sWords.clear();
83         generateWords(MAX_UNIGRAMS, random);
84 
85         for (int i = 0; i < sWords.size(); ++i) {
86             sChainBigrams.put(i, new ArrayList<Integer>());
87             if (i > 0) {
88                 sChainBigrams.get(i - 1).add(i);
89             }
90         }
91 
92         sStarBigrams.put(0, new ArrayList<Integer>());
93         for (int i = 1; i < sWords.size(); ++i) {
94             sStarBigrams.get(0).add(i);
95         }
96     }
97 
98     // Utilities for test
99 
100     /**
101      * Makes new buffer according to BUFFER_TYPE.
102      */
getBuffer(final File file, final int bufferType)103     private FusionDictionaryBufferInterface getBuffer(final File file, final int bufferType) {
104         FileInputStream inStream = null;
105         try {
106             inStream = new FileInputStream(file);
107             if (bufferType == USE_BYTE_ARRAY) {
108                 final byte[] array = new byte[(int)file.length()];
109                 inStream.read(array);
110                 return new UserHistoryDictIOUtils.ByteArrayWrapper(array);
111             } else if (bufferType == USE_BYTE_BUFFER){
112                 final ByteBuffer buffer = inStream.getChannel().map(
113                         FileChannel.MapMode.READ_ONLY, 0, file.length());
114                 return new BinaryDictInputOutput.ByteBufferWrapper(buffer);
115             }
116         } catch (IOException e) {
117             Log.e(TAG, "IOException while making buffer: " + e);
118         } finally {
119             if (inStream != null) {
120                 try {
121                     inStream.close();
122                 } catch (IOException e) {
123                     Log.e(TAG, "IOException while closing stream: " + e);
124                 }
125             }
126         }
127         return null;
128     }
129 
130     /**
131      * Generates a random word.
132      */
generateWord(final int value)133     private String generateWord(final int value) {
134         final int lengthOfChars = CHARACTERS.length;
135         StringBuilder builder = new StringBuilder("a");
136         long lvalue = Math.abs((long)value);
137         while (lvalue > 0) {
138             builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
139             lvalue /= lengthOfChars;
140         }
141         return builder.toString();
142     }
143 
generateWords(final int number, final Random random)144     private void generateWords(final int number, final Random random) {
145         final Set<String> wordSet = CollectionUtils.newHashSet();
146         while (wordSet.size() < number) {
147             wordSet.add(generateWord(random.nextInt()));
148         }
149         sWords.addAll(wordSet);
150     }
151 
152     /**
153      * Adds unigrams to the dictionary.
154      */
addUnigrams(final int number, final FusionDictionary dict, final List<String> words, final Map<String, List<String>> shortcutMap)155     private void addUnigrams(final int number, final FusionDictionary dict,
156             final List<String> words, final Map<String, List<String>> shortcutMap) {
157         for (int i = 0; i < number; ++i) {
158             final String word = words.get(i);
159             final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList();
160             if (shortcutMap != null && shortcutMap.containsKey(word)) {
161                 for (final String shortcut : shortcutMap.get(word)) {
162                     shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
163                 }
164             }
165             dict.add(word, UNIGRAM_FREQ, (shortcutMap == null) ? null : shortcuts,
166                     false /* isNotAWord */);
167         }
168     }
169 
addBigrams(final FusionDictionary dict, final List<String> words, final SparseArray<List<Integer>> bigrams)170     private void addBigrams(final FusionDictionary dict,
171             final List<String> words,
172             final SparseArray<List<Integer>> bigrams) {
173         for (int i = 0; i < bigrams.size(); ++i) {
174             final int w1 = bigrams.keyAt(i);
175             for (int w2 : bigrams.valueAt(i)) {
176                 dict.setBigram(words.get(w1), words.get(w2), BIGRAM_FREQ);
177             }
178         }
179     }
180 
timeWritingDictToFile(final File file, final FusionDictionary dict, final FormatSpec.FormatOptions formatOptions)181     private long timeWritingDictToFile(final File file, final FusionDictionary dict,
182             final FormatSpec.FormatOptions formatOptions) {
183 
184         long now = -1, diff = -1;
185 
186         try {
187             final FileOutputStream out = new FileOutputStream(file);
188 
189             now = System.currentTimeMillis();
190             BinaryDictInputOutput.writeDictionaryBinary(out, dict, formatOptions);
191             diff = System.currentTimeMillis() - now;
192 
193             out.flush();
194             out.close();
195         } catch (IOException e) {
196             Log.e(TAG, "IO exception while writing file: " + e);
197         } catch (UnsupportedFormatException e) {
198             Log.e(TAG, "UnsupportedFormatException: " + e);
199         }
200 
201         return diff;
202     }
203 
checkDictionary(final FusionDictionary dict, final List<String> words, final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap)204     private void checkDictionary(final FusionDictionary dict, final List<String> words,
205             final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap) {
206         assertNotNull(dict);
207 
208         // check unigram
209         for (final String word : words) {
210             final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, word);
211             assertNotNull(cg);
212         }
213 
214         // check bigram
215         for (int i = 0; i < bigrams.size(); ++i) {
216             final int w1 = bigrams.keyAt(i);
217             for (final int w2 : bigrams.valueAt(i)) {
218                 final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, words.get(w1));
219                 assertNotNull(words.get(w1) + "," + words.get(w2), cg.getBigram(words.get(w2)));
220             }
221         }
222 
223         // check shortcut
224         if (shortcutMap != null) {
225             for (final Map.Entry<String, List<String>> entry : shortcutMap.entrySet()) {
226                 final CharGroup group = FusionDictionary.findWordInTree(dict.mRoot, entry.getKey());
227                 for (final String word : entry.getValue()) {
228                     assertNotNull("shortcut not found: " + entry.getKey() + ", " + word,
229                             group.getShortcut(word));
230                 }
231             }
232         }
233     }
234 
outputOptions(final int bufferType, final FormatSpec.FormatOptions formatOptions)235     private String outputOptions(final int bufferType,
236             final FormatSpec.FormatOptions formatOptions) {
237         String result = " : buffer type = "
238                 + ((bufferType == USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
239         result += " : version = " + formatOptions.mVersion;
240         return result + ", supportsDynamicUpdate = " + formatOptions.mSupportsDynamicUpdate;
241     }
242 
243     // Tests for readDictionaryBinary and writeDictionaryBinary
244 
timeReadingAndCheckDict(final File file, final List<String> words, final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap, final int bufferType)245     private long timeReadingAndCheckDict(final File file, final List<String> words,
246             final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap,
247             final int bufferType) {
248         long now, diff = -1;
249         final FusionDictionaryBufferInterface buffer = getBuffer(file, bufferType);
250         assertNotNull(buffer);
251 
252         FusionDictionary dict = null;
253         try {
254             now = System.currentTimeMillis();
255             dict = BinaryDictInputOutput.readDictionaryBinary(buffer, null);
256             diff  = System.currentTimeMillis() - now;
257         } catch (IOException e) {
258             Log.e(TAG, "IOException while reading dictionary: " + e);
259         } catch (UnsupportedFormatException e) {
260             Log.e(TAG, "Unsupported format: " + e);
261         }
262 
263         checkDictionary(dict, words, bigrams, shortcutMap);
264         return diff;
265     }
266 
267     // Tests for readDictionaryBinary and writeDictionaryBinary
runReadAndWrite(final List<String> words, final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcuts, final int bufferType, final FormatSpec.FormatOptions formatOptions, final String message)268     private String runReadAndWrite(final List<String> words,
269             final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcuts,
270             final int bufferType, final FormatSpec.FormatOptions formatOptions,
271             final String message) {
272         File file = null;
273         try {
274             file = File.createTempFile("runReadAndWrite", ".dict");
275         } catch (IOException e) {
276             Log.e(TAG, "IOException: " + e);
277         }
278         assertNotNull(file);
279 
280         final FusionDictionary dict = new FusionDictionary(new Node(),
281                 new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
282         addUnigrams(words.size(), dict, words, shortcuts);
283         addBigrams(dict, words, bigrams);
284         checkDictionary(dict, words, bigrams, shortcuts);
285 
286         final long write = timeWritingDictToFile(file, dict, formatOptions);
287         final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType);
288 
289         return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
290                 + " : " + outputOptions(bufferType, formatOptions);
291     }
292 
runReadAndWriteTests(final List<String> results, final int bufferType, final FormatSpec.FormatOptions formatOptions)293     private void runReadAndWriteTests(final List<String> results, final int bufferType,
294             final FormatSpec.FormatOptions formatOptions) {
295         results.add(runReadAndWrite(sWords, sEmptyBigrams, null /* shortcuts */, bufferType,
296                 formatOptions, "unigram"));
297         results.add(runReadAndWrite(sWords, sChainBigrams, null /* shortcuts */, bufferType,
298                 formatOptions, "chain"));
299         results.add(runReadAndWrite(sWords, sStarBigrams, null /* shortcuts */, bufferType,
300                 formatOptions, "star"));
301     }
302 
testReadAndWriteWithByteBuffer()303     public void testReadAndWriteWithByteBuffer() {
304         final List<String> results = CollectionUtils.newArrayList();
305 
306         runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION2);
307         runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
308         runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
309 
310         for (final String result : results) {
311             Log.d(TAG, result);
312         }
313     }
314 
testReadAndWriteWithByteArray()315     public void testReadAndWriteWithByteArray() {
316         final List<String> results = CollectionUtils.newArrayList();
317 
318         runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION2);
319         runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
320         runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
321 
322         for (final String result : results) {
323             Log.d(TAG, result);
324         }
325     }
326 
327     // Tests for readUnigramsAndBigramsBinary
328 
checkWordMap(final List<String> expectedWords, final SparseArray<List<Integer>> expectedBigrams, final Map<Integer, String> resultWords, final Map<Integer, Integer> resultFrequencies, final Map<Integer, ArrayList<PendingAttribute>> resultBigrams)329     private void checkWordMap(final List<String> expectedWords,
330             final SparseArray<List<Integer>> expectedBigrams,
331             final Map<Integer, String> resultWords,
332             final Map<Integer, Integer> resultFrequencies,
333             final Map<Integer, ArrayList<PendingAttribute>> resultBigrams) {
334         // check unigrams
335         final Set<String> actualWordsSet = new HashSet<String>(resultWords.values());
336         final Set<String> expectedWordsSet = new HashSet<String>(expectedWords);
337         assertEquals(actualWordsSet, expectedWordsSet);
338 
339         for (int freq : resultFrequencies.values()) {
340             assertEquals(freq, UNIGRAM_FREQ);
341         }
342 
343         // check bigrams
344         final Map<String, List<String>> expBigrams = new HashMap<String, List<String>>();
345         for (int i = 0; i < expectedBigrams.size(); ++i) {
346             final String word1 = expectedWords.get(expectedBigrams.keyAt(i));
347             for (int w2 : expectedBigrams.valueAt(i)) {
348                 if (expBigrams.get(word1) == null) {
349                     expBigrams.put(word1, new ArrayList<String>());
350                 }
351                 expBigrams.get(word1).add(expectedWords.get(w2));
352             }
353         }
354 
355         final Map<String, List<String>> actBigrams = new HashMap<String, List<String>>();
356         for (Entry<Integer, ArrayList<PendingAttribute>> entry : resultBigrams.entrySet()) {
357             final String word1 = resultWords.get(entry.getKey());
358             final int unigramFreq = resultFrequencies.get(entry.getKey());
359             for (PendingAttribute attr : entry.getValue()) {
360                 final String word2 = resultWords.get(attr.mAddress);
361                 if (actBigrams.get(word1) == null) {
362                     actBigrams.put(word1, new ArrayList<String>());
363                 }
364                 actBigrams.get(word1).add(word2);
365 
366                 final int bigramFreq = BinaryDictInputOutput.reconstructBigramFrequency(
367                         unigramFreq, attr.mFrequency);
368                 assertTrue(Math.abs(bigramFreq - BIGRAM_FREQ) < TOLERANCE_OF_BIGRAM_FREQ);
369             }
370         }
371 
372         assertEquals(actBigrams, expBigrams);
373     }
374 
375     private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
376             final SparseArray<List<Integer>> bigrams, final int bufferType) {
377         FileInputStream inStream = null;
378 
379         final Map<Integer, String> resultWords = CollectionUtils.newTreeMap();
380         final Map<Integer, ArrayList<PendingAttribute>> resultBigrams =
381                 CollectionUtils.newTreeMap();
382         final Map<Integer, Integer> resultFreqs = CollectionUtils.newTreeMap();
383 
384         long now = -1, diff = -1;
385         final FusionDictionaryBufferInterface buffer = getBuffer(file, bufferType);
386         assertNotNull("Can't get buffer.", buffer);
387         try {
388             now = System.currentTimeMillis();
389             BinaryDictIOUtils.readUnigramsAndBigramsBinary(buffer, resultWords, resultFreqs,
390                     resultBigrams);
391             diff = System.currentTimeMillis() - now;
392         } catch (IOException e) {
393             Log.e(TAG, "IOException " + e);
394         } catch (UnsupportedFormatException e) {
395             Log.e(TAG, "UnsupportedFormatException: " + e);
396         } finally {
397             if (inStream != null) {
398                 try {
399                     inStream.close();
400                 } catch (IOException e) {
401                     // do nothing
402                 }
403             }
404         }
405 
406         checkWordMap(words, bigrams, resultWords, resultFreqs, resultBigrams);
407         return diff;
408     }
409 
410     private String runReadUnigramsAndBigramsBinary(final List<String> words,
411             final SparseArray<List<Integer>> bigrams, final int bufferType,
412             final FormatSpec.FormatOptions formatOptions, final String message) {
413         File file = null;
414         try {
415             file = File.createTempFile("runReadUnigrams", ".dict");
416         } catch (IOException e) {
417             Log.e(TAG, "IOException: " + e);
418         }
419         assertNotNull(file);
420 
421         // making the dictionary from lists of words.
422         final FusionDictionary dict = new FusionDictionary(new Node(),
423                 new FusionDictionary.DictionaryOptions(
424                         new HashMap<String, String>(), false, false));
425         addUnigrams(words.size(), dict, words, null /* shortcutMap */);
426         addBigrams(dict, words, bigrams);
427 
428         timeWritingDictToFile(file, dict, formatOptions);
429 
430         long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType);
431         long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
432                 bufferType);
433 
434         return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
435                 + " : " + message + " : " + outputOptions(bufferType, formatOptions);
436     }
437 
438     private void runReadUnigramsAndBigramsTests(final List<String> results, final int bufferType,
439             final FormatSpec.FormatOptions formatOptions) {
440         results.add(runReadUnigramsAndBigramsBinary(sWords, sEmptyBigrams, bufferType,
441                 formatOptions, "unigram"));
442         results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
443                 formatOptions, "chain"));
444         results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
445                 formatOptions, "star"));
446     }
447 
448     public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
449         final List<String> results = CollectionUtils.newArrayList();
450 
451         runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2);
452         runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
453         runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
454 
455         for (final String result : results) {
456             Log.d(TAG, result);
457         }
458     }
459 
460     public void testReadUnigramsAndBigramsBinaryWithByteArray() {
461         final List<String> results = CollectionUtils.newArrayList();
462 
463         runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2);
464         runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
465         runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
466 
467         for (final String result : results) {
468             Log.d(TAG, result);
469         }
470     }
471 
472     // Tests for getTerminalPosition
473     private String getWordFromBinary(final FusionDictionaryBufferInterface buffer,
474             final int address) {
475         if (buffer.position() != 0) buffer.position(0);
476 
477         FileHeader header = null;
478         try {
479             header = BinaryDictInputOutput.readHeader(buffer);
480         } catch (IOException e) {
481             return null;
482         } catch (UnsupportedFormatException e) {
483             return null;
484         }
485         if (header == null) return null;
486         return BinaryDictInputOutput.getWordAtAddress(buffer, header.mHeaderSize,
487                 address - header.mHeaderSize, header.mFormatOptions);
488     }
489 
490     private long runGetTerminalPosition(final FusionDictionaryBufferInterface buffer,
491             final String word, int index, boolean contained) {
492         final int expectedFrequency = (UNIGRAM_FREQ + index) % 255;
493         long diff = -1;
494         int position = -1;
495         try {
496             final long now = System.nanoTime();
497             position = BinaryDictIOUtils.getTerminalPosition(buffer, word);
498             diff = System.nanoTime() - now;
499         } catch (IOException e) {
500             Log.e(TAG, "IOException while getTerminalPosition: " + e);
501         } catch (UnsupportedFormatException e) {
502             Log.e(TAG, "UnsupportedFormatException while getTermianlPosition: " + e);
503         }
504 
505         assertEquals(FormatSpec.NOT_VALID_WORD != position, contained);
506         if (contained) assertEquals(getWordFromBinary(buffer, position), word);
507         return diff;
508     }
509 
510     public void testGetTerminalPosition() {
511         File file = null;
512         try {
513             file = File.createTempFile("testGetTerminalPosition", ".dict");
514         } catch (IOException e) {
515             // do nothing
516         }
517         assertNotNull(file);
518 
519         final FusionDictionary dict = new FusionDictionary(new Node(),
520                 new FusionDictionary.DictionaryOptions(
521                         new HashMap<String, String>(), false, false));
522         addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
523         timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE);
524 
525         final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY);
526 
527         try {
528             // too long word
529             final String longWord = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
530             assertEquals(FormatSpec.NOT_VALID_WORD,
531                     BinaryDictIOUtils.getTerminalPosition(buffer, longWord));
532 
533             // null
534             assertEquals(FormatSpec.NOT_VALID_WORD,
535                     BinaryDictIOUtils.getTerminalPosition(buffer, null));
536 
537             // empty string
538             assertEquals(FormatSpec.NOT_VALID_WORD,
539                     BinaryDictIOUtils.getTerminalPosition(buffer, ""));
540         } catch (IOException e) {
541         } catch (UnsupportedFormatException e) {
542         }
543 
544         // Test a word that is contained within the dictionary.
545         long sum = 0;
546         for (int i = 0; i < sWords.size(); ++i) {
547             final long time = runGetTerminalPosition(buffer, sWords.get(i), i, true);
548             sum += time == -1 ? 0 : time;
549         }
550         Log.d(TAG, "per a search : " + (((double)sum) / sWords.size() / 1000000));
551 
552         // Test a word that isn't contained within the dictionary.
553         final Random random = new Random((int)System.currentTimeMillis());
554         for (int i = 0; i < 1000; ++i) {
555             final String word = generateWord(random.nextInt());
556             if (sWords.indexOf(word) != -1) continue;
557             runGetTerminalPosition(buffer, word, i, false);
558         }
559     }
560 
561     public void testDeleteWord() {
562         File file = null;
563         try {
564             file = File.createTempFile("testDeleteWord", ".dict");
565         } catch (IOException e) {
566             // do nothing
567         }
568         assertNotNull(file);
569 
570         final FusionDictionary dict = new FusionDictionary(new Node(),
571                 new FusionDictionary.DictionaryOptions(
572                         new HashMap<String, String>(), false, false));
573         addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
574         timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE);
575 
576         final FusionDictionaryBufferInterface buffer = getBuffer(file, USE_BYTE_ARRAY);
577 
578         try {
579             MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
580                     BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0)));
581             BinaryDictIOUtils.deleteWord(buffer, sWords.get(0));
582             assertEquals(FormatSpec.NOT_VALID_WORD,
583                     BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(0)));
584 
585             MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
586                     BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5)));
587             BinaryDictIOUtils.deleteWord(buffer, sWords.get(5));
588             assertEquals(FormatSpec.NOT_VALID_WORD,
589                     BinaryDictIOUtils.getTerminalPosition(buffer, sWords.get(5)));
590         } catch (IOException e) {
591         } catch (UnsupportedFormatException e) {
592         }
593     }
594 }
595