diff options
Diffstat (limited to 'tests/src')
8 files changed, 581 insertions, 176 deletions
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java new file mode 100644 index 000000000..b2d31c21f --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import com.android.inputmethod.latin.makedict.FormatSpec; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +@LargeTest +public class BinaryDictionaryDecayingTests extends AndroidTestCase { + private static final String TEST_DICT_FILE_EXTENSION = ".testDict"; + private static final String TEST_LOCALE = "test"; + + // Note that these are corresponding definitions in native code in + // latinime::DynamicPatriciaTriePolicy. + private static final String SET_NEEDS_TO_DECAY_FOR_TESTING_KEY = + "SET_NEEDS_TO_DECAY_FOR_TESTING"; + + private static final int DUMMY_PROBABILITY = 0; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + private void forcePassingShortTime(final BinaryDictionary binaryDictionary) { + // Entries having low probability would be suppressed once in 2 GCs. + final int count = 2; + for (int i = 0; i < count; i++) { + binaryDictionary.getPropertyForTests(SET_NEEDS_TO_DECAY_FOR_TESTING_KEY); + binaryDictionary.flushWithGC(); + } + } + + private void forcePassingLongTime(final BinaryDictionary binaryDictionary) { + // Currently, probabilities are decayed when GC is run. All entries that have never been + // typed in 128 GCs would be removed. + final int count = 128; + for (int i = 0; i < count; i++) { + binaryDictionary.getPropertyForTests(SET_NEEDS_TO_DECAY_FOR_TESTING_KEY); + binaryDictionary.flushWithGC(); + } + } + + private File createEmptyDictionaryAndGetFile(final String filename) throws IOException { + final File file = File.createTempFile(filename, TEST_DICT_FILE_EXTENSION, + getContext().getCacheDir()); + Map<String, String> attributeMap = new HashMap<String, String>(); + attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE, + FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); + attributeMap.put(FormatSpec.FileHeader.USES_FORGETTING_CURVE_ATTRIBUTE, + FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); + if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + 3 /* dictVersion */, attributeMap)) { + return file; + } else { + throw new IOException("Empty dictionary cannot be created."); + } + } + + public void testAddValidAndInvalidWords() { + File dictFile = null; + try { + dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), + 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + binaryDictionary.addUnigramWord("a", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidWord("a")); + binaryDictionary.addUnigramWord("a", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidWord("a")); + binaryDictionary.addUnigramWord("a", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidWord("a")); + binaryDictionary.addUnigramWord("a", Dictionary.NOT_A_PROBABILITY); + assertTrue(binaryDictionary.isValidWord("a")); + + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + assertTrue(binaryDictionary.isValidWord("b")); + + final int unigramProbability = binaryDictionary.getFrequency("a"); + binaryDictionary.addBigramWords("a", "b", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidBigram("a", "b")); + binaryDictionary.addBigramWords("a", "b", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidBigram("a", "b")); + binaryDictionary.addBigramWords("a", "b", Dictionary.NOT_A_PROBABILITY); + assertFalse(binaryDictionary.isValidBigram("a", "b")); + binaryDictionary.addBigramWords("a", "b", Dictionary.NOT_A_PROBABILITY); + assertTrue(binaryDictionary.isValidBigram("a", "b")); + + binaryDictionary.addUnigramWord("c", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "c", DUMMY_PROBABILITY); + assertTrue(binaryDictionary.isValidBigram("a", "c")); + + binaryDictionary.close(); + dictFile.delete(); + } + + // TODO: Add large tests. + public void testDecayingProbability() { + File dictFile = null; + try { + dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), + 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + assertTrue(binaryDictionary.isValidWord("a")); + forcePassingShortTime(binaryDictionary); + assertFalse(binaryDictionary.isValidWord("a")); + + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + forcePassingShortTime(binaryDictionary); + assertTrue(binaryDictionary.isValidWord("a")); + forcePassingLongTime(binaryDictionary); + assertFalse(binaryDictionary.isValidWord("a")); + + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "b", DUMMY_PROBABILITY); + assertTrue(binaryDictionary.isValidBigram("a", "b")); + forcePassingShortTime(binaryDictionary); + assertFalse(binaryDictionary.isValidBigram("a", "b")); + + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "b", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "b", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "b", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("a", DUMMY_PROBABILITY); + binaryDictionary.addUnigramWord("b", DUMMY_PROBABILITY); + binaryDictionary.addBigramWords("a", "b", DUMMY_PROBABILITY); + assertTrue(binaryDictionary.isValidBigram("a", "b")); + forcePassingShortTime(binaryDictionary); + assertTrue(binaryDictionary.isValidBigram("a", "b")); + forcePassingLongTime(binaryDictionary); + assertFalse(binaryDictionary.isValidBigram("a", "b")); + + binaryDictionary.close(); + dictFile.delete(); + } +} diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java index 96a2217a3..6a21522f9 100644 --- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java @@ -21,24 +21,19 @@ import android.test.suitebuilder.annotation.LargeTest; import android.util.Pair; import com.android.inputmethod.latin.makedict.CodePointUtils; -import com.android.inputmethod.latin.makedict.DictEncoder; import com.android.inputmethod.latin.makedict.FormatSpec; -import com.android.inputmethod.latin.makedict.FusionDictionary; -import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; -import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.makedict.Ver3DictEncoder; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; +import java.util.Map; import java.util.Random; @LargeTest public class BinaryDictionaryTests extends AndroidTestCase { - private static final FormatSpec.FormatOptions FORMAT_OPTIONS = - new FormatSpec.FormatOptions(3 /* version */, true /* supportsDynamicUpdate */); private static final String TEST_DICT_FILE_EXTENSION = ".testDict"; private static final String TEST_LOCALE = "test"; @@ -52,15 +47,18 @@ public class BinaryDictionaryTests extends AndroidTestCase { super.tearDown(); } - private File createEmptyDictionaryAndGetFile(final String filename) throws IOException, - UnsupportedFormatException { - final FusionDictionary dict = new FusionDictionary(new PtNodeArray(), - new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false)); + private File createEmptyDictionaryAndGetFile(final String filename) throws IOException { final File file = File.createTempFile(filename, TEST_DICT_FILE_EXTENSION, getContext().getCacheDir()); - final DictEncoder dictEncoder = new Ver3DictEncoder(file); - dictEncoder.writeDictionary(dict, FORMAT_OPTIONS); - return file; + Map<String, String> attributeMap = new HashMap<String, String>(); + attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE, + FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); + if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + 3 /* dictVersion */, attributeMap)) { + return file; + } else { + throw new IOException("Empty dictionary cannot be created."); + } } public void testIsValidDictionary() { @@ -69,8 +67,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -95,8 +91,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -139,8 +133,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -169,8 +161,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -240,8 +230,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -294,8 +282,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -342,8 +328,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -392,8 +376,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, @@ -445,8 +427,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), @@ -516,8 +496,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), @@ -617,8 +595,6 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); } catch (IOException e) { fail("IOException while writing an initial dictionary : " + e); - } catch (UnsupportedFormatException e) { - fail("UnsupportedFormatException while writing an initial dictionary : " + e); } final ArrayList<String> words = new ArrayList<String>(); @@ -630,7 +606,7 @@ public class BinaryDictionaryTests extends AndroidTestCase { binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); - while(!binaryDictionary.needsToRunGC()) { + while(!binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) { final String word = CodePointUtils.generateWord(random, codePointSet); words.add(word); final int unigramProbability = random.nextInt(0xFF); @@ -650,4 +626,57 @@ public class BinaryDictionaryTests extends AndroidTestCase { dictFile.delete(); } + + public void testUnigramAndBigramCount() { + final int flashWithGCIterationCount = 10; + final int codePointSetSize = 50; + final int unigramCountPerIteration = 1000; + final int bigramCountPerIteration = 2000; + final int seed = 1123581321; + + final Random random = new Random(seed); + + File dictFile = null; + try { + dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary"); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + + final ArrayList<String> words = new ArrayList<String>(); + final HashSet<Pair<String, String>> bigrams = new HashSet<Pair<String, String>>(); + final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random); + + BinaryDictionary binaryDictionary; + for (int i = 0; i < flashWithGCIterationCount; i++) { + binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), + 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + for (int j = 0; j < unigramCountPerIteration; j++) { + final String word = CodePointUtils.generateWord(random, codePointSet); + words.add(word); + final int unigramProbability = random.nextInt(0xFF); + binaryDictionary.addUnigramWord(word, unigramProbability); + } + for (int j = 0; j < bigramCountPerIteration; j++) { + final String word0 = words.get(random.nextInt(words.size())); + final String word1 = words.get(random.nextInt(words.size())); + bigrams.add(new Pair<String, String>(word0, word1)); + final int bigramProbability = random.nextInt(0xF); + binaryDictionary.addBigramWords(word0, word1, bigramProbability); + } + assertEquals(new HashSet<String>(words).size(), Integer.parseInt( + binaryDictionary.getPropertyForTests(BinaryDictionary.UNIGRAM_COUNT_QUERY))); + assertEquals(new HashSet<Pair<String, String>>(bigrams).size(), Integer.parseInt( + binaryDictionary.getPropertyForTests(BinaryDictionary.BIGRAM_COUNT_QUERY))); + binaryDictionary.flushWithGC(); + assertEquals(new HashSet<String>(words).size(), Integer.parseInt( + binaryDictionary.getPropertyForTests(BinaryDictionary.UNIGRAM_COUNT_QUERY))); + assertEquals(new HashSet<Pair<String, String>>(bigrams).size(), Integer.parseInt( + binaryDictionary.getPropertyForTests(BinaryDictionary.BIGRAM_COUNT_QUERY))); + binaryDictionary.close(); + } + + dictFile.delete(); + } } diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java index a4d94262f..aa1658301 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java @@ -104,7 +104,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { } sStarBigrams.put(0, new ArrayList<Integer>()); - for (int i = 1; i < sWords.size(); ++i) { + // MAX - 1 because we added one above already + final int maxBigrams = Math.min(sWords.size(), FormatSpec.MAX_BIGRAMS_IN_A_PTNODE - 1); + for (int i = 1; i < maxBigrams; ++i) { sStarBigrams.get(0).add(i); } @@ -544,8 +546,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { } private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word, - int index, boolean contained) { - final int expectedFrequency = (UNIGRAM_FREQ + index) % 255; + final boolean contained) { long diff = -1; int position = -1; try { @@ -603,7 +604,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { // Test a word that is contained within the dictionary. long sum = 0; for (int i = 0; i < sWords.size(); ++i) { - final long time = checkGetTerminalPosition(dictDecoder, sWords.get(i), i, true); + final long time = checkGetTerminalPosition(dictDecoder, sWords.get(i), true); sum += time == -1 ? 0 : time; } Log.d(TAG, "per search : " + (((double)sum) / sWords.size() / 1000000) + " : " + message @@ -616,11 +617,11 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { for (int i = 0; i < 1000; ++i) { final String word = CodePointUtils.generateWord(random, codePointSet); if (sWords.indexOf(word) != -1) continue; - checkGetTerminalPosition(dictDecoder, word, i, false); + checkGetTerminalPosition(dictDecoder, word, false); } } - private void runGetTerminalPositionTests(final ArrayList<String> results, final int bufferType, + private void runGetTerminalPositionTests(final int bufferType, final FormatOptions formatOptions) { runGetTerminalPosition(sWords, sEmptyBigrams, bufferType, formatOptions, "unigram"); } @@ -628,17 +629,17 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { public void testGetTerminalPosition() { final ArrayList<String> results = CollectionUtils.newArrayList(); - runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION2); - runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION2); + runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION2); - runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE); - runGetTerminalPositionTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION2); + runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE); + runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE); for (final String result : results) { Log.d(TAG, result); @@ -656,27 +657,21 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */); timeWritingDictToFile(file, dict, VERSION3_WITH_DYNAMIC_UPDATE); - final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file, DictDecoder.USE_BYTEARRAY); - try { - dictDecoder.openDictBuffer(); - } catch (IOException e) { - // ignore - Log.e(TAG, "IOException while opening the buffer", e); - } - assertTrue("Can't get the buffer", dictDecoder.isDictBufferOpen()); + final Ver3DictUpdater dictUpdater = new Ver3DictUpdater(file, + DictDecoder.USE_WRITABLE_BYTEBUFFER); try { MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, - dictDecoder.getTerminalPosition(sWords.get(0))); - DynamicBinaryDictIOUtils.deleteWord(dictDecoder, sWords.get(0)); + dictUpdater.getTerminalPosition(sWords.get(0))); + dictUpdater.deleteWord(sWords.get(0)); assertEquals(FormatSpec.NOT_VALID_WORD, - dictDecoder.getTerminalPosition(sWords.get(0))); + dictUpdater.getTerminalPosition(sWords.get(0))); MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, - dictDecoder.getTerminalPosition(sWords.get(5))); - DynamicBinaryDictIOUtils.deleteWord(dictDecoder, sWords.get(5)); + dictUpdater.getTerminalPosition(sWords.get(5))); + dictUpdater.deleteWord(sWords.get(5)); assertEquals(FormatSpec.NOT_VALID_WORD, - dictDecoder.getTerminalPosition(sWords.get(5))); + dictUpdater.getTerminalPosition(sWords.get(5))); } catch (IOException e) { } catch (UnsupportedFormatException e) { } diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java index a83749499..acd65856c 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java @@ -27,9 +27,7 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import com.android.inputmethod.latin.utils.CollectionUtils; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -186,46 +184,31 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase { private long insertAndCheckWord(final File file, final String word, final int frequency, final boolean exist, final ArrayList<WeightedString> bigrams, final ArrayList<WeightedString> shortcuts) { - BufferedOutputStream outStream = null; long amountOfTime = -1; try { - final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file, + final Ver3DictUpdater dictUpdater = new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER); - dictDecoder.openDictBuffer(); - outStream = new BufferedOutputStream(new FileOutputStream(file, true)); if (!exist) { assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); } final long now = System.nanoTime(); - DynamicBinaryDictIOUtils.insertWord(dictDecoder, outStream, word, frequency, bigrams, - shortcuts, false, false); + dictUpdater.insertWord(word, frequency, bigrams, shortcuts, false, false); amountOfTime = System.nanoTime() - now; - outStream.flush(); MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word)); - outStream.close(); } catch (IOException e) { Log.e(TAG, "Raised an IOException while inserting a word", e); } catch (UnsupportedFormatException e) { Log.e(TAG, "Raised an UnsupportedFormatException error while inserting a word", e); - } finally { - if (outStream != null) { - try { - outStream.close(); - } catch (IOException e) { - Log.e(TAG, "Failed to close the output stream", e); - } - } } return amountOfTime; } private void deleteWord(final File file, final String word) { try { - final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file, + final Ver3DictUpdater dictUpdater = new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER); - dictDecoder.openDictBuffer(); - DynamicBinaryDictIOUtils.deleteWord(dictDecoder, word); + dictUpdater.deleteWord(word); } catch (IOException e) { } catch (UnsupportedFormatException e) { } diff --git a/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java b/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java new file mode 100644 index 000000000..aeb8552bd --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/makedict/SparseTableTests.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.makedict; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Random; + +/** + * Unit tests for SparseTable. + */ +@LargeTest +public class SparseTableTests extends AndroidTestCase { + private static final String TAG = SparseTableTests.class.getSimpleName(); + + private final Random mRandom; + private final ArrayList<Integer> mRandomIndex; + + private static final int DEFAULT_SIZE = 10000; + private static final int BLOCK_SIZE = 8; + + public SparseTableTests() { + this(System.currentTimeMillis(), DEFAULT_SIZE); + } + + public SparseTableTests(final long seed, final int tableSize) { + super(); + Log.d(TAG, "Seed for test is " + seed + ", size is " + tableSize); + mRandom = new Random(seed); + mRandomIndex = new ArrayList<Integer>(tableSize); + for (int i = 0; i < tableSize; ++i) { + mRandomIndex.add(SparseTable.NOT_EXIST); + } + } + + public void testSet() { + final SparseTable table = new SparseTable(16, BLOCK_SIZE, 1); + table.set(0, 3, 6); + table.set(0, 8, 16); + for (int i = 0; i < 16; ++i) { + if (i == 3 || i == 8) { + assertEquals(i * 2, table.get(0, i)); + } else { + assertEquals(SparseTable.NOT_EXIST, table.get(0, i)); + } + } + } + + private void generateRandomIndex(final int size, final int prop) { + for (int i = 0; i < size; ++i) { + if (mRandom.nextInt(100) < prop) { + mRandomIndex.set(i, mRandom.nextInt()); + } else { + mRandomIndex.set(i, SparseTable.NOT_EXIST); + } + } + } + + private void runTestRandomSet() { + final SparseTable table = new SparseTable(DEFAULT_SIZE, BLOCK_SIZE, 1); + int elementCount = 0; + for (int i = 0; i < DEFAULT_SIZE; ++i) { + if (mRandomIndex.get(i) != SparseTable.NOT_EXIST) { + table.set(0, i, mRandomIndex.get(i)); + elementCount++; + } + } + + Log.d(TAG, "table size = " + table.getLookupTableSize() + " + " + + table.getContentTableSize()); + Log.d(TAG, "the table has " + elementCount + " elements"); + for (int i = 0; i < DEFAULT_SIZE; ++i) { + assertEquals(table.get(0, i), (int)mRandomIndex.get(i)); + } + + // flush and reload + OutputStream lookupOutStream = null; + OutputStream contentOutStream = null; + try { + final File lookupIndexFile = File.createTempFile("testRandomSet", ".small"); + final File contentFile = File.createTempFile("testRandomSet", ".big"); + lookupOutStream = new FileOutputStream(lookupIndexFile); + contentOutStream = new FileOutputStream(contentFile); + table.write(lookupOutStream, new OutputStream[] { contentOutStream }); + lookupOutStream.flush(); + contentOutStream.flush(); + final SparseTable newTable = SparseTable.readFromFiles(lookupIndexFile, + new File[] { contentFile }, BLOCK_SIZE); + for (int i = 0; i < DEFAULT_SIZE; ++i) { + assertEquals(table.get(0, i), newTable.get(0, i)); + } + } catch (IOException e) { + Log.d(TAG, "IOException while flushing and realoding", e); + } finally { + if (lookupOutStream != null) { + try { + lookupOutStream.close(); + } catch (IOException e) { + Log.d(TAG, "IOException while closing the stream", e); + } + } + if (contentOutStream != null) { + try { + contentOutStream.close(); + } catch (IOException e) { + Log.d(TAG, "IOException while closing contentStream.", e); + } + } + } + } + + public void testRandomSet() { + for (int i = 0; i <= 100; i += 10) { + generateRandomIndex(DEFAULT_SIZE, i); + runTestRandomSet(); + } + } + + public void testMultipleContents() { + final int numOfContents = 5; + generateRandomIndex(DEFAULT_SIZE, 20); + final SparseTable table = new SparseTable(DEFAULT_SIZE, BLOCK_SIZE, numOfContents); + for (int i = 0; i < mRandomIndex.size(); ++i) { + if (mRandomIndex.get(i) != SparseTable.NOT_EXIST) { + for (int j = 0; j < numOfContents; ++j) { + table.set(j, i, mRandomIndex.get(i)); + } + } + } + + OutputStream lookupOutStream = null; + OutputStream[] contentsOutStream = new OutputStream[numOfContents]; + try { + final File lookupIndexFile = File.createTempFile("testMultipleContents", "small"); + lookupOutStream = new FileOutputStream(lookupIndexFile); + final File[] contentFiles = new File[numOfContents]; + for (int i = 0; i < numOfContents; ++i) { + contentFiles[i] = File.createTempFile("testMultipleContents", "big" + i); + contentsOutStream[i] = new FileOutputStream(contentFiles[i]); + } + table.write(lookupOutStream, contentsOutStream); + lookupOutStream.flush(); + for (int i = 0; i < numOfContents; ++i) { + contentsOutStream[i].flush(); + } + final SparseTable newTable = SparseTable.readFromFiles(lookupIndexFile, contentFiles, + BLOCK_SIZE); + for (int i = 0; i < numOfContents; ++i) { + for (int j = 0; j < DEFAULT_SIZE; ++j) { + assertEquals(table.get(i, j), newTable.get(i, j)); + } + } + } catch (IOException e) { + Log.d(TAG, "IOException while flushing and reloading", e); + } finally { + if (lookupOutStream != null) { + try { + lookupOutStream.close(); + } catch (IOException e) { + Log.d(TAG, "IOException while closing the stream", e); + } + } + for (int i = 0; i < numOfContents; ++i) { + if (contentsOutStream[i] != null) { + try { + contentsOutStream[i].close(); + } catch (IOException e) { + Log.d(TAG, "IOException while closing the stream.", e); + } + } + } + } + } +} diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java index 06c427193..7c1decb71 100644 --- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java @@ -75,10 +75,10 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { return new ArrayList<String>(wordSet); } - private void addToDict(final UserHistoryPredictionDictionary dict, final List<String> words) { + private void addToDict(final UserHistoryDictionary dict, final List<String> words) { String prevWord = null; for (String word : words) { - dict.addToPersonalizationPredictionDictionary(prevWord, word, true); + dict.addToDictionary(prevWord, word, true); prevWord = word; } } @@ -90,8 +90,8 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { private void addAndWriteRandomWords(final String testFilenameSuffix, final int numberOfWords, final Random random, final boolean checkContents) { final List<String> words = generateWords(numberOfWords, random); - final UserHistoryPredictionDictionary dict = - PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(), + final UserHistoryDictionary dict = + PersonalizationHelper.getUserHistoryDictionary(getContext(), testFilenameSuffix /* locale */, mPrefs); // Add random words to the user history dictionary. addToDict(dict, words); @@ -109,35 +109,54 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { dict.close(); } + /** + * Clear all entries in the user history dictionary. + * @param testFilenameSuffix file name suffix used for testing. + */ + private void clearHistory(final String testFilenameSuffix) { + final UserHistoryDictionary dict = + PersonalizationHelper.getUserHistoryDictionary(getContext(), + testFilenameSuffix /* locale */, mPrefs); + dict.clearAndFlushDictionary(); + dict.close(); + } + + /** + * Shut down executer and wait until all operations of user history are done. + * @param testFilenameSuffix file name suffix used for testing. + */ + private void waitForWriting(final String testFilenameSuffix) { + try { + final UserHistoryDictionary dict = + PersonalizationHelper.getUserHistoryDictionary(getContext(), + testFilenameSuffix, mPrefs); + dict.shutdownExecutorForTests(); + while (!dict.isTerminatedForTests()) { + Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS); + } + } catch (InterruptedException e) { + Log.d(TAG, "InterruptedException: ", e); + } + } + public void testRandomWords() { - File dictFile = null; Log.d(TAG, "This test can be used for profiling."); Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true."); final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis(); + final String fileName = UserHistoryDictionary.NAME + "." + testFilenameSuffix + + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; + final int numberOfWords = 1000; final Random random = new Random(123456); try { + clearHistory(testFilenameSuffix); addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random, true /* checksContents */); } finally { - try { - final UserHistoryPredictionDictionary dict = - PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(), - testFilenameSuffix, mPrefs); - Log.d(TAG, "waiting for writing ..."); - dict.shutdownExecutorForTests(); - while (!dict.isTerminatedForTests()) { - Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS); - } - } catch (InterruptedException e) { - Log.d(TAG, "InterruptedException: " + e); - } - - final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix - + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; - dictFile = new File(getContext().getFilesDir(), fileName); - + Log.d(TAG, "waiting for writing ..."); + waitForWriting(testFilenameSuffix); + final File dictFile = new File(getContext().getFilesDir(), fileName); if (dictFile != null) { assertTrue(dictFile.exists()); assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE); @@ -159,9 +178,10 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { // Create filename suffixes for this test. for (int i = 0; i < numberOfLanguages; i++) { testFilenameSuffixes[i] = "testSwitchingLanguages" + i; - final String fileName = UserHistoryPredictionDictionary.NAME + "." + + final String fileName = UserHistoryDictionary.NAME + "." + testFilenameSuffixes[i] + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; dictFiles[i] = new File(getContext().getFilesDir(), fileName); + clearHistory(testFilenameSuffixes[i]); } final long start = System.currentTimeMillis(); @@ -178,19 +198,9 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took " + (end - start) + " ms"); } finally { - try { - Log.d(TAG, "waiting for writing ..."); - for (int i = 0; i < numberOfLanguages; i++) { - final UserHistoryPredictionDictionary dict = - PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(), - testFilenameSuffixes[i], mPrefs); - dict.shutdownExecutorForTests(); - while (!dict.isTerminatedForTests()) { - Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS); - } - } - } catch (InterruptedException e) { - Log.d(TAG, "InterruptedException: " + e); + Log.d(TAG, "waiting for writing ..."); + for (int i = 0; i < numberOfLanguages; i++) { + waitForWriting(testFilenameSuffixes[i]); } for (final File file : dictFiles) { if (file != null) { @@ -203,33 +213,21 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { } public void testAddManyWords() { - File dictFile = null; final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis(); final int numberOfWords = ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ? 10000 : 1000; final Random random = new Random(123456); - - UserHistoryPredictionDictionary dict = - PersonalizationHelper.getUserHistoryPredictionDictionary(getContext(), - testFilenameSuffix, mPrefs); + clearHistory(testFilenameSuffix); try { addAndWriteRandomWords(testFilenameSuffix, numberOfWords, random, true /* checksContents */); - dict.close(); } finally { - try { - Log.d(TAG, "waiting for writing ..."); - dict.shutdownExecutorForTests(); - while (!dict.isTerminatedForTests()) { - Thread.sleep(WAIT_TERMINATING_IN_MILLISECONDS); - } - } catch (InterruptedException e) { - Log.d(TAG, "InterruptedException: ", e); - } - final String fileName = UserHistoryPredictionDictionary.NAME + "." + testFilenameSuffix + Log.d(TAG, "waiting for writing ..."); + waitForWriting(testFilenameSuffix); + final String fileName = UserHistoryDictionary.NAME + "." + testFilenameSuffix + ExpandableBinaryDictionary.DICT_FILE_EXTENSION; - dictFile = new File(getContext().getFilesDir(), fileName); + final File dictFile = new File(getContext().getFilesDir(), fileName); if (dictFile != null) { assertTrue(dictFile.exists()); assertTrue(dictFile.length() >= MIN_USER_HISTORY_DICTIONARY_FILE_SIZE); diff --git a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java new file mode 100644 index 000000000..fa6ad16c1 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.utils; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.style.SuggestionSpan; +import android.text.style.URLSpan; +import android.text.SpannableStringBuilder; +import android.text.Spannable; +import android.text.Spanned; + +@SmallTest +public class SpannableStringUtilsTests extends AndroidTestCase { + public void testConcatWithSuggestionSpansOnly() { + SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n" + + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n" + + "test string\ntest string\n"); + final int N = 10; + for (int i = 0; i < N; ++i) { + // Put a PARAGRAPH-flagged span that should not be found in the result. + s.setSpan(new SuggestionSpan(getContext(), + new String[] {"" + i}, Spannable.SPAN_PARAGRAPH), + i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH); + // Put a normal suggestion span that should be found in the result. + s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0); + // Put a URL span than should not be found in the result. + s.setSpan(new URLSpan("http://a"), i, i * 2, 0); + } + + final CharSequence a = s.subSequence(0, 15); + final CharSequence b = s.subSequence(15, s.length()); + final Spanned result = + (Spanned)SpannableStringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b); + + Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class); + for (int i = 0; i < spans.length; i++) { + final int flags = result.getSpanFlags(spans[i]); + assertEquals("Should not find a span with PARAGRAPH flag", + flags & Spannable.SPAN_PARAGRAPH, 0); + assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan); + } + } +} diff --git a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java index eb9fb984e..4e396a1cf 100644 --- a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java @@ -20,11 +20,6 @@ import com.android.inputmethod.latin.settings.SettingsValues; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; -import android.text.style.SuggestionSpan; -import android.text.style.URLSpan; -import android.text.SpannableStringBuilder; -import android.text.Spannable; -import android.text.Spanned; import java.util.Arrays; import java.util.List; @@ -285,34 +280,4 @@ public class StringUtilsTests extends AndroidTestCase { assertEquals(objs[i], newObjArray.get(i)); } } - - public void testConcatWithSuggestionSpansOnly() { - SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n" - + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n" - + "test string\ntest string\n"); - final int N = 10; - for (int i = 0; i < N; ++i) { - // Put a PARAGRAPH-flagged span that should not be found in the result. - s.setSpan(new SuggestionSpan(getContext(), - new String[] {"" + i}, Spannable.SPAN_PARAGRAPH), - i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH); - // Put a normal suggestion span that should be found in the result. - s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0); - // Put a URL span than should not be found in the result. - s.setSpan(new URLSpan("http://a"), i, i * 2, 0); - } - - final CharSequence a = s.subSequence(0, 15); - final CharSequence b = s.subSequence(15, s.length()); - final Spanned result = - (Spanned)StringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b); - - Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class); - for (int i = 0; i < spans.length; i++) { - final int flags = result.getSpanFlags(spans[i]); - assertEquals("Should not find a span with PARAGRAPH flag", - flags & Spannable.SPAN_PARAGRAPH, 0); - assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan); - } - } } |