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
17package com.android.inputmethod.latin.makedict;
18
19import com.android.inputmethod.latin.CollectionUtils;
20import com.android.inputmethod.latin.UserHistoryDictIOUtils;
21import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
22import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
23import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
24import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
25import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
26
27import android.test.AndroidTestCase;
28import android.test.MoreAsserts;
29import android.util.Log;
30import android.util.SparseArray;
31
32import java.io.File;
33import java.io.FileInputStream;
34import java.io.FileOutputStream;
35import java.io.IOException;
36import java.nio.ByteBuffer;
37import java.nio.channels.FileChannel;
38import java.util.ArrayList;
39import java.util.HashMap;
40import java.util.HashSet;
41import java.util.List;
42import java.util.Map;
43import java.util.Map.Entry;
44import java.util.Random;
45import java.util.Set;
46
47/**
48 * Unit tests for BinaryDictInputOutput
49 */
50public 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
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     */
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     */
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
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     */
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
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
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
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
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
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
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
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
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
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
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