blob: 36c7f190a1b20972f2323d8899ed2079a5f5c055 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2000-2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
/**
* Port From: ICU4C v2.1 : collate/StringSearchTest
* Source File: $ICU4CRoot/source/test/intltest/srchtest.cpp
**/
package com.ibm.icu.dev.test.search;
import static com.ibm.icu.text.Collator.IDENTICAL;
import static com.ibm.icu.text.Collator.PRIMARY;
import static com.ibm.icu.text.Collator.QUATERNARY;
import static com.ibm.icu.text.Collator.SECONDARY;
import static com.ibm.icu.text.Collator.TERTIARY;
import static com.ibm.icu.text.SearchIterator.ElementComparisonType.ANY_BASE_WEIGHT_IS_WILDCARD;
import static com.ibm.icu.text.SearchIterator.ElementComparisonType.PATTERN_BASE_WEIGHT_IS_WILDCARD;
import static com.ibm.icu.text.SearchIterator.ElementComparisonType.STANDARD_ELEMENT_COMPARISON;
import java.text.StringCharacterIterator;
import java.util.Locale;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.BreakIterator;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RuleBasedCollator;
import com.ibm.icu.text.SearchIterator;
import com.ibm.icu.text.SearchIterator.ElementComparisonType;
import com.ibm.icu.text.StringSearch;
import com.ibm.icu.util.ULocale;
public class SearchTest extends TestFmwk {
//inner class
static class SearchData {
SearchData(String text, String pattern,
String coll, int strength, ElementComparisonType cmpType, String breaker,
int[] offset, int[] size) {
this.text = text;
this.pattern = pattern;
this.collator = coll;
this.strength = strength;
this.cmpType = cmpType;
this.breaker = breaker;
this.offset = offset;
this.size = size;
}
String text;
String pattern;
String collator;
int strength;
ElementComparisonType cmpType;
String breaker;
int[] offset;
int[] size;
}
RuleBasedCollator m_en_us_;
RuleBasedCollator m_fr_fr_;
RuleBasedCollator m_de_;
RuleBasedCollator m_es_;
BreakIterator m_en_wordbreaker_;
BreakIterator m_en_characterbreaker_;
// Just calling SearchData constructor, to make the test data source code
// nice and short
private static SearchData SD(String text, String pattern, String coll, int strength,
ElementComparisonType cmpType, String breaker, int[] offset, int[] size) {
return new SearchData(text, pattern, coll, strength, cmpType, breaker, offset, size);
}
// Just returning int[], to make the test data nice and short
private static int[] IA(int... elements) {
return elements;
}
static SearchData[] BASIC = {
SD("xxxxxxxxxxxxxxxxxxxx", "fisher", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("silly spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(13, -1), IA(6)),
SD("silly spring string string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(13, 20, -1), IA(6, 6)),
SD("silly string spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(6, 20, -1), IA(6, 6)),
SD("string spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 14, -1), IA(6, 6)),
SD("Scott Ganyo", "c", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(1)),
SD("Scott Ganyo", " ", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(5, -1), IA(1)),
SD("\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300b", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00c9", "e", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
};
SearchData BREAKITERATOREXACT[] = {
SD("foxy fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(0, 5, -1), IA(3, 3)),
SD("foxy fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(5, -1), IA(3)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(10, 14, -1), IA(3, 2)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(10, -1), IA(3)),
SD("Channel, another channel, more channels, and one last Channel", "Channel", "es", TERTIARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(0, 54, -1), IA(7, 7)),
/* jitterbug 1745 */
SD("testing that \u00e9 does not match e", "e", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(1, 17, 30, -1), IA(1, 1, 1)),
SD("testing that string ab\u00e9cd does not match e", "e", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(1, 28, 41, -1), IA(1, 1, 1)),
SD("\u00c9", "e", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(0, -1), IA(1)),
};
SearchData BREAKITERATORCANONICAL[] = {
SD("foxy fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(0, 5, -1), IA(3, 3)),
SD("foxy fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(5, -1), IA(3)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(10, 14, -1), IA(3, 2)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(10, -1), IA(3)),
SD("Channel, another channel, more channels, and one last Channel", "Channel", "es", TERTIARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(0, 54, -1), IA(7, 7)),
/* jitterbug 1745 */
SD("testing that \u00e9 does not match e", "e", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(1, 17, 30, -1), IA(1, 1, 1)),
SD("testing that string ab\u00e9cd does not match e", "e", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(1, 28, 41, -1), IA(1, 1, 1)),
SD("\u00c9", "e", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, "characterbreaker", IA(0, -1), IA(1)),
};
SearchData BASICCANONICAL[] = {
SD("xxxxxxxxxxxxxxxxxxxx", "fisher", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("silly spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(13, -1), IA(6)),
SD("silly spring string string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(13, 20, -1), IA(6, 6)),
SD("silly string spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(6, 20, -1), IA(6, 6)),
SD("string spring string", "string", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 14, -1), IA(6, 6)),
SD("Scott Ganyo", "c", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(1)),
SD("Scott Ganyo", " ", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(5, -1), IA(1)),
SD("\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300b", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325b", "\u0300b", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0325\u0300A\u0325\u0300", "\u0300A\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0325\u0300A\u0325\u0300", "\u0325A\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325b\u0300\u0325c \u0325b\u0300 \u0300b\u0325", "\u0300b\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00c4\u0323", "A\u0323\u0308", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(2)),
SD("\u0308\u0323", "\u0323\u0308", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(2)),
};
SearchData COLLATOR[] = {
/* english */
SD("fox fpx", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(3)),
/* tailored */
SD("fox fpx", "fox", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 4, -1), IA(3, 3)),
};
String TESTCOLLATORRULE = "& o,O ; p,P";
String EXTRACOLLATIONRULE = " & ae ; \u00e4 & AE ; \u00c4 & oe ; \u00f6 & OE ; \u00d6 & ue ; \u00fc & UE ; \u00dc";
SearchData COLLATORCANONICAL[] = {
/* english */
SD("fox fpx", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(3)),
/* tailored */
SD("fox fpx", "fox", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 4, -1), IA(3, 3)),
};
SearchData COMPOSITEBOUNDARIES[] = {
SD("\u00C0", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u00C0C", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u00C0A", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(1)),
SD("B\u00C0", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00C0B", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00C0", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* first one matches only because it's at the start of the text */
SD("\u0300\u00C0", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
/* \\u0300 blocked by \\u0300 */
SD("\u00C0\u0300", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* A + 030A + 0301 */
SD("\u01FA", "\u01FA", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u01FA", "A\u030A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u01FA", "\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u030AA", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* blocked accent */
SD("\u01FA", "A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u0301A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u030A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FAA", "\u0301A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F73", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u0F73", "\u0F71", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F72", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F71\u0F72", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("A\u0F73", "A\u0F71", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73A", "\u0F72A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA A\u0301\u030A A\u030A\u0301 A\u030A \u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(10, -1), IA(2)),
};
SearchData COMPOSITEBOUNDARIESCANONICAL[] = {
SD("\u00C0", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u00C0C", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u00C0A", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(1)),
SD("B\u00C0", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00C0B", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u00C0", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* first one matches only because it's at the start of the text */
SD("\u0300\u00C0", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
/* \u0300 blocked by \u0300 */
SD("\u00C0\u0300", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* A + 030A + 0301 */
SD("\u01FA", "\u01FA", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u01FA", "A\u030A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u01FA", "\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u030AA", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* blocked accent */
SD("\u01FA", "A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u0301A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA", "\u030A\u0301", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FAA", "\u0301A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F73", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("\u0F73", "\u0F71", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F72", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73", "\u0F71\u0F72", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1)),
SD("A\u0F73", "A\u0F71", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0F73A", "\u0F72A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u01FA A\u0301\u030A A\u030A\u0301 A\u030A \u01FA", "A\u030A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(10, -1), IA(2)),
};
SearchData SUPPLEMENTARY[] = {
SD("abc \uD800\uDC00 \uD800\uDC01 \uD801\uDC00 \uD800\uDC00abc abc\uD800\uDC00 \uD800\uD800\uDC00 \uD800\uDC00\uDC00",
"\uD800\uDC00", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(4, 13, 22, 26, 29, -1), IA(2, 2, 2, 2, 2)),
SD("and\uD834\uDDB9this sentence", "\uD834\uDDB9", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(2)),
SD("and \uD834\uDDB9 this sentence", " \uD834\uDDB9 ", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and-\uD834\uDDB9-this sentence", "-\uD834\uDDB9-", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and,\uD834\uDDB9,this sentence", ",\uD834\uDDB9,", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and?\uD834\uDDB9?this sentence", "?\uD834\uDDB9?", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
};
String CONTRACTIONRULE = "&z = ab/c < AB < X\u0300 < ABC < X\u0300\u0315";
SearchData CONTRACTION[] = {
/* common discontiguous */
SD("A\u0300\u0315", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u0300\u0315", "\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* contraction prefix */
SD("AB\u0315C", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("AB\u0315C", "AB", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("AB\u0315C", "\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/*
* discontiguous problem here for backwards iteration. accents not found because discontiguous stores all
* information
*/
SD("X\u0300\u0319\u0315", "\u0319", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* ends not with a contraction character */
SD("X\u0315\u0300D", "\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("X\u0315\u0300D", "X\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(3)),
SD("X\u0300\u031A\u0315D", "X\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* blocked discontiguous */
SD("X\u0300\u031A\u0315D", "\u031A\u0315D", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/*
* "ab" generates a contraction that's an expansion. The "z" matches the first CE of the expansion but the
* match fails because it ends in the middle of an expansion...
*/
SD("ab", "z", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
};
SearchData CONTRACTIONCANONICAL[] = {
/* common discontiguous */
SD("A\u0300\u0315", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("A\u0300\u0315", "\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* contraction prefix */
SD("AB\u0315C", "A", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("AB\u0315C", "AB", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("AB\u0315C", "\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/*
* discontiguous problem here for backwards iteration. forwards gives 0, 4 but backwards give 1, 3
*/
/*
* {"X\u0300\u0319\u0315", "\u0319", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, {0, -1), {4}),
*/
/* ends not with a contraction character */
SD("X\u0315\u0300D", "\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("X\u0315\u0300D", "X\u0300\u0315", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(3)),
SD("X\u0300\u031A\u0315D", "X\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/* blocked discontiguous */
SD("X\u0300\u031A\u0315D", "\u031A\u0315D", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
/*
* "ab" generates a contraction that's an expansion. The "z" matches the first CE of the expansion but the
* match fails because it ends in the middle of an expansion...
*/
SD("ab", "z", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(2)),
};
SearchData MATCH[] = {
SD("a busy bee is a very busy beeee", "bee", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(7, 26, -1), IA(3, 3)),
/* 012345678901234567890123456789012345678901234567890 */
SD("a busy bee is a very busy beeee with no bee life", "bee", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(7, 26, 40, -1), IA(3, 3, 3)),
};
String IGNORABLERULE = "&a = \u0300";
SearchData IGNORABLE[] = {
/*
* This isn't much of a test when matches have to be on grapheme boundiaries. The match at 0 only works because it's
* at the start of the text.
*/
SD("\u0300\u0315 \u0300\u0315 ", "\u0300", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(2)),
};
SearchData DIACTRICMATCH[] = {
SD("\u0061\u0061\u00E1", "\u0061\u00E1", null, SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(2)),
SD("\u0020\u00C2\u0303\u0020\u0041\u0061\u1EAA\u0041\u0302\u0303\u00C2\u0303\u1EAB\u0061\u0302\u0303\u00E2\u0303\uD806\uDC01\u0300\u0020", "\u00C2\u0303",
null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, 4, 5, 6, 7, 10, 12, 13, 16, -1), IA(2, 1, 1, 1, 3, 2, 1, 3, 2)),
SD("\u03BA\u03B1\u03B9\u0300\u0020\u03BA\u03B1\u1F76", "\u03BA\u03B1\u03B9", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 5, -1), IA(4, 3)),
};
SearchData NORMCANONICAL[] = {
SD("\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("\u0300\u0325", "\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0325\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0325", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("a\u0300\u0325", "\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
};
SearchData NORMEXACT[] = {
SD("a\u0300\u0325", "a\u0325\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(3)),
};
SearchData NONNORMEXACT[] = {
SD("a\u0300\u0325", "\u0325\u0300", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
};
SearchData OVERLAP[] = {
SD("abababab", "abab", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 2, 4, -1), IA(4, 4, 4)),
};
SearchData NONOVERLAP[] = {
SD("abababab", "abab", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 4, -1), IA(4, 4)),
};
SearchData OVERLAPCANONICAL[] = {
SD("abababab", "abab", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 2, 4, -1), IA(4, 4, 4)),
};
SearchData NONOVERLAPCANONICAL[] = {
SD("abababab", "abab", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 4, -1), IA(4, 4)),
};
SearchData PATTERNCANONICAL[] = {
SD("The quick brown fox jumps over the lazy foxes", "the", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 31, -1), IA(3, 3)),
SD("The quick brown fox jumps over the lazy foxes", "fox", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, 40, -1), IA(3, 3)),
};
SearchData PATTERN[] = {
SD("The quick brown fox jumps over the lazy foxes", "the", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 31, -1), IA(3, 3)),
SD("The quick brown fox jumps over the lazy foxes", "fox", null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, 40, -1), IA(3, 3)),
};
String PECHE_WITH_ACCENTS = "un p\u00E9ch\u00E9, "
+ "\u00E7a p\u00E8che par, "
+ "p\u00E9cher, "
+ "une p\u00EAche, "
+ "un p\u00EAcher, "
+ "j\u2019ai p\u00EAch\u00E9, "
+ "un p\u00E9cheur, "
+ "\u201Cp\u00E9che\u201D, "
+ "decomp peche\u0301, "
+ "base peche";
// in the above, the interesting words and their offsets are:
// 3 pe<301>che<301>
// 13 pe<300>che
// 24 pe<301>cher
// 36 pe<302>che
// 46 pe<302>cher
// 59 pe<302>che<301>
// 69 pe<301>cheur
// 79 pe<301>che
// 94 peche<+301>
// 107 peche
SearchData STRENGTH[] = {
/* 012345678901234567890123456789012345678901234567890123456789 */
SD("The quick brown fox jumps over the lazy foxes", "fox", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, 40, -1), IA(3, 3)),
SD("The quick brown fox jumps over the lazy foxes", "fox", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(16, -1), IA(3)),
SD("blackbirds Pat p\u00E9ch\u00E9 p\u00EAche p\u00E9cher p\u00EAcher Tod T\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe",
"peche", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(15, 21, 27, 34, -1), IA(5, 5, 5, 5)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(10, 14, -1), IA(3, 2)),
SD("A channel, another CHANNEL, more Channels, and one last channel...", "channel", "es", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(2, 19, 33, 56, -1), IA(7, 7, 7, 7)),
SD("\u00c0 should match but not A", "A\u0300", "en", IDENTICAL, STANDARD_ELEMENT_COMPARISON, null, IA(0, -1), IA(1, 0)),
/* some tests for modified element comparison, ticket #7093 */
SD(PECHE_WITH_ACCENTS, "peche", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "en", SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(107, -1), IA(5)),
SD(PECHE_WITH_ACCENTS, "peche", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(24, 69, 79, -1), IA(5, 5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(79, -1), IA(5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 24, 69, 79, -1), IA(5, 5, 5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 79, -1), IA(5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 24, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 79, 94, 107, -1), IA(5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "en", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "en", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
/* more tests for modified element comparison (with fr), ticket #7093 */
SD(PECHE_WITH_ACCENTS, "peche", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "fr", SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(107, -1), IA(5)),
SD(PECHE_WITH_ACCENTS, "peche", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(24, 69, 79, -1), IA(5, 5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(79, -1), IA(5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 24, 69, 79, -1), IA(5, 5, 5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 79, -1), IA(5, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 24, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "p\u00E9che", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 79, 94, 107, -1), IA(5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "pech\u00E9", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "fr", SECONDARY, PATTERN_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 59, 94, -1), IA(5, 5, 6)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, null, IA(3, 13, 24, 36, 46, 59, 69, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 5, 5, 5, 6, 5)),
SD(PECHE_WITH_ACCENTS, "peche\u0301", "fr", SECONDARY, ANY_BASE_WEIGHT_IS_WILDCARD, "wordbreaker", IA(3, 13, 36, 59, 79, 94, 107, -1), IA(5, 5, 5, 5, 5, 6, 5)),
};
SearchData STRENGTHCANONICAL[] = {
/* 012345678901234567890123456789012345678901234567890123456789 */
SD("The quick brown fox jumps over the lazy foxes", "fox", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, 40, -1), IA(3, 3)),
SD("The quick brown fox jumps over the lazy foxes", "fox", "en", PRIMARY, STANDARD_ELEMENT_COMPARISON, "wordbreaker", IA(16, -1), IA(3)),
SD("blackbirds Pat p\u00E9ch\u00E9 p\u00EAche p\u00E9cher p\u00EAcher Tod T\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe",
"peche", "fr", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(15, 21, 27, 34, -1), IA(5, 5, 5, 5)),
SD("This is a toe T\u00F6ne", "toe", "de", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(10, 14, -1), IA(3, 2)),
SD("A channel, another CHANNEL, more Channels, and one last channel...", "channel", "es", PRIMARY, STANDARD_ELEMENT_COMPARISON, null, IA(2, 19, 33, 56, -1), IA(7, 7, 7, 7)),
};
SearchData SUPPLEMENTARYCANONICAL[] = {
/* 012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890012345678901234567890123456789 */
SD("abc \uD800\uDC00 \uD800\uDC01 \uD801\uDC00 \uD800\uDC00abc abc\uD800\uDC00 \uD800\uD800\uDC00 \uD800\uDC00\uDC00", "\uD800\uDC00",
null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(4, 13, 22, 26, 29, -1), IA(2, 2, 2, 2, 2)),
SD("and\uD834\uDDB9this sentence", "\uD834\uDDB9", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(2)),
SD("and \uD834\uDDB9 this sentence", " \uD834\uDDB9 ", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and-\uD834\uDDB9-this sentence", "-\uD834\uDDB9-", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and,\uD834\uDDB9,this sentence", ",\uD834\uDDB9,", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
SD("and?\uD834\uDDB9?this sentence", "?\uD834\uDDB9?", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(3, -1), IA(4)),
};
static SearchData VARIABLE[] = {
/* 012345678901234567890123456789012345678901234567890123456789 */
SD("blackbirds black blackbirds blackbird black-bird", "blackbird", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(0, 17, 28, 38, -1), IA(9, 9, 9, 10)),
/*
* to see that it doesn't go into an infinite loop if the start of text is a ignorable character
*/
SD(" on", "go", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
SD("abcdefghijklmnopqrstuvwxyz", " ",
null, PRIMARY, STANDARD_ELEMENT_COMPARISON, null,
IA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1),
IA(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
/* testing tightest match */
SD(" abc a bc ab c a bc ab c", "abc", null, QUATERNARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, -1), IA(3)),
/* 012345678901234567890123456789012345678901234567890123456789 */
SD(" abc a bc ab c a bc ab c", "abc", null, SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(1, 6, 13, 21, 31, -1), IA(3, 4, 4, 5, 5)),
/* totally ignorable text */
SD(" ---------------", "abc", null, SECONDARY, STANDARD_ELEMENT_COMPARISON, null, IA(-1), IA(0)),
};
static SearchData TEXTCANONICAL[] = {
SD("the foxy brown fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(4, 15, -1), IA(3, 3)),
SD("the quick brown fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, -1), IA(3)),
};
/**
* Constructor
*/
public SearchTest()
{
}
protected void init()throws Exception{
m_en_us_ = (RuleBasedCollator)Collator.getInstance(Locale.US);
m_fr_fr_ = (RuleBasedCollator)Collator.getInstance(Locale.FRANCE);
m_de_ = (RuleBasedCollator)Collator.getInstance(new Locale("de", "DE"));
m_es_ = (RuleBasedCollator)Collator.getInstance(new Locale("es", "ES"));
m_en_wordbreaker_ = BreakIterator.getWordInstance();
m_en_characterbreaker_ = BreakIterator.getCharacterInstance();
String rules = m_de_.getRules() + EXTRACOLLATIONRULE;
m_de_ = new RuleBasedCollator(rules);
rules = m_es_.getRules() + EXTRACOLLATIONRULE;
m_es_ = new RuleBasedCollator(rules);
}
public static void main(String[] args) throws Exception {
new SearchTest().run(args);
// new SearchTest().TestContraction();
}
RuleBasedCollator getCollator(String collator) {
if (collator == null) {
return m_en_us_;
} if (collator.equals("fr")) {
return m_fr_fr_;
} else if (collator.equals("de")) {
return m_de_;
} else if (collator.equals("es")) {
return m_es_;
} else {
return m_en_us_;
}
}
BreakIterator getBreakIterator(String breaker) {
if (breaker == null) {
return null;
} if (breaker.equals("wordbreaker")) {
return m_en_wordbreaker_;
} else {
return m_en_characterbreaker_;
}
}
boolean assertCanonicalEqual(SearchData search) {
Collator collator = getCollator(search.collator);
BreakIterator breaker = getBreakIterator(search.breaker);
StringSearch strsrch;
String text = search.text;
String pattern = search.pattern;
if (breaker != null) {
breaker.setText(text);
}
collator.setStrength(search.strength);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), (RuleBasedCollator)collator, breaker);
strsrch.setElementComparisonType(search.cmpType);
strsrch.setCanonical(true);
} catch (Exception e) {
errln("Error opening string search" + e.getMessage());
return false;
}
if (!assertEqualWithStringSearch(strsrch, search)) {
collator.setStrength(TERTIARY);
collator.setDecomposition(Collator.NO_DECOMPOSITION);
return false;
}
collator.setStrength(TERTIARY);
collator.setDecomposition(Collator.NO_DECOMPOSITION);
return true;
}
boolean assertEqual(SearchData search) {
Collator collator = getCollator(search.collator);
BreakIterator breaker = getBreakIterator(search.breaker);
StringSearch strsrch;
String text = search.text;
String pattern = search.pattern;
if (breaker != null) {
breaker.setText(text);
}
collator.setStrength(search.strength);
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), (RuleBasedCollator)collator, breaker);
strsrch.setElementComparisonType(search.cmpType);
} catch (Exception e) {
errln("Error opening string search " + e.getMessage());
return false;
}
if (!assertEqualWithStringSearch(strsrch, search)) {
collator.setStrength(TERTIARY);
return false;
}
collator.setStrength(TERTIARY);
return true;
}
boolean assertEqualWithAttribute(SearchData search, boolean canonical, boolean overlap) {
Collator collator = getCollator(search.collator);
BreakIterator breaker = getBreakIterator(search.breaker);
StringSearch strsrch;
String text = search.text;
String pattern = search.pattern;
if (breaker != null) {
breaker.setText(text);
}
collator.setStrength(search.strength);
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), (RuleBasedCollator)collator, breaker);
strsrch.setCanonical(canonical);
strsrch.setOverlapping(overlap);
strsrch.setElementComparisonType(search.cmpType);
} catch (Exception e) {
errln("Error opening string search " + e.getMessage());
return false;
}
if (!assertEqualWithStringSearch(strsrch, search)) {
collator.setStrength(TERTIARY);
return false;
}
collator.setStrength(TERTIARY);
return true;
}
boolean assertEqualWithStringSearch(StringSearch strsrch, SearchData search) {
int count = 0;
int matchindex = search.offset[count];
String matchtext;
if (strsrch.getMatchStart() != SearchIterator.DONE ||
strsrch.getMatchLength() != 0) {
errln("Error with the initialization of match start and length");
}
// start of following matches
while (matchindex >= 0) {
int matchlength = search.size[count];
strsrch.next();
//int x = strsrch.getMatchStart();
if (matchindex != strsrch.getMatchStart() ||
matchlength != strsrch.getMatchLength()) {
errln("Text: " + search.text);
errln("Searching forward for pattern: " + strsrch.getPattern());
errln("Expected offset,len " + matchindex + ", " + matchlength + "; got " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return false;
}
count ++;
matchtext = strsrch.getMatchedText();
String targetText = search.text;
if (matchlength > 0 &&
targetText.substring(matchindex, matchindex + matchlength).compareTo(matchtext) != 0) {
errln("Error getting following matched text");
}
matchindex = search.offset[count];
}
strsrch.next();
if (strsrch.getMatchStart() != SearchIterator.DONE ||
strsrch.getMatchLength() != 0) {
errln("Text: " + search.text);
errln("Searching forward for pattern: " + strsrch.getPattern());
errln("Expected DONE offset,len -1, 0; got " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return false;
}
// start of preceding matches
count = count == 0 ? 0 : count - 1;
matchindex = search.offset[count];
while (matchindex >= 0) {
int matchlength = search.size[count];
strsrch.previous();
if (matchindex != strsrch.getMatchStart() ||
matchlength != strsrch.getMatchLength()) {
errln("Text: " + search.text);
errln("Searching backward for pattern: " + strsrch.getPattern());
errln("Expected offset,len " + matchindex + ", " + matchlength + "; got " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return false;
}
matchtext = strsrch.getMatchedText();
String targetText = search.text;
if (matchlength > 0 &&
targetText.substring(matchindex, matchindex + matchlength).compareTo(matchtext) != 0) {
errln("Error getting following matched text");
}
matchindex = count > 0 ? search.offset[count - 1] : -1;
count --;
}
strsrch.previous();
if (strsrch.getMatchStart() != SearchIterator.DONE ||
strsrch.getMatchLength() != 0) {
errln("Text: " + search.text);
errln("Searching backward for pattern: " + strsrch.getPattern());
errln("Expected DONE offset,len -1, 0; got " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return false;
}
return true;
}
public void TestConstructor()
{
String pattern = "pattern";
String text = "text";
StringCharacterIterator textiter = new StringCharacterIterator(text);
Collator defaultcollator = Collator.getInstance();
BreakIterator breaker = BreakIterator.getCharacterInstance();
breaker.setText(text);
StringSearch search = new StringSearch(pattern, text);
if (!search.getPattern().equals(pattern)
|| !search.getTarget().equals(textiter)
|| !search.getCollator().equals(defaultcollator)
/*|| !search.getBreakIterator().equals(breaker)*/) {
errln("StringSearch(String, String) error");
}
search = new StringSearch(pattern, textiter, m_fr_fr_);
if (!search.getPattern().equals(pattern)
|| !search.getTarget().equals(textiter)
|| !search.getCollator().equals(m_fr_fr_)
/*|| !search.getBreakIterator().equals(breaker)*/) {
errln("StringSearch(String, StringCharacterIterator, "
+ "RuleBasedCollator) error");
}
Locale de = new Locale("de", "DE");
breaker = BreakIterator.getCharacterInstance(de);
breaker.setText(text);
search = new StringSearch(pattern, textiter, de);
if (!search.getPattern().equals(pattern)
|| !search.getTarget().equals(textiter)
|| !search.getCollator().equals(Collator.getInstance(de))
/*|| !search.getBreakIterator().equals(breaker)*/) {
errln("StringSearch(String, StringCharacterIterator, Locale) "
+ "error");
}
search = new StringSearch(pattern, textiter, m_fr_fr_,
m_en_wordbreaker_);
if (!search.getPattern().equals(pattern)
|| !search.getTarget().equals(textiter)
|| !search.getCollator().equals(m_fr_fr_)
|| !search.getBreakIterator().equals(m_en_wordbreaker_)) {
errln("StringSearch(String, StringCharacterIterator, Locale) "
+ "error");
}
}
public void TestBasic() {
for (int count = 0; count < BASIC.length; count++) {
if (!assertEqual(BASIC[count])) {
errln("Error at test number " + count);
}
}
}
public void TestBreakIterator() {
String text = BREAKITERATOREXACT[0].text;
String pattern = BREAKITERATOREXACT[0].pattern;
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening string search");
return;
}
strsrch.setBreakIterator(null);
if (strsrch.getBreakIterator() != null) {
errln("Error usearch_getBreakIterator returned wrong object");
}
strsrch.setBreakIterator(m_en_characterbreaker_);
if (!strsrch.getBreakIterator().equals(m_en_characterbreaker_)) {
errln("Error usearch_getBreakIterator returned wrong object");
}
strsrch.setBreakIterator(m_en_wordbreaker_);
if (!strsrch.getBreakIterator().equals(m_en_wordbreaker_)) {
errln("Error usearch_getBreakIterator returned wrong object");
}
int count = 0;
while (count < 4) {
// special purposes for tests numbers 0-3
SearchData search = BREAKITERATOREXACT[count];
RuleBasedCollator collator = getCollator(search.collator);
BreakIterator breaker = getBreakIterator(search.breaker);
//StringSearch strsrch;
text = search.text;
pattern = search.pattern;
if (breaker != null) {
breaker.setText(text);
}
collator.setStrength(search.strength);
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, breaker);
if (strsrch.getBreakIterator() != breaker) {
errln("Error setting break iterator");
}
if (!assertEqualWithStringSearch(strsrch, search)) {
collator.setStrength(TERTIARY);
}
search = BREAKITERATOREXACT[count + 1];
breaker = getBreakIterator(search.breaker);
if (breaker != null) {
breaker.setText(text);
}
strsrch.setBreakIterator(breaker);
if (strsrch.getBreakIterator() != breaker) {
errln("Error setting break iterator");
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, search)) {
errln("Error at test number " + count);
}
count += 2;
}
for (count = 0; count < BREAKITERATOREXACT.length; count++) {
if (!assertEqual(BREAKITERATOREXACT[count])) {
errln("Error at test number " + count);
}
}
}
public void TestBreakIteratorCanonical() {
int count = 0;
while (count < 4) {
// special purposes for tests numbers 0-3
SearchData search = BREAKITERATORCANONICAL[count];
String text = search.text;
String pattern = search.pattern;
RuleBasedCollator collator = getCollator(search.collator);
collator.setStrength(search.strength);
BreakIterator breaker = getBreakIterator(search.breaker);
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, breaker);
} catch (Exception e) {
errln("Error creating string search data");
return;
}
strsrch.setCanonical(true);
if (!strsrch.getBreakIterator().equals(breaker)) {
errln("Error setting break iterator");
return;
}
if (!assertEqualWithStringSearch(strsrch, search)) {
collator.setStrength(TERTIARY);
return;
}
search = BREAKITERATOREXACT[count + 1];
breaker = getBreakIterator(search.breaker);
breaker.setText(strsrch.getTarget());
strsrch.setBreakIterator(breaker);
if (!strsrch.getBreakIterator().equals(breaker)) {
errln("Error setting break iterator");
return;
}
strsrch.reset();
strsrch.setCanonical(true);
if (!assertEqualWithStringSearch(strsrch, search)) {
errln("Error at test number " + count);
return;
}
count += 2;
}
for (count = 0; count < BREAKITERATORCANONICAL.length; count++) {
if (!assertEqual(BREAKITERATORCANONICAL[count])) {
errln("Error at test number " + count);
return;
}
}
}
public void TestCanonical() {
for (int count = 0; count < BASICCANONICAL.length; count++) {
if (!assertCanonicalEqual(BASICCANONICAL[count])) {
errln("Error at test number " + count);
}
}
}
public void TestCollator() {
// test collator that thinks "o" and "p" are the same thing
String text = COLLATOR[0].text;
String pattern = COLLATOR[0].pattern;
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening string search ");
return;
}
if (!assertEqualWithStringSearch(strsrch, COLLATOR[0])) {
return;
}
String rules = TESTCOLLATORRULE;
RuleBasedCollator tailored = null;
try {
tailored = new RuleBasedCollator(rules);
tailored.setStrength(COLLATOR[1].strength);
} catch (Exception e) {
errln("Error opening rule based collator ");
return;
}
strsrch.setCollator(tailored);
if (!strsrch.getCollator().equals(tailored)) {
errln("Error setting rule based collator");
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, COLLATOR[1])) {
return;
}
strsrch.setCollator(m_en_us_);
strsrch.reset();
if (!strsrch.getCollator().equals(m_en_us_)) {
errln("Error setting rule based collator");
}
if (!assertEqualWithStringSearch(strsrch, COLLATOR[0])) {
errln("Error searching collator test");
}
}
public void TestCollatorCanonical() {
/* test collator that thinks "o" and "p" are the same thing */
String text = COLLATORCANONICAL[0].text;
String pattern = COLLATORCANONICAL[0].pattern;
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
strsrch.setCanonical(true);
} catch (Exception e) {
errln("Error opening string search ");
}
if (!assertEqualWithStringSearch(strsrch, COLLATORCANONICAL[0])) {
return;
}
String rules = TESTCOLLATORRULE;
RuleBasedCollator tailored = null;
try {
tailored = new RuleBasedCollator(rules);
tailored.setStrength(COLLATORCANONICAL[1].strength);
tailored.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
} catch (Exception e) {
errln("Error opening rule based collator ");
}
strsrch.setCollator(tailored);
if (!strsrch.getCollator().equals(tailored)) {
errln("Error setting rule based collator");
}
strsrch.reset();
strsrch.setCanonical(true);
if (!assertEqualWithStringSearch(strsrch, COLLATORCANONICAL[1])) {
logln("COLLATORCANONICAL[1] failed"); // Error should already be reported.
}
strsrch.setCollator(m_en_us_);
strsrch.reset();
if (!strsrch.getCollator().equals(m_en_us_)) {
errln("Error setting rule based collator");
}
if (!assertEqualWithStringSearch(strsrch, COLLATORCANONICAL[0])) {
logln("COLLATORCANONICAL[0] failed"); // Error should already be reported.
}
}
public void TestCompositeBoundaries() {
for (int count = 0; count < COMPOSITEBOUNDARIES.length; count++) {
// logln("composite " + count);
if (!assertEqual(COMPOSITEBOUNDARIES[count])) {
errln("Error at test number " + count);
}
}
}
public void TestCompositeBoundariesCanonical() {
for (int count = 0; count < COMPOSITEBOUNDARIESCANONICAL.length; count++) {
// logln("composite " + count);
if (!assertCanonicalEqual(COMPOSITEBOUNDARIESCANONICAL[count])) {
errln("Error at test number " + count);
}
}
}
public void TestContraction() {
String rules = CONTRACTIONRULE;
RuleBasedCollator collator = null;
try {
collator = new RuleBasedCollator(rules);
collator.setStrength(TERTIARY);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
} catch (Exception e) {
errln("Error opening collator ");
}
String text = "text";
String pattern = "pattern";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, null);
} catch (Exception e) {
errln("Error opening string search ");
}
for (int count = 0; count< CONTRACTION.length; count++) {
text = CONTRACTION[count].text;
pattern = CONTRACTION[count].pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
if (!assertEqualWithStringSearch(strsrch, CONTRACTION[count])) {
errln("Error at test number " + count);
}
}
}
public void TestContractionCanonical() {
String rules = CONTRACTIONRULE;
RuleBasedCollator collator = null;
try {
collator = new RuleBasedCollator(rules);
collator.setStrength(TERTIARY);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
} catch (Exception e) {
errln("Error opening collator ");
}
String text = "text";
String pattern = "pattern";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, null);
strsrch.setCanonical(true);
} catch (Exception e) {
errln("Error opening string search");
}
for (int count = 0; count < CONTRACTIONCANONICAL.length; count++) {
text = CONTRACTIONCANONICAL[count].text;
pattern = CONTRACTIONCANONICAL[count].pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
if (!assertEqualWithStringSearch(strsrch, CONTRACTIONCANONICAL[count])) {
errln("Error at test number " + count);
}
}
}
public void TestGetMatch() {
SearchData search = MATCH[0];
String text = search.text;
String pattern = search.pattern;
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening string search ");
return;
}
int count = 0;
int matchindex = search.offset[count];
String matchtext;
while (matchindex >= 0) {
int matchlength = search.size[count];
strsrch.next();
if (matchindex != strsrch.getMatchStart() ||
matchlength != strsrch.getMatchLength()) {
errln("Text: " + search.text);
errln("Pattern: " + strsrch.getPattern());
errln("Error match found at " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return;
}
count++;
matchtext = strsrch.getMatchedText();
if (matchtext.length() != matchlength){
errln("Error getting match text");
}
matchindex = search.offset[count];
}
strsrch.next();
if (strsrch.getMatchStart() != StringSearch.DONE ||
strsrch.getMatchLength() != 0) {
errln("Error end of match not found");
}
matchtext = strsrch.getMatchedText();
if (matchtext != null) {
errln("Error getting null matches");
}
}
public void TestGetSetAttribute() {
String pattern = "pattern";
String text = "text";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening search");
return;
}
if (strsrch.isOverlapping()) {
errln("Error default overlaping should be false");
}
strsrch.setOverlapping(true);
if (!strsrch.isOverlapping()) {
errln("Error setting overlap true");
}
strsrch.setOverlapping(false);
if (strsrch.isOverlapping()) {
errln("Error setting overlap false");
}
strsrch.setCanonical(true);
if (!strsrch.isCanonical()) {
errln("Error setting canonical match true");
}
strsrch.setCanonical(false);
if (strsrch.isCanonical()) {
errln("Error setting canonical match false");
}
if (strsrch.getElementComparisonType() != STANDARD_ELEMENT_COMPARISON) {
errln("Error default element comparison type should be STANDARD_ELEMENT_COMPARISON");
}
strsrch.setElementComparisonType(ElementComparisonType.PATTERN_BASE_WEIGHT_IS_WILDCARD);
if (strsrch.getElementComparisonType() != ElementComparisonType.PATTERN_BASE_WEIGHT_IS_WILDCARD) {
errln("Error setting element comparison type PATTERN_BASE_WEIGHT_IS_WILDCARD");
}
}
public void TestGetSetOffset() {
String pattern = "1234567890123456";
String text = "12345678901234567890123456789012";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening search");
return;
}
/* testing out of bounds error */
try {
strsrch.setIndex(-1);
errln("Error expecting set offset error");
} catch (IndexOutOfBoundsException e) {
logln("PASS: strsrch.setIndex(-1) failed as expected");
}
try {
strsrch.setIndex(128);
errln("Error expecting set offset error");
} catch (IndexOutOfBoundsException e) {
logln("PASS: strsrch.setIndex(128) failed as expected");
}
for (int index = 0; index < BASIC.length; index++) {
SearchData search = BASIC[index];
text =search.text;
pattern = search.pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
strsrch.getCollator().setStrength(search.strength);
strsrch.reset();
int count = 0;
int matchindex = search.offset[count];
while (matchindex >= 0) {
int matchlength = search.size[count];
strsrch.next();
if (matchindex != strsrch.getMatchStart() ||
matchlength != strsrch.getMatchLength()) {
errln("Text: " + text);
errln("Pattern: " + strsrch.getPattern());
errln("Error match found at " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return;
}
matchindex = search.offset[count + 1] == -1 ? -1 :
search.offset[count + 2];
if (search.offset[count + 1] != -1) {
strsrch.setIndex(search.offset[count + 1] + 1);
if (strsrch.getIndex() != search.offset[count + 1] + 1) {
errln("Error setting offset\n");
return;
}
}
count += 2;
}
strsrch.next();
if (strsrch.getMatchStart() != StringSearch.DONE) {
errln("Text: " + text);
errln("Pattern: " + strsrch.getPattern());
errln("Error match found at " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return;
}
}
strsrch.getCollator().setStrength(TERTIARY);
}
public void TestGetSetOffsetCanonical() {
String text = "text";
String pattern = "pattern";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Fail to open StringSearch!");
return;
}
strsrch.setCanonical(true);
//TODO: setCanonical is not sufficient for canonical match. See #10725
strsrch.getCollator().setDecomposition(Collator.CANONICAL_DECOMPOSITION);
/* testing out of bounds error */
try {
strsrch.setIndex(-1);
errln("Error expecting set offset error");
} catch (IndexOutOfBoundsException e) {
logln("PASS: strsrch.setIndex(-1) failed as expected");
}
try {
strsrch.setIndex(128);
errln("Error expecting set offset error");
} catch (IndexOutOfBoundsException e) {
logln("PASS: strsrch.setIndex(128) failed as expected");
}
for (int index = 0; index < BASICCANONICAL.length; index++) {
SearchData search = BASICCANONICAL[index];
text = search.text;
pattern = search.pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
int count = 0;
int matchindex = search.offset[count];
while (matchindex >= 0) {
int matchlength = search.size[count];
strsrch.next();
if (matchindex != strsrch.getMatchStart() ||
matchlength != strsrch.getMatchLength()) {
errln("Text: " + text);
errln("Pattern: " + strsrch.getPattern());
errln("Error match found at " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return;
}
matchindex = search.offset[count + 1] == -1 ? -1 :
search.offset[count + 2];
if (search.offset[count + 1] != -1) {
strsrch.setIndex(search.offset[count + 1] + 1);
if (strsrch.getIndex() != search.offset[count + 1] + 1) {
errln("Error setting offset");
return;
}
}
count += 2;
}
strsrch.next();
if (strsrch.getMatchStart() != StringSearch.DONE) {
errln("Text: " + text);
errln("Pattern: %s" + strsrch.getPattern());
errln("Error match found at " + strsrch.getMatchStart() + ", " + strsrch.getMatchLength());
return;
}
}
strsrch.getCollator().setStrength(TERTIARY);
strsrch.getCollator().setDecomposition(Collator.NO_DECOMPOSITION);
}
public void TestIgnorable() {
String rules = IGNORABLERULE;
int count = 0;
RuleBasedCollator collator = null;
try {
collator = new RuleBasedCollator(rules);
collator.setStrength(IGNORABLE[count].strength);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
} catch (Exception e) {
errln("Error opening collator ");
return;
}
String pattern = "pattern";
String text = "text";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, null);
} catch (Exception e) {
errln("Error opening string search ");
return;
}
for (; count < IGNORABLE.length; count++) {
text = IGNORABLE[count].text;
pattern = IGNORABLE[count].pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
if (!assertEqualWithStringSearch(strsrch, IGNORABLE[count])) {
errln("Error at test number " + count);
}
}
}
public void TestInitialization() {
String pattern;
String text;
String temp = "a";
StringSearch result;
/* simple test on the pattern ce construction */
pattern = temp + temp;
text = temp + temp + temp;
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error opening search ");
return;
}
/* testing if an extremely large pattern will fail the initialization */
pattern = "";
for (int count = 0; count < 512; count ++) {
pattern += temp;
}
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
logln("pattern:" + result.getPattern());
} catch (Exception e) {
errln("Fail: an extremely large pattern will fail the initialization");
return;
}
}
public void TestNormCanonical() {
m_en_us_.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
for (int count = 0; count < NORMCANONICAL.length; count++) {
if (!assertCanonicalEqual(NORMCANONICAL[count])) {
errln("Error at test number " + count);
}
}
m_en_us_.setDecomposition(Collator.NO_DECOMPOSITION);
}
public void TestNormExact() {
int count;
m_en_us_.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
for (count = 0; count < BASIC.length; count++) {
if (!assertEqual(BASIC[count])) {
errln("Error at test number " + count);
}
}
for (count = 0; count < NORMEXACT.length; count++) {
if (!assertEqual(NORMEXACT[count])) {
errln("Error at test number " + count);
}
}
m_en_us_.setDecomposition(Collator.NO_DECOMPOSITION);
for (count = 0; count < NONNORMEXACT.length; count++) {
if (!assertEqual(NONNORMEXACT[count])) {
errln("Error at test number " + count);
}
}
}
public void TestOpenClose() {
StringSearch result;
BreakIterator breakiter = m_en_wordbreaker_;
String pattern = "";
String text = "";
String temp = "a";
StringCharacterIterator chariter= new StringCharacterIterator(text);
/* testing null arguments */
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), null, null);
errln("Error: null arguments should produce an error");
} catch (Exception e) {
logln("PASS: null arguments failed as expected");
}
chariter.setText(text);
try {
result = new StringSearch(pattern, chariter, null, null);
errln("Error: null arguments should produce an error");
} catch (Exception e) {
logln("PASS: null arguments failed as expected");
}
text = String.valueOf(0x1);
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), null, null);
errln("Error: Empty pattern should produce an error");
} catch (Exception e) {
logln("PASS: Empty pattern failed as expected");
}
chariter.setText(text);
try {
result = new StringSearch(pattern, chariter, null, null);
errln("Error: Empty pattern should produce an error");
} catch (Exception e) {
logln("PASS: Empty pattern failed as expected");
}
text = "";
pattern =temp;
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), null, null);
errln("Error: Empty text should produce an error");
} catch (Exception e) {
logln("PASS: Empty text failed as expected");
}
chariter.setText(text);
try {
result = new StringSearch(pattern, chariter, null, null);
errln("Error: Empty text should produce an error");
} catch (Exception e) {
logln("PASS: Empty text failed as expected");
}
text += temp;
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), null, null);
errln("Error: null arguments should produce an error");
} catch (Exception e) {
logln("PASS: null arguments failed as expected");
}
chariter.setText(text);
try {
result = new StringSearch(pattern, chariter, null, null);
errln("Error: null arguments should produce an error");
} catch (Exception e) {
logln("PASS: null arguments failed as expected");
}
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, null);
} catch (Exception e) {
errln("Error: null break iterator is valid for opening search");
}
try {
result = new StringSearch(pattern, chariter, m_en_us_, null);
} catch (Exception e) {
errln("Error: null break iterator is valid for opening search");
}
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), Locale.ENGLISH);
} catch (Exception e) {
errln("Error: null break iterator is valid for opening search");
}
try {
result = new StringSearch(pattern, chariter, Locale.ENGLISH);
} catch (Exception e) {
errln("Error: null break iterator is valid for opening search");
}
try {
result = new StringSearch(pattern, new StringCharacterIterator(text), m_en_us_, breakiter);
} catch (Exception e) {
errln("Error: Break iterator is valid for opening search");
}
try {
result = new StringSearch(pattern, chariter, m_en_us_, null);
logln("pattern:" + result.getPattern());
} catch (Exception e) {
errln("Error: Break iterator is valid for opening search");
}
}
public void TestOverlap() {
int count;
for (count = 0; count < OVERLAP.length; count++) {
if (!assertEqualWithAttribute(OVERLAP[count], false, true)) {
errln("Error at overlap test number " + count);
}
}
for (count = 0; count < NONOVERLAP.length; count++) {
if (!assertEqual(NONOVERLAP[count])) {
errln("Error at non overlap test number " + count);
}
}
for (count = 0; count < OVERLAP.length && count < NONOVERLAP.length; count++) {
SearchData search = (OVERLAP[count]);
String text = search.text;
String pattern = search.pattern;
RuleBasedCollator collator = getCollator(search.collator);
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, new StringCharacterIterator(text), collator, null);
} catch (Exception e) {
errln("error open StringSearch");
return;
}
strsrch.setOverlapping(true);
if (!strsrch.isOverlapping()) {
errln("Error setting overlap option");
}
if (!assertEqualWithStringSearch(strsrch, search)) {
return;
}
search = NONOVERLAP[count];
strsrch.setOverlapping(false);
if (strsrch.isOverlapping()) {
errln("Error setting overlap option");
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, search)) {
errln("Error at test number " + count);
}
}
}
public void TestOverlapCanonical() {
int count;
for (count = 0; count < OVERLAPCANONICAL.length; count++) {
if (!assertEqualWithAttribute(OVERLAPCANONICAL[count], true, true)) {
errln("Error at overlap test number %d" + count);
}
}
for (count = 0; count < NONOVERLAP.length; count++) {
if (!assertCanonicalEqual(NONOVERLAPCANONICAL[count])) {
errln("Error at non overlap test number %d" + count);
}
}
for (count = 0; count < OVERLAPCANONICAL.length && count < NONOVERLAPCANONICAL.length; count++) {
SearchData search = OVERLAPCANONICAL[count];
RuleBasedCollator collator = getCollator(search.collator);
StringSearch strsrch = new StringSearch(search.pattern, new StringCharacterIterator(search.text), collator, null);
strsrch.setCanonical(true);
strsrch.setOverlapping(true);
if (strsrch.isOverlapping() != true) {
errln("Error setting overlap option");
}
if (!assertEqualWithStringSearch(strsrch, search)) {
strsrch = null;
return;
}
search = NONOVERLAPCANONICAL[count];
strsrch.setOverlapping(false);
if (strsrch.isOverlapping() != false) {
errln("Error setting overlap option");
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, search)) {
strsrch = null;
errln("Error at test number %d" + count);
}
}
}
public void TestPattern() {
m_en_us_.setStrength(PATTERN[0].strength);
StringSearch strsrch = new StringSearch(PATTERN[0].pattern, new StringCharacterIterator(PATTERN[0].text), m_en_us_, null);
if (strsrch.getPattern() != PATTERN[0].pattern) {
errln("Error setting pattern");
}
if (!assertEqualWithStringSearch(strsrch, PATTERN[0])) {
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
return;
}
strsrch.setPattern(PATTERN[1].pattern);
if (PATTERN[1].pattern != strsrch.getPattern()) {
errln("Error setting pattern");
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
return;
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, PATTERN[1])) {
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
return;
}
strsrch.setPattern(PATTERN[0].pattern);
if (PATTERN[0].pattern != strsrch.getPattern()) {
errln("Error setting pattern");
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
return;
}
strsrch.reset();
if (!assertEqualWithStringSearch(strsrch, PATTERN[0])) {
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
return;
}
/* enormous pattern size to see if this crashes */
String pattern = "";
for (int templength = 0; templength != 512; templength ++) {
pattern += 0x61;
}
try{
strsrch.setPattern(pattern);
}catch(Exception e) {
errln("Error setting pattern with size 512");
}
m_en_us_.setStrength(TERTIARY);
if (strsrch != null) {
strsrch = null;
}
}
public void TestPatternCanonical() {
//StringCharacterIterator text = new StringCharacterIterator(PATTERNCANONICAL[0].text);
m_en_us_.setStrength(PATTERNCANONICAL[0].strength);
StringSearch strsrch = new StringSearch(PATTERNCANONICAL[0].pattern, new StringCharacterIterator(PATTERNCANONICAL[0].text),
m_en_us_, null);
strsrch.setCanonical(true);
if (PATTERNCANONICAL[0].pattern != strsrch.getPattern()) {
errln("Error setting pattern");
}
if (!assertEqualWithStringSearch(strsrch, PATTERNCANONICAL[0])) {
m_en_us_.setStrength(TERTIARY);
strsrch = null;
return;
}
strsrch.setPattern(PATTERNCANONICAL[1].pattern);
if (PATTERNCANONICAL[1].pattern != strsrch.getPattern()) {
errln("Error setting pattern");
m_en_us_.setStrength(TERTIARY);
strsrch = null;
return;
}
strsrch.reset();
strsrch.setCanonical(true);
if (!assertEqualWithStringSearch(strsrch, PATTERNCANONICAL[1])) {
m_en_us_.setStrength(TERTIARY);
strsrch = null;
return;
}
strsrch.setPattern(PATTERNCANONICAL[0].pattern);
if (PATTERNCANONICAL[0].pattern != strsrch.getPattern()) {
errln("Error setting pattern");
m_en_us_.setStrength(TERTIARY);
strsrch = null;
return;
}
strsrch.reset();
strsrch.setCanonical(true);
if (!assertEqualWithStringSearch(strsrch, PATTERNCANONICAL[0])) {
m_en_us_.setStrength(TERTIARY);
strsrch = null;
return;
}
}
public void TestReset() {
StringCharacterIterator text = new StringCharacterIterator("fish fish");
String pattern = "s";
StringSearch strsrch = new StringSearch(pattern, text, m_en_us_, null);
strsrch.setOverlapping(true);
strsrch.setCanonical(true);
strsrch.setIndex(9);
strsrch.reset();
if (strsrch.isCanonical() || strsrch.isOverlapping() ||
strsrch.getIndex() != 0 || strsrch.getMatchLength() != 0 ||
strsrch.getMatchStart() != SearchIterator.DONE) {
errln("Error resetting string search");
}
strsrch.previous();
if (strsrch.getMatchStart() != 7 || strsrch.getMatchLength() != 1) {
errln("Error resetting string search\n");
}
}
public void TestSetMatch() {
for (int count = 0; count < MATCH.length; count++) {
SearchData search = MATCH[count];
StringSearch strsrch = new StringSearch(search.pattern, new StringCharacterIterator(search.text),
m_en_us_, null);
int size = 0;
while (search.offset[size] != -1) {
size ++;
}
if (strsrch.first() != search.offset[0]) {
errln("Error getting first match");
}
if (strsrch.last() != search.offset[size -1]) {
errln("Error getting last match");
}
int index = 0;
while (index < size) {
if (index + 2 < size) {
if (strsrch.following(search.offset[index + 2] - 1) != search.offset[index + 2]) {
errln("Error getting following match at index " + (search.offset[index + 2]-1));
}
}
if (index + 1 < size) {
if (strsrch.preceding(search.offset[index + 1] + search.size[index + 1] + 1) != search.offset[index + 1]) {
errln("Error getting preceeding match at index " + (search.offset[index + 1] + 1));
}
}
index += 2;
}
if (strsrch.following(search.text.length()) != SearchIterator.DONE) {
errln("Error expecting out of bounds match");
}
if (strsrch.preceding(0) != SearchIterator.DONE) {
errln("Error expecting out of bounds match");
}
}
}
public void TestStrength() {
for (int count = 0; count < STRENGTH.length; count++) {
if (!assertEqual(STRENGTH[count])) {
errln("Error at test number " + count);
}
}
}
public void TestStrengthCanonical() {
for (int count = 0; count < STRENGTHCANONICAL.length; count++) {
if (!assertCanonicalEqual(STRENGTHCANONICAL[count])) {
errln("Error at test number" + count);
}
}
}
public void TestSupplementary() {
for (int count = 0; count < SUPPLEMENTARY.length; count++) {
if (!assertEqual(SUPPLEMENTARY[count])) {
errln("Error at test number " + count);
}
}
}
public void TestSupplementaryCanonical() {
for (int count = 0; count < SUPPLEMENTARYCANONICAL.length; count++) {
if (!assertCanonicalEqual(SUPPLEMENTARYCANONICAL[count])) {
errln("Error at test number" + count);
}
}
}
public void TestText() {
SearchData TEXT[] = {
SD("the foxy brown fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(4, 15, -1), IA(3, 3)),
SD("the quick brown fox", "fox", null, TERTIARY, STANDARD_ELEMENT_COMPARISON, null, IA(16, -1), IA(3))
};
StringCharacterIterator t = new StringCharacterIterator(TEXT[0].text);
StringSearch strsrch = new StringSearch(TEXT[0].pattern, t, m_en_us_, null);
if (!t.equals(strsrch.getTarget())) {
errln("Error setting text");
}
if (!assertEqualWithStringSearch(strsrch, TEXT[0])) {
errln("Error at assertEqualWithStringSearch");
return;
}
t = new StringCharacterIterator(TEXT[1].text);
strsrch.setTarget(t);
if (!t.equals(strsrch.getTarget())) {
errln("Error setting text");
return;
}
if (!assertEqualWithStringSearch(strsrch, TEXT[1])) {
errln("Error at assertEqualWithStringSearch");
return;
}
}
public void TestTextCanonical() {
StringCharacterIterator t = new StringCharacterIterator(TEXTCANONICAL[0].text);
StringSearch strsrch = new StringSearch(TEXTCANONICAL[0].pattern, t, m_en_us_, null);
strsrch.setCanonical(true);
if (!t.equals(strsrch.getTarget())) {
errln("Error setting text");
}
if (!assertEqualWithStringSearch(strsrch, TEXTCANONICAL[0])) {
strsrch = null;
return;
}
t = new StringCharacterIterator(TEXTCANONICAL[1].text);
strsrch.setTarget(t);
if (!t.equals(strsrch.getTarget())) {
errln("Error setting text");
strsrch = null;
return;
}
if (!assertEqualWithStringSearch(strsrch, TEXTCANONICAL[1])) {
strsrch = null;
return;
}
t = new StringCharacterIterator(TEXTCANONICAL[0].text);
strsrch.setTarget(t);
if (!t.equals(strsrch.getTarget())) {
errln("Error setting text");
strsrch = null;
return;
}
if (!assertEqualWithStringSearch(strsrch, TEXTCANONICAL[0])) {
errln("Error at assertEqualWithStringSearch");
strsrch = null;
return;
}
}
public void TestVariable() {
m_en_us_.setAlternateHandlingShifted(true);
for (int count = 0; count < VARIABLE.length; count++) {
// logln("variable" + count);
if (!assertEqual(VARIABLE[count])) {
errln("Error at test number " + count);
}
}
m_en_us_.setAlternateHandlingShifted(false);
}
public void TestVariableCanonical() {
m_en_us_.setAlternateHandlingShifted(true);
for (int count = 0; count < VARIABLE.length; count++) {
// logln("variable " + count);
if (!assertCanonicalEqual(VARIABLE[count])) {
errln("Error at test number " + count);
}
}
m_en_us_.setAlternateHandlingShifted(false);
}
public void TestSubClass()
{
class TestSearch extends SearchIterator
{
String pattern;
String text;
TestSearch(StringCharacterIterator target, BreakIterator breaker,
String pattern)
{
super(target, breaker);
this.pattern = pattern;
StringBuffer buffer = new StringBuffer();
while (targetText.getIndex() != targetText.getEndIndex()) {
buffer.append(targetText.current());
targetText.next();
}
text = buffer.toString();
targetText.setIndex(targetText.getBeginIndex());
}
protected int handleNext(int start)
{
int match = text.indexOf(pattern, start);
if (match < 0) {
targetText.last();
return DONE;
}
targetText.setIndex(match);
setMatchLength(pattern.length());
return match;
}
protected int handlePrevious(int start)
{
int match = text.lastIndexOf(pattern, start - 1);
if (match < 0) {
targetText.setIndex(0);
return DONE;
}
targetText.setIndex(match);
setMatchLength(pattern.length());
return match;
}
public int getIndex()
{
int result = targetText.getIndex();
if (result < 0 || result >= text.length()) {
return DONE;
}
return result;
}
}
TestSearch search = new TestSearch(
new StringCharacterIterator("abc abcd abc"),
null, "abc");
int expected[] = {0, 4, 9};
for (int i = 0; i < expected.length; i ++) {
if (search.next() != expected[i]) {
errln("Error getting next match");
}
if (search.getMatchLength() != search.pattern.length()) {
errln("Error getting next match length");
}
}
if (search.next() != SearchIterator.DONE) {
errln("Error should have reached the end of the iteration");
}
for (int i = expected.length - 1; i >= 0; i --) {
if (search.previous() != expected[i]) {
errln("Error getting next match");
}
if (search.getMatchLength() != search.pattern.length()) {
errln("Error getting next match length");
}
}
if (search.previous() != SearchIterator.DONE) {
errln("Error should have reached the start of the iteration");
}
}
//Test for ticket 5024
public void TestDiactricMatch() {
String pattern = "pattern";
String text = "text";
StringSearch strsrch = null;
try {
strsrch = new StringSearch(pattern, text);
} catch (Exception e) {
errln("Error opening string search ");
return;
}
for (int count = 0; count < DIACTRICMATCH.length; count++) {
strsrch.setCollator(getCollator(DIACTRICMATCH[count].collator));
strsrch.getCollator().setStrength(DIACTRICMATCH[count].strength);
strsrch.setBreakIterator(getBreakIterator(DIACTRICMATCH[count].breaker));
strsrch.reset();
text = DIACTRICMATCH[count].text;
pattern = DIACTRICMATCH[count].pattern;
strsrch.setTarget(new StringCharacterIterator(text));
strsrch.setPattern(pattern);
if (!assertEqualWithStringSearch(strsrch, DIACTRICMATCH[count])) {
errln("Error at test number " + count);
}
}
}
public void TestUsingSearchCollator() {
String scKoText =
" " +
/*01*/ "\uAC00 " + // simple LV Hangul
/*03*/ "\uAC01 " + // simple LVT Hangul
/*05*/ "\uAC0F " + // LVTT, last jamo expands for search
/*07*/ "\uAFFF " + // LLVVVTT, every jamo expands for search
/*09*/ "\u1100\u1161\u11A8 " + // 0xAC01 as conjoining jamo
/*13*/ "\u1100\u1161\u1100 " + // 0xAC01 as basic conjoining jamo (per search rules)
/*17*/ "\u3131\u314F\u3131 " + // 0xAC01 as compatibility jamo
/*21*/ "\u1100\u1161\u11B6 " + // 0xAC0F as conjoining jamo; last expands for search
/*25*/ "\u1100\u1161\u1105\u1112 " + // 0xAC0F as basic conjoining jamo; last expands for search
/*30*/ "\u1101\u1170\u11B6 " + // 0xAFFF as conjoining jamo; all expand for search
/*34*/ "\u00E6 " + // small letter ae, expands
/*36*/ "\u1E4D " + // small letter o with tilde and acute, decomposes
"";
String scKoPat0 = "\uAC01";
String scKoPat1 = "\u1100\u1161\u11A8"; // 0xAC01 as conjoining jamo
String scKoPat2 = "\uAC0F";
String scKoPat3 = "\u1100\u1161\u1105\u1112"; // 0xAC0F as basic conjoining jamo
String scKoPat4 = "\uAFFF";
String scKoPat5 = "\u1101\u1170\u11B6"; // 0xAFFF as conjoining jamo
int[] scKoSrchOff01 = { 3, 9, 13 };
int[] scKoSrchOff23 = { 5, 21, 25 };
int[] scKoSrchOff45 = { 7, 30 };
int[] scKoStndOff01 = { 3, 9 };
int[] scKoStndOff2 = { 5, 21 };
int[] scKoStndOff3 = { 25 };
int[] scKoStndOff45 = { 7, 30 };
class PatternAndOffsets {
private String pattern;
private int[] offsets;
PatternAndOffsets(String pat, int[] offs) {
pattern = pat;
offsets = offs;
}
public String getPattern() { return pattern; }
public int[] getOffsets() { return offsets; }
}
final PatternAndOffsets[] scKoSrchPatternsOffsets = {
new PatternAndOffsets( scKoPat0, scKoSrchOff01 ),
new PatternAndOffsets( scKoPat1, scKoSrchOff01 ),
new PatternAndOffsets( scKoPat2, scKoSrchOff23 ),
new PatternAndOffsets( scKoPat3, scKoSrchOff23 ),
new PatternAndOffsets( scKoPat4, scKoSrchOff45 ),
new PatternAndOffsets( scKoPat5, scKoSrchOff45 ),
};
final PatternAndOffsets[] scKoStndPatternsOffsets = {
new PatternAndOffsets( scKoPat0, scKoStndOff01 ),
new PatternAndOffsets( scKoPat1, scKoStndOff01 ),
new PatternAndOffsets( scKoPat2, scKoStndOff2 ),
new PatternAndOffsets( scKoPat3, scKoStndOff3 ),
new PatternAndOffsets( scKoPat4, scKoStndOff45 ),
new PatternAndOffsets( scKoPat5, scKoStndOff45 ),
};
class TUSCItem {
private String localeString;
private String text;
private PatternAndOffsets[] patternsAndOffsets;
TUSCItem(String locStr, String txt, PatternAndOffsets[] patsAndOffs) {
localeString = locStr;
text = txt;
patternsAndOffsets = patsAndOffs;
}
public String getLocaleString() { return localeString; }
public String getText() { return text; }
public PatternAndOffsets[] getPatternsAndOffsets() { return patternsAndOffsets; }
}
final TUSCItem[] tuscItems = {
new TUSCItem( "root", scKoText, scKoStndPatternsOffsets ),
new TUSCItem( "root@collation=search", scKoText, scKoSrchPatternsOffsets ),
new TUSCItem( "ko@collation=search", scKoText, scKoSrchPatternsOffsets ),
};
String dummyPat = "a";
for (TUSCItem tuscItem: tuscItems) {
String localeString = tuscItem.getLocaleString();
ULocale uloc = new ULocale(localeString);
RuleBasedCollator col = null;
try {
col = (RuleBasedCollator)Collator.getInstance(uloc);
} catch (Exception e) {
errln("Error: in locale " + localeString + ", err in Collator.getInstance");
continue;
}
StringCharacterIterator ci = new StringCharacterIterator(tuscItem.getText());
StringSearch srch = new StringSearch(dummyPat, ci, col);
for ( PatternAndOffsets patternAndOffsets: tuscItem.getPatternsAndOffsets() ) {
srch.setPattern(patternAndOffsets.getPattern());
int[] offsets = patternAndOffsets.getOffsets();
int ioff, noff = offsets.length;
int offset;
srch.reset();
ioff = 0;
while (true) {
offset = srch.next();
if (offset == SearchIterator.DONE) {
break;
}
if ( ioff < noff ) {
if ( offset != offsets[ioff] ) {
errln("Error: in locale " + localeString + ", expected SearchIterator.next() " + offsets[ioff] + ", got " + offset);
//ioff = noff;
//break;
}
ioff++;
} else {
errln("Error: in locale " + localeString + ", SearchIterator.next() returned more matches than expected");
}
}
if ( ioff < noff ) {
errln("Error: in locale " + localeString + ", SearchIterator.next() returned fewer matches than expected");
}
srch.reset();
ioff = noff;
while (true) {
offset = srch.previous();
if (offset == SearchIterator.DONE) {
break;
}
if ( ioff > 0 ) {
ioff--;
if ( offset != offsets[ioff] ) {
errln("Error: in locale " + localeString + ", expected SearchIterator.previous() " + offsets[ioff] + ", got " + offset);
//ioff = 0;
// break;
}
} else {
errln("Error: in locale " + localeString + ", expected SearchIterator.previous() returned more matches than expected");
}
}
if ( ioff > 0 ) {
errln("Error: in locale " + localeString + ", expected SearchIterator.previous() returned fewer matches than expected");
}
}
}
}
}