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