2 ***************************************************************************** 
   3 * Copyright (C) 2001-2010, International Business Machines orporation   
   4 * and others. All Rights Reserved. 
   5 ****************************************************************************/ 
   7 #include "unicode/utypes.h" 
   9 #if !UCONFIG_NO_COLLATION 
  12 #if !UCONFIG_NO_BREAK_ITERATION 
  13 #include "../cintltst/usrchdat.c" 
  15 #include "unicode/stsearch.h" 
  16 #include "unicode/ustring.h" 
  17 #include "unicode/schriter.h" 
  21 // private definitions ----------------------------------------------------- 
  23 #define CASE(id,test)                 \ 
  28             logln((UnicodeString)""); \ 
  30                   dataerrln(__FILE__ " cannot test - failed to create collator.");  \ 
  37 // public contructors and destructors -------------------------------------- 
  39 StringSearchTest::StringSearchTest()  
  40 #if !UCONFIG_NO_BREAK_ITERATION 
  42     m_en_wordbreaker_(NULL
), m_en_characterbreaker_(NULL
) 
  45 #if !UCONFIG_NO_BREAK_ITERATION 
  46     UErrorCode    status 
= U_ZERO_ERROR
; 
  48     m_en_us_ 
= (RuleBasedCollator 
*)Collator::createInstance("en_US", status
); 
  49     m_fr_fr_ 
= (RuleBasedCollator 
*)Collator::createInstance("fr_FR", status
); 
  50     m_de_    
= (RuleBasedCollator 
*)Collator::createInstance("de_DE", status
); 
  51     m_es_    
= (RuleBasedCollator 
*)Collator::createInstance("es_ES", status
); 
  52     if(U_FAILURE(status
)) { 
  61       errln("Collator creation failed with %s", u_errorName(status
)); 
  67     rules
.setTo(((RuleBasedCollator 
*)m_de_
)->getRules()); 
  68     UChar extrarules
[128]; 
  69     u_unescape(EXTRACOLLATIONRULE
, extrarules
, 128); 
  70     rules
.append(extrarules
, u_strlen(extrarules
)); 
  73     m_de_ 
= new RuleBasedCollator(rules
, status
); 
  75     rules
.setTo(((RuleBasedCollator 
*)m_es_
)->getRules()); 
  76     rules
.append(extrarules
, u_strlen(extrarules
)); 
  80     m_es_ 
= new RuleBasedCollator(rules
, status
);  
  82 #if !UCONFIG_NO_BREAK_ITERATION 
  83     m_en_wordbreaker_      
= BreakIterator::createWordInstance( 
  84                                                     Locale::getEnglish(), status
); 
  85     m_en_characterbreaker_ 
= BreakIterator::createCharacterInstance( 
  86                                                     Locale::getEnglish(), status
); 
  91 StringSearchTest::~StringSearchTest()  
  93 #if !UCONFIG_NO_BREAK_ITERATION 
  98 #if !UCONFIG_NO_BREAK_ITERATION 
  99     delete m_en_wordbreaker_
; 
 100     delete m_en_characterbreaker_
; 
 105 // public methods ---------------------------------------------------------- 
 107 void StringSearchTest::runIndexedTest(int32_t index
, UBool exec
,  
 108                                       const char* &name
, char* )  
 110 #if !UCONFIG_NO_BREAK_ITERATION 
 111     UBool areBroken 
= FALSE
; 
 112     if (m_en_us_ 
== NULL 
&& m_fr_fr_ 
== NULL 
&& m_de_ 
== NULL 
&& 
 113         m_es_ 
== NULL 
&& m_en_wordbreaker_ 
== NULL 
&& 
 114         m_en_characterbreaker_ 
== NULL 
&& exec
) { 
 119 #if !UCONFIG_NO_FILE_IO 
 120         CASE(0, TestOpenClose
) 
 122         CASE(1, TestInitialization
) 
 124         CASE(3, TestNormExact
) 
 125         CASE(4, TestStrength
) 
 126 #if UCONFIG_NO_BREAK_ITERATION 
 128         name 
= "TestBreakIterator"; 
 131         CASE(5, TestBreakIterator
) 
 133         CASE(6, TestVariable
) 
 135         CASE(8, TestCollator
) 
 138         CASE(11, TestCompositeBoundaries
) 
 139         CASE(12, TestGetSetOffset
) 
 140         CASE(13, TestGetSetAttribute
) 
 141         CASE(14, TestGetMatch
) 
 142         CASE(15, TestSetMatch
) 
 144         CASE(17, TestSupplementary
) 
 145         CASE(18, TestContraction
) 
 146         CASE(19, TestIgnorable
) 
 147         CASE(20, TestCanonical
) 
 148         CASE(21, TestNormCanonical
) 
 149         CASE(22, TestStrengthCanonical
) 
 150 #if UCONFIG_NO_BREAK_ITERATION 
 152         name 
= "TestBreakIteratorCanonical"; 
 155         CASE(23, TestBreakIteratorCanonical
) 
 157         CASE(24, TestVariableCanonical
) 
 158         CASE(25, TestOverlapCanonical
) 
 159         CASE(26, TestCollatorCanonical
) 
 160         CASE(27, TestPatternCanonical
) 
 161         CASE(28, TestTextCanonical
) 
 162         CASE(29, TestCompositeBoundariesCanonical
) 
 163         CASE(30, TestGetSetOffsetCanonical
) 
 164         CASE(31, TestSupplementaryCanonical
) 
 165         CASE(32, TestContractionCanonical
) 
 166         CASE(33, TestUClassID
) 
 167         CASE(34, TestSubclass
) 
 168         CASE(35, TestCoverage
) 
 169         CASE(36, TestDiacriticMatch
) 
 170         default: name 
= ""; break; 
 177 #if !UCONFIG_NO_BREAK_ITERATION 
 178 // private methods ------------------------------------------------------ 
 180 RuleBasedCollator 
* StringSearchTest::getCollator(const char *collator
) 
 182     if (collator 
== NULL
) { 
 185     if (strcmp(collator
, "fr") == 0) { 
 188     else if (strcmp(collator
, "de") == 0) { 
 191     else if (strcmp(collator
, "es") == 0) { 
 199 BreakIterator 
* StringSearchTest::getBreakIterator(const char *breaker
) 
 201 #if UCONFIG_NO_BREAK_ITERATION 
 204     if (breaker 
== NULL
) { 
 207     if (strcmp(breaker
, "wordbreaker") == 0) { 
 208         return m_en_wordbreaker_
; 
 211         return m_en_characterbreaker_
; 
 216 char * StringSearchTest::toCharString(const UnicodeString 
&text
) 
 218     static char   result
[1024]; 
 221            int    length 
= text
.length(); 
 223     for (; count 
< length
; count 
++) { 
 224         UChar ch 
= text
[count
]; 
 225         if (ch 
>= 0x20 && ch 
<= 0x7e) { 
 226             result
[index 
++] = (char)ch
; 
 229             sprintf(result
+index
, "\\u%04x", ch
); 
 230             index 
+= 6; /* \uxxxx */ 
 238 Collator::ECollationStrength 
StringSearchTest::getECollationStrength( 
 239                                     const UCollationStrength 
&strength
) const 
 244     return Collator::PRIMARY
; 
 245   case UCOL_SECONDARY 
: 
 246     return Collator::SECONDARY
; 
 248     return Collator::TERTIARY
; 
 250     return Collator::IDENTICAL
; 
 254 UBool 
StringSearchTest::assertEqualWithStringSearch(StringSearch 
*strsrch
, 
 255                                                     const SearchData 
*search
) 
 258     UErrorCode    status      
= U_ZERO_ERROR
; 
 259     int32_t   matchindex  
= search
->offset
[count
]; 
 260     UnicodeString matchtext
; 
 262     strsrch
->setAttribute(USEARCH_ELEMENT_COMPARISON
, search
->elemCompare
, status
); 
 263     if (U_FAILURE(status
)) { 
 264         errln("Error setting USEARCH_ELEMENT_COMPARISON attribute %s", u_errorName(status
)); 
 268     if (strsrch
->getMatchedStart() != USEARCH_DONE 
|| 
 269         strsrch
->getMatchedLength() != 0) { 
 270         errln("Error with the initialization of match start and length"); 
 272     // start of following matches  
 273     while (U_SUCCESS(status
) && matchindex 
>= 0) { 
 274         int32_t matchlength 
= search
->size
[count
]; 
 275         strsrch
->next(status
); 
 276         if (matchindex 
!= strsrch
->getMatchedStart() ||  
 277             matchlength 
!= strsrch
->getMatchedLength()) { 
 278             char *str 
= toCharString(strsrch
->getText()); 
 279             errln("Text: %s", str
); 
 280             str 
= toCharString(strsrch
->getPattern()); 
 281             infoln("Pattern: %s", str
); 
 282             infoln("Error following match found at idx,len %d,%d; expected %d,%d",  
 283                     strsrch
->getMatchedStart(), strsrch
->getMatchedLength(), 
 284                     matchindex
, matchlength
); 
 289         strsrch
->getMatchedText(matchtext
); 
 291         if (U_FAILURE(status
) || 
 292             strsrch
->getText().compareBetween(matchindex
,  
 293                                               matchindex 
+ matchlength
, 
 295                                               matchtext
.length())) { 
 296             errln("Error getting following matched text"); 
 299         matchindex 
= search
->offset
[count
]; 
 301     strsrch
->next(status
); 
 302     if (strsrch
->getMatchedStart() != USEARCH_DONE 
|| 
 303         strsrch
->getMatchedLength() != 0) { 
 304         char *str 
= toCharString(strsrch
->getText()); 
 305             errln("Text: %s", str
); 
 306             str 
= toCharString(strsrch
->getPattern()); 
 307             errln("Pattern: %s", str
); 
 308             errln("Error following match found at %d %d",  
 309                     strsrch
->getMatchedStart(), strsrch
->getMatchedLength()); 
 312     // start of preceding matches  
 313     count 
= count 
== 0 ? 0 : count 
- 1; 
 314     matchindex 
= search
->offset
[count
]; 
 315     while (U_SUCCESS(status
) && matchindex 
>= 0) { 
 316         int32_t matchlength 
= search
->size
[count
]; 
 317         strsrch
->previous(status
); 
 318         if (matchindex 
!= strsrch
->getMatchedStart() ||  
 319             matchlength 
!= strsrch
->getMatchedLength()) { 
 320             char *str 
= toCharString(strsrch
->getText()); 
 321             errln("Text: %s", str
); 
 322             str 
= toCharString(strsrch
->getPattern()); 
 323             errln("Pattern: %s", str
); 
 324             errln("Error following match found at %d %d",  
 325                     strsrch
->getMatchedStart(), strsrch
->getMatchedLength()); 
 329         strsrch
->getMatchedText(matchtext
); 
 331         if (U_FAILURE(status
) || 
 332             strsrch
->getText().compareBetween(matchindex
,  
 333                                               matchindex 
+ matchlength
, 
 335                                               matchtext
.length())) { 
 336             errln("Error getting following matched text"); 
 339         matchindex 
= count 
> 0 ? search
->offset
[count 
- 1] : -1; 
 342     strsrch
->previous(status
); 
 343     if (strsrch
->getMatchedStart() != USEARCH_DONE 
|| 
 344         strsrch
->getMatchedLength() != 0) { 
 345         char *str 
= toCharString(strsrch
->getText()); 
 346             errln("Text: %s", str
); 
 347             str 
= toCharString(strsrch
->getPattern()); 
 348             errln("Pattern: %s", str
); 
 349             errln("Error following match found at %d %d",  
 350                     strsrch
->getMatchedStart(), strsrch
->getMatchedLength()); 
 353     strsrch
->setAttribute(USEARCH_ELEMENT_COMPARISON
, USEARCH_STANDARD_ELEMENT_COMPARISON
, status
); 
 357 UBool 
StringSearchTest::assertEqual(const SearchData 
*search
) 
 359     UErrorCode     status   
= U_ZERO_ERROR
; 
 361     Collator      
*collator 
= getCollator(search
->collator
); 
 362     BreakIterator 
*breaker  
= getBreakIterator(search
->breaker
); 
 363     StringSearch  
*strsrch
, *strsrch2
; 
 366 #if UCONFIG_NO_BREAK_ITERATION 
 367     if(search
->breaker
) { 
 368       return TRUE
; /* skip test */ 
 371     u_unescape(search
->text
, temp
, 128); 
 374     u_unescape(search
->pattern
, temp
, 128); 
 375     UnicodeString  pattern
; 
 378 #if !UCONFIG_NO_BREAK_ITERATION 
 379     if (breaker 
!= NULL
) { 
 380         breaker
->setText(text
); 
 383     collator
->setStrength(getECollationStrength(search
->strength
)); 
 384     strsrch 
= new StringSearch(pattern
, text
, (RuleBasedCollator 
*)collator
,  
 386     if (U_FAILURE(status
)) { 
 387         errln("Error opening string search %s", u_errorName(status
)); 
 391     if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 392         collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 398     strsrch2 
= strsrch
->clone(); 
 399     if( strsrch2 
== strsrch 
|| *strsrch2 
!= *strsrch 
|| 
 400         !assertEqualWithStringSearch(strsrch2
, search
) 
 402         infoln("failure with StringSearch.clone()"); 
 403         collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 410     collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 415 UBool 
StringSearchTest::assertCanonicalEqual(const SearchData 
*search
) 
 417     UErrorCode     status   
= U_ZERO_ERROR
; 
 418     Collator      
*collator 
= getCollator(search
->collator
); 
 419     BreakIterator 
*breaker  
= getBreakIterator(search
->breaker
); 
 420     StringSearch  
*strsrch
;  
 424 #if UCONFIG_NO_BREAK_ITERATION 
 425     if(search
->breaker
) { 
 426       return TRUE
; /* skip test */ 
 430     u_unescape(search
->text
, temp
, 128); 
 433     u_unescape(search
->pattern
, temp
, 128); 
 434     UnicodeString  pattern
; 
 437 #if !UCONFIG_NO_BREAK_ITERATION 
 438     if (breaker 
!= NULL
) { 
 439         breaker
->setText(text
); 
 442     collator
->setStrength(getECollationStrength(search
->strength
)); 
 443     collator
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_ON
, status
); 
 444     strsrch 
= new StringSearch(pattern
, text
, (RuleBasedCollator 
*)collator
,  
 446     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
 447     if (U_FAILURE(status
)) { 
 448         errln("Error opening string search %s", u_errorName(status
)); 
 453     if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 459     collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 460     collator
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_OFF
, status
); 
 466 UBool 
StringSearchTest::assertEqualWithAttribute(const SearchData 
*search
,  
 467                                             USearchAttributeValue canonical
, 
 468                                             USearchAttributeValue overlap
) 
 470     UErrorCode     status   
= U_ZERO_ERROR
; 
 471     Collator      
*collator 
= getCollator(search
->collator
); 
 472     BreakIterator 
*breaker  
= getBreakIterator(search
->breaker
); 
 473     StringSearch  
*strsrch
;  
 477 #if UCONFIG_NO_BREAK_ITERATION 
 478     if(search
->breaker
) { 
 479       return TRUE
; /* skip test */ 
 483     u_unescape(search
->text
, temp
, 128); 
 486     u_unescape(search
->pattern
, temp
, 128); 
 487     UnicodeString  pattern
; 
 490 #if !UCONFIG_NO_BREAK_ITERATION 
 491     if (breaker 
!= NULL
) { 
 492         breaker
->setText(text
); 
 495     collator
->setStrength(getECollationStrength(search
->strength
)); 
 496     strsrch 
= new StringSearch(pattern
, text
, (RuleBasedCollator 
*)collator
,  
 498     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, canonical
, status
); 
 499     strsrch
->setAttribute(USEARCH_OVERLAP
, overlap
, status
); 
 501     if (U_FAILURE(status
)) { 
 502         errln("Error opening string search %s", u_errorName(status
)); 
 506     if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 507         collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 511     collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 516 void StringSearchTest::TestOpenClose() 
 518     UErrorCode               status    
= U_ZERO_ERROR
; 
 519     StringSearch            
*result
; 
 520     BreakIterator           
*breakiter 
= m_en_wordbreaker_
; 
 521     UnicodeString            pattern
; 
 523     UnicodeString            
temp("a"); 
 524     StringCharacterIterator  
chariter(text
); 
 526     /* testing null arguments */ 
 527     result 
= new StringSearch(pattern
, text
, NULL
, NULL
, status
); 
 528     if (U_SUCCESS(status
)) { 
 529         errln("Error: NULL arguments should produce an error"); 
 533     chariter
.setText(text
); 
 534     status 
= U_ZERO_ERROR
; 
 535     result 
= new StringSearch(pattern
, chariter
, NULL
, NULL
, status
); 
 536     if (U_SUCCESS(status
)) { 
 537         errln("Error: NULL arguments should produce an error"); 
 542     status 
= U_ZERO_ERROR
; 
 543     result 
= new StringSearch(pattern
, text
, NULL
, NULL
, status
); 
 544     if (U_SUCCESS(status
)) { 
 545         errln("Error: Empty pattern should produce an error"); 
 549     chariter
.setText(text
); 
 550     status 
= U_ZERO_ERROR
; 
 551     result 
= new StringSearch(pattern
, chariter
, NULL
, NULL
, status
); 
 552     if (U_SUCCESS(status
)) { 
 553         errln("Error: Empty pattern should produce an error"); 
 558     pattern
.append(temp
); 
 559     status 
= U_ZERO_ERROR
; 
 560     result 
= new StringSearch(pattern
, text
, NULL
, NULL
, status
); 
 561     if (U_SUCCESS(status
)) { 
 562         errln("Error: Empty text should produce an error"); 
 566     chariter
.setText(text
); 
 567     status 
= U_ZERO_ERROR
; 
 568     result 
= new StringSearch(pattern
, chariter
, NULL
, NULL
, status
); 
 569     if (U_SUCCESS(status
)) { 
 570         errln("Error: Empty text should produce an error"); 
 575     status 
= U_ZERO_ERROR
; 
 576     result 
= new StringSearch(pattern
, text
, NULL
, NULL
, status
); 
 577     if (U_SUCCESS(status
)) { 
 578         errln("Error: NULL arguments should produce an error"); 
 582     chariter
.setText(text
); 
 583     status 
= U_ZERO_ERROR
; 
 584     result 
= new StringSearch(pattern
, chariter
, NULL
, NULL
, status
); 
 585     if (U_SUCCESS(status
)) { 
 586         errln("Error: NULL arguments should produce an error"); 
 590     status 
= U_ZERO_ERROR
; 
 591     result 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
, status
); 
 592     if (U_FAILURE(status
)) { 
 593         errln("Error: NULL break iterator is valid for opening search"); 
 597     status 
= U_ZERO_ERROR
; 
 598     result 
= new StringSearch(pattern
, chariter
, m_en_us_
, NULL
, status
); 
 599     if (U_FAILURE(status
)) { 
 600         errln("Error: NULL break iterator is valid for opening search"); 
 604     status 
= U_ZERO_ERROR
; 
 605     result 
= new StringSearch(pattern
, text
, Locale::getEnglish(), NULL
, status
); 
 606     if (U_FAILURE(status
) || result 
== NULL
) { 
 607         errln("Error: NULL break iterator is valid for opening search"); 
 611     status 
= U_ZERO_ERROR
; 
 612     result 
= new StringSearch(pattern
, chariter
, Locale::getEnglish(), NULL
, status
); 
 613     if (U_FAILURE(status
)) { 
 614         errln("Error: NULL break iterator is valid for opening search"); 
 618     status 
= U_ZERO_ERROR
; 
 619     result 
= new StringSearch(pattern
, text
, m_en_us_
, breakiter
, status
); 
 620     if (U_FAILURE(status
)) { 
 621         errln("Error: Break iterator is valid for opening search"); 
 625     status 
= U_ZERO_ERROR
; 
 626     result 
= new StringSearch(pattern
, chariter
, m_en_us_
, NULL
, status
); 
 627     if (U_FAILURE(status
)) { 
 628         errln("Error: Break iterator is valid for opening search"); 
 633 void StringSearchTest::TestInitialization() 
 635     UErrorCode     status 
= U_ZERO_ERROR
; 
 636     UnicodeString  pattern
; 
 638     UnicodeString  
temp("a"); 
 639     StringSearch  
*result
; 
 642     /* simple test on the pattern ce construction */ 
 643     pattern
.append(temp
); 
 644     pattern
.append(temp
); 
 648     result 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
, status
); 
 649     if (U_FAILURE(status
)) { 
 650         errln("Error opening search %s", u_errorName(status
)); 
 652     StringSearch 
*copy 
= new StringSearch(*result
); 
 653     if (*(copy
->getCollator()) != *(result
->getCollator()) || 
 654         copy
->getBreakIterator() != result
->getBreakIterator() || 
 655         copy
->getMatchedLength() != result
->getMatchedLength() || 
 656         copy
->getMatchedStart() != result
->getMatchedStart() || 
 657         copy
->getOffset() != result
->getOffset() || 
 658         copy
->getPattern() != result
->getPattern() || 
 659         copy
->getText() != result
->getText() || 
 660         *(copy
) != *(result
)) 
 662         errln("Error copying StringSearch"); 
 666     copy 
= (StringSearch 
*)result
->safeClone(); 
 667     if (*(copy
->getCollator()) != *(result
->getCollator()) || 
 668         copy
->getBreakIterator() != result
->getBreakIterator() || 
 669         copy
->getMatchedLength() != result
->getMatchedLength() || 
 670         copy
->getMatchedStart() != result
->getMatchedStart() || 
 671         copy
->getOffset() != result
->getOffset() || 
 672         copy
->getPattern() != result
->getPattern() || 
 673         copy
->getText() != result
->getText() || 
 674         *(copy
) != *(result
)) { 
 675         errln("Error copying StringSearch"); 
 679     /* testing if an extremely large pattern will fail the initialization */ 
 680     for (count 
= 0; count 
< 512; count 
++) { 
 681         pattern
.append(temp
); 
 683     result 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
, status
); 
 684     if (*result 
!= *result
) { 
 685         errln("Error: string search object expected to match itself"); 
 687     if (*result 
== *copy
) { 
 688         errln("Error: string search objects are not expected to match"); 
 691     if (*(copy
->getCollator()) != *(result
->getCollator()) || 
 692         copy
->getBreakIterator() != result
->getBreakIterator() || 
 693         copy
->getMatchedLength() != result
->getMatchedLength() || 
 694         copy
->getMatchedStart() != result
->getMatchedStart() || 
 695         copy
->getOffset() != result
->getOffset() || 
 696         copy
->getPattern() != result
->getPattern() || 
 697         copy
->getText() != result
->getText() || 
 698         *(copy
) != *(result
)) { 
 699         errln("Error copying StringSearch"); 
 701     if (U_FAILURE(status
)) { 
 702         errln("Error opening search %s", u_errorName(status
)); 
 708 void StringSearchTest::TestBasic() 
 711     while (BASIC
[count
].text 
!= NULL
) { 
 712         //printf("count %d", count); 
 713         if (!assertEqual(&BASIC
[count
])) { 
 714             infoln("Error at test number %d", count
); 
 720 void StringSearchTest::TestNormExact() 
 723     UErrorCode status 
= U_ZERO_ERROR
; 
 724     m_en_us_
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_ON
, status
); 
 725     if (U_FAILURE(status
)) { 
 726         errln("Error setting collation normalization %s",  
 727               u_errorName(status
)); 
 729     while (BASIC
[count
].text 
!= NULL
) { 
 730         if (!assertEqual(&BASIC
[count
])) { 
 731             infoln("Error at test number %d", count
); 
 736     while (NORMEXACT
[count
].text 
!= NULL
) { 
 737         if (!assertEqual(&NORMEXACT
[count
])) { 
 738             infoln("Error at test number %d", count
); 
 742     m_en_us_
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_OFF
, status
); 
 744     while (NONNORMEXACT
[count
].text 
!= NULL
) { 
 745         if (!assertEqual(&NONNORMEXACT
[count
])) { 
 746             infoln("Error at test number %d", count
); 
 752 void StringSearchTest::TestStrength() 
 755     while (STRENGTH
[count
].text 
!= NULL
) { 
 756         if (!assertEqual(&STRENGTH
[count
])) { 
 757             infoln("Error at test number %d", count
); 
 763 #if !UCONFIG_NO_BREAK_ITERATION 
 765 void StringSearchTest::TestBreakIterator() 
 768     u_unescape(BREAKITERATOREXACT
[0].text
, temp
, 128); 
 770     text
.setTo(temp
, u_strlen(temp
)); 
 771     u_unescape(BREAKITERATOREXACT
[0].pattern
, temp
, 128); 
 772     UnicodeString pattern
; 
 773     pattern
.setTo(temp
, u_strlen(temp
)); 
 775     UErrorCode status 
= U_ZERO_ERROR
; 
 776     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
 778     if (U_FAILURE(status
)) { 
 779         errln("Error opening string search %s", u_errorName(status
)); 
 782     strsrch
->setBreakIterator(NULL
, status
); 
 783     if (U_FAILURE(status
) || strsrch
->getBreakIterator() != NULL
) { 
 784         errln("Error usearch_getBreakIterator returned wrong object"); 
 787     strsrch
->setBreakIterator(m_en_characterbreaker_
, status
); 
 788     if (U_FAILURE(status
) ||  
 789         strsrch
->getBreakIterator() != m_en_characterbreaker_
) { 
 790         errln("Error usearch_getBreakIterator returned wrong object"); 
 793     strsrch
->setBreakIterator(m_en_wordbreaker_
, status
); 
 794     if (U_FAILURE(status
) ||  
 795         strsrch
->getBreakIterator() != m_en_wordbreaker_
) { 
 796         errln("Error usearch_getBreakIterator returned wrong object"); 
 803         // special purposes for tests numbers 0-3 
 804         const SearchData        
*search   
= &(BREAKITERATOREXACT
[count
]);      
 805               RuleBasedCollator 
*collator 
= getCollator(search
->collator
); 
 806               BreakIterator     
*breaker  
= getBreakIterator(search
->breaker
); 
 807               StringSearch      
*strsrch
;  
 809         u_unescape(search
->text
, temp
, 128); 
 810         text
.setTo(temp
, u_strlen(temp
)); 
 811         u_unescape(search
->pattern
, temp
, 128); 
 812         pattern
.setTo(temp
, u_strlen(temp
)); 
 813         if (breaker 
!= NULL
) { 
 814             breaker
->setText(text
); 
 816         collator
->setStrength(getECollationStrength(search
->strength
)); 
 818         strsrch 
= new StringSearch(pattern
, text
, collator
, breaker
, status
); 
 819         if (U_FAILURE(status
) ||  
 820             strsrch
->getBreakIterator() != breaker
) { 
 821             errln("Error setting break iterator"); 
 822             if (strsrch 
!= NULL
) { 
 826         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 827             collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
 830         search   
= &(BREAKITERATOREXACT
[count 
+ 1]); 
 831         breaker  
= getBreakIterator(search
->breaker
); 
 832         if (breaker 
!= NULL
) { 
 833             breaker
->setText(text
); 
 835         strsrch
->setBreakIterator(breaker
, status
); 
 836         if (U_FAILURE(status
) ||  
 837             strsrch
->getBreakIterator() != breaker
) { 
 838             errln("Error setting break iterator"); 
 842         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 843              infoln("Error at test number %d", count
); 
 849     while (BREAKITERATOREXACT
[count
].text 
!= NULL
) { 
 850          if (!assertEqual(&BREAKITERATOREXACT
[count
])) { 
 851              infoln("Error at test number %d", count
); 
 859 void StringSearchTest::TestVariable() 
 862     UErrorCode status 
= U_ZERO_ERROR
; 
 863     m_en_us_
->setAttribute(UCOL_ALTERNATE_HANDLING
, UCOL_SHIFTED
, status
); 
 864     if (U_FAILURE(status
)) { 
 865         errln("Error setting collation alternate attribute %s",  
 866               u_errorName(status
)); 
 868     while (VARIABLE
[count
].text 
!= NULL
) { 
 869         logln("variable %d", count
); 
 870         if (!assertEqual(&VARIABLE
[count
])) { 
 871             infoln("Error at test number %d", count
); 
 875     m_en_us_
->setAttribute(UCOL_ALTERNATE_HANDLING
, UCOL_NON_IGNORABLE
,  
 879 void StringSearchTest::TestOverlap() 
 882     while (OVERLAP
[count
].text 
!= NULL
) { 
 883         if (!assertEqualWithAttribute(&OVERLAP
[count
], USEARCH_OFF
,  
 885             errln("Error at overlap test number %d", count
); 
 890     while (NONOVERLAP
[count
].text 
!= NULL
) { 
 891         if (!assertEqual(&NONOVERLAP
[count
])) { 
 892             errln("Error at non overlap test number %d", count
); 
 899         const SearchData 
*search 
= &(OVERLAP
[count
]);      
 901         u_unescape(search
->text
, temp
, 128); 
 903         text
.setTo(temp
, u_strlen(temp
)); 
 904         u_unescape(search
->pattern
, temp
, 128); 
 905         UnicodeString pattern
; 
 906         pattern
.setTo(temp
, u_strlen(temp
)); 
 908         RuleBasedCollator 
*collator 
= getCollator(search
->collator
); 
 909         UErrorCode         status   
= U_ZERO_ERROR
; 
 910         StringSearch      
*strsrch  
= new StringSearch(pattern
, text
,  
 914         strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_ON
, status
); 
 915         if (U_FAILURE(status
) || 
 916             strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_ON
) { 
 917             errln("Error setting overlap option"); 
 919         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 924         search 
= &(NONOVERLAP
[count
]); 
 925         strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_OFF
, status
); 
 926         if (U_FAILURE(status
) || 
 927             strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_OFF
) { 
 928             errln("Error setting overlap option"); 
 931         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
 933             errln("Error at test number %d", count
); 
 941 void StringSearchTest::TestCollator() 
 943     // test collator that thinks "o" and "p" are the same thing 
 945     u_unescape(COLLATOR
[0].text
, temp
, 128); 
 947     text
.setTo(temp
, u_strlen(temp
)); 
 948     u_unescape(COLLATOR
[0].pattern
, temp
, 128); 
 949     UnicodeString pattern
; 
 950     pattern
.setTo(temp
, u_strlen(temp
)); 
 952     UErrorCode    status 
= U_ZERO_ERROR
; 
 953     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
 955     if (U_FAILURE(status
)) { 
 956         errln("Error opening string search %s", u_errorName(status
)); 
 960     if (!assertEqualWithStringSearch(strsrch
, &COLLATOR
[0])) { 
 965     u_unescape(TESTCOLLATORRULE
, temp
, 128); 
 967     rules
.setTo(temp
, u_strlen(temp
)); 
 968     RuleBasedCollator 
*tailored 
= new RuleBasedCollator(rules
, status
); 
 969     tailored
->setStrength(getECollationStrength(COLLATOR
[1].strength
));  
 971     if (U_FAILURE(status
)) { 
 972         errln("Error opening rule based collator %s", u_errorName(status
)); 
 974         if (tailored 
!= NULL
) { 
 980     strsrch
->setCollator(tailored
, status
); 
 981     if (U_FAILURE(status
) || (*strsrch
->getCollator()) != (*tailored
)) { 
 982         errln("Error setting rule based collator"); 
 984         if (tailored 
!= NULL
) { 
 989     if (!assertEqualWithStringSearch(strsrch
, &COLLATOR
[1])) { 
 991         if (tailored 
!= NULL
) { 
 997     strsrch
->setCollator(m_en_us_
, status
); 
 999     if (U_FAILURE(status
) || (*strsrch
->getCollator()) != (*m_en_us_
)) { 
1000         errln("Error setting rule based collator"); 
1002         if (tailored 
!= NULL
) { 
1006     if (!assertEqualWithStringSearch(strsrch
, &COLLATOR
[0])) { 
1007        errln("Error searching collator test"); 
1010     if (tailored 
!= NULL
) { 
1015 void StringSearchTest::TestPattern() 
1020     u_unescape(PATTERN
[0].text
, temp
, 512); 
1022     text
.setTo(temp
, u_strlen(temp
)); 
1023     u_unescape(PATTERN
[0].pattern
, temp
, 512); 
1024     UnicodeString pattern
; 
1025     pattern
.setTo(temp
, u_strlen(temp
)); 
1027     m_en_us_
->setStrength(getECollationStrength(PATTERN
[0].strength
)); 
1028     UErrorCode    status 
= U_ZERO_ERROR
; 
1029     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1032     if (U_FAILURE(status
)) { 
1033         errln("Error opening string search %s", u_errorName(status
)); 
1034         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1035         if (strsrch 
!= NULL
) { 
1040     if (strsrch
->getPattern() != pattern
) { 
1041         errln("Error setting pattern"); 
1043     if (!assertEqualWithStringSearch(strsrch
, &PATTERN
[0])) { 
1044         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1045         if (strsrch 
!= NULL
) { 
1051     u_unescape(PATTERN
[1].pattern
, temp
, 512); 
1052     pattern
.setTo(temp
, u_strlen(temp
)); 
1053     strsrch
->setPattern(pattern
, status
); 
1054     if (pattern 
!= strsrch
->getPattern()) { 
1055         errln("Error setting pattern"); 
1056         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1057         if (strsrch 
!= NULL
) { 
1063     if (U_FAILURE(status
)) { 
1064         errln("Error setting pattern %s", u_errorName(status
)); 
1066     if (!assertEqualWithStringSearch(strsrch
, &PATTERN
[1])) { 
1067         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1068         if (strsrch 
!= NULL
) { 
1074     u_unescape(PATTERN
[0].pattern
, temp
, 512); 
1075     pattern
.setTo(temp
, u_strlen(temp
)); 
1076     strsrch
->setPattern(pattern
, status
); 
1077     if (pattern 
!= strsrch
->getPattern()) { 
1078         errln("Error setting pattern"); 
1079         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1080         if (strsrch 
!= NULL
) { 
1086     if (U_FAILURE(status
)) { 
1087         errln("Error setting pattern %s", u_errorName(status
)); 
1089     if (!assertEqualWithStringSearch(strsrch
, &PATTERN
[0])) { 
1090         m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1091         if (strsrch 
!= NULL
) { 
1096     /* enormous pattern size to see if this crashes */ 
1097     for (templength 
= 0; templength 
!= 512; templength 
++) { 
1098         temp
[templength
] = 0x61; 
1101     pattern
.setTo(temp
, 511); 
1102     strsrch
->setPattern(pattern
, status
); 
1103     if (U_FAILURE(status
)) { 
1104         errln("Error setting pattern with size 512, %s", u_errorName(status
)); 
1106     m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1107     if (strsrch 
!= NULL
) { 
1112 void StringSearchTest::TestText() 
1115     u_unescape(TEXT
[0].text
, temp
, 128); 
1117     text
.setTo(temp
, u_strlen(temp
)); 
1118     u_unescape(TEXT
[0].pattern
, temp
, 128); 
1119     UnicodeString pattern
; 
1120     pattern
.setTo(temp
, u_strlen(temp
)); 
1122     UErrorCode status 
= U_ZERO_ERROR
; 
1123     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1125     if (U_FAILURE(status
)) { 
1126         errln("Error opening string search %s", u_errorName(status
)); 
1129     if (text 
!= strsrch
->getText()) { 
1130         errln("Error setting text"); 
1132     if (!assertEqualWithStringSearch(strsrch
, &TEXT
[0])) { 
1137     u_unescape(TEXT
[1].text
, temp
, 128); 
1138     text
.setTo(temp
, u_strlen(temp
)); 
1139     strsrch
->setText(text
, status
); 
1140     if (text 
!= strsrch
->getText()) { 
1141         errln("Error setting text"); 
1145     if (U_FAILURE(status
)) { 
1146         errln("Error setting text %s", u_errorName(status
)); 
1148     if (!assertEqualWithStringSearch(strsrch
, &TEXT
[1])) { 
1153     u_unescape(TEXT
[0].text
, temp
, 128); 
1154     text
.setTo(temp
, u_strlen(temp
)); 
1155     StringCharacterIterator 
chariter(text
); 
1156     strsrch
->setText(chariter
, status
); 
1157     if (text 
!= strsrch
->getText()) { 
1158         errln("Error setting text"); 
1162     if (U_FAILURE(status
)) { 
1163         errln("Error setting pattern %s", u_errorName(status
)); 
1165     if (!assertEqualWithStringSearch(strsrch
, &TEXT
[0])) { 
1166         errln("Error searching within set text"); 
1171 void StringSearchTest::TestCompositeBoundaries() 
1174     while (COMPOSITEBOUNDARIES
[count
].text 
!= NULL
) {  
1175         logln("composite %d", count
); 
1176         if (!assertEqual(&COMPOSITEBOUNDARIES
[count
])) { 
1177             errln("Error at test number %d", count
); 
1183 void StringSearchTest::TestGetSetOffset() 
1185     UErrorCode     status  
= U_ZERO_ERROR
; 
1186     UnicodeString  
pattern("1234567890123456"); 
1187     UnicodeString  
text("12345678901234567890123456789012"); 
1188     StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
,  
1190     /* testing out of bounds error */ 
1191     strsrch
->setOffset(-1, status
); 
1192     if (U_SUCCESS(status
)) { 
1193         errln("Error expecting set offset error"); 
1195     strsrch
->setOffset(128, status
); 
1196     if (U_SUCCESS(status
)) { 
1197         errln("Error expecting set offset error"); 
1200     while (BASIC
[index
].text 
!= NULL
) { 
1201         UErrorCode  status      
= U_ZERO_ERROR
; 
1202         SearchData  search      
= BASIC
[index 
++]; 
1205         u_unescape(search
.text
, temp
, 128); 
1206         text
.setTo(temp
, u_strlen(temp
)); 
1207         u_unescape(search
.pattern
, temp
, 128); 
1208         pattern
.setTo(temp
, u_strlen(temp
)); 
1209         strsrch
->setText(text
, status
); 
1210         strsrch
->setPattern(pattern
, status
); 
1211         strsrch
->getCollator()->setStrength(getECollationStrength( 
1216         int32_t matchindex  
= search
.offset
[count
]; 
1217         while (U_SUCCESS(status
) && matchindex 
>= 0) { 
1218             int32_t matchlength 
= search
.size
[count
]; 
1219             strsrch
->next(status
); 
1220             if (matchindex 
!= strsrch
->getMatchedStart() ||  
1221                 matchlength 
!= strsrch
->getMatchedLength()) { 
1222                 char *str 
= toCharString(strsrch
->getText()); 
1223                 errln("Text: %s", str
); 
1224                 str 
= toCharString(strsrch
->getPattern()); 
1225                 errln("Pattern: %s", str
); 
1226                 errln("Error match found at %d %d",  
1227                         strsrch
->getMatchedStart(),  
1228                         strsrch
->getMatchedLength()); 
1231             matchindex 
= search
.offset
[count 
+ 1] == -1 ? -1 :  
1232                          search
.offset
[count 
+ 2]; 
1233             if (search
.offset
[count 
+ 1] != -1) { 
1234                 strsrch
->setOffset(search
.offset
[count 
+ 1] + 1, status
); 
1235                 if (strsrch
->getOffset() != search
.offset
[count 
+ 1] + 1) { 
1236                     errln("Error setting offset\n"); 
1243         strsrch
->next(status
); 
1244         if (strsrch
->getMatchedStart() != USEARCH_DONE
) { 
1245             char *str 
= toCharString(strsrch
->getText()); 
1246             errln("Text: %s", str
); 
1247             str 
= toCharString(strsrch
->getPattern()); 
1248             errln("Pattern: %s", str
); 
1249             errln("Error match found at %d %d",  
1250                         strsrch
->getMatchedStart(),  
1251                         strsrch
->getMatchedLength()); 
1255     strsrch
->getCollator()->setStrength(getECollationStrength( 
1260 void StringSearchTest::TestGetSetAttribute() 
1262     UErrorCode     status    
= U_ZERO_ERROR
; 
1263     UnicodeString  
pattern("pattern"); 
1264     UnicodeString  
text("text"); 
1265     StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1267     if (U_FAILURE(status
)) { 
1268         errln("Error opening search %s", u_errorName(status
)); 
1272     strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_DEFAULT
, status
); 
1273     if (U_FAILURE(status
) ||  
1274         strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_OFF
) { 
1275         errln("Error setting overlap to the default"); 
1277     strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_ON
, status
); 
1278     if (U_FAILURE(status
) ||  
1279         strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_ON
) { 
1280         errln("Error setting overlap true"); 
1282     strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_OFF
, status
); 
1283     if (U_FAILURE(status
) ||  
1284         strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_OFF
) { 
1285         errln("Error setting overlap false"); 
1287     strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_ATTRIBUTE_VALUE_COUNT
,  
1289     if (U_SUCCESS(status
)) { 
1290         errln("Error setting overlap to illegal value"); 
1292     status 
= U_ZERO_ERROR
; 
1293     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_DEFAULT
, status
); 
1294     if (U_FAILURE(status
) ||  
1295         strsrch
->getAttribute(USEARCH_CANONICAL_MATCH
) != USEARCH_OFF
) { 
1296         errln("Error setting canonical match to the default"); 
1298     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1299     if (U_FAILURE(status
) ||  
1300         strsrch
->getAttribute(USEARCH_CANONICAL_MATCH
) != USEARCH_ON
) { 
1301         errln("Error setting canonical match true"); 
1303     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_OFF
, status
); 
1304     if (U_FAILURE(status
) ||  
1305         strsrch
->getAttribute(USEARCH_CANONICAL_MATCH
) != USEARCH_OFF
) { 
1306         errln("Error setting canonical match false"); 
1308     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
,  
1309                           USEARCH_ATTRIBUTE_VALUE_COUNT
, status
); 
1310     if (U_SUCCESS(status
)) { 
1311         errln("Error setting canonical match to illegal value"); 
1313     status 
= U_ZERO_ERROR
; 
1314     strsrch
->setAttribute(USEARCH_ATTRIBUTE_COUNT
, USEARCH_DEFAULT
, status
); 
1315     if (U_SUCCESS(status
)) { 
1316         errln("Error setting illegal attribute success"); 
1322 void StringSearchTest::TestGetMatch() 
1325     SearchData search 
= MATCH
[0]; 
1326     u_unescape(search
.text
, temp
, 128); 
1328     text
.setTo(temp
, u_strlen(temp
)); 
1329     u_unescape(search
.pattern
, temp
, 128); 
1330     UnicodeString pattern
; 
1331     pattern
.setTo(temp
, u_strlen(temp
)); 
1333     UErrorCode    status  
= U_ZERO_ERROR
; 
1334     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1336     if (U_FAILURE(status
)) { 
1337         errln("Error opening string search %s", u_errorName(status
)); 
1338         if (strsrch 
!= NULL
) { 
1345     int32_t   matchindex 
= search
.offset
[count
]; 
1346     UnicodeString matchtext
; 
1347     while (U_SUCCESS(status
) && matchindex 
>= 0) { 
1348         int32_t matchlength 
= search
.size
[count
]; 
1349         strsrch
->next(status
); 
1350         if (matchindex 
!= strsrch
->getMatchedStart() ||  
1351             matchlength 
!= strsrch
->getMatchedLength()) { 
1352             char *str 
= toCharString(strsrch
->getText()); 
1353             errln("Text: %s", str
); 
1354             str 
= toCharString(strsrch
->getPattern()); 
1355             errln("Pattern: %s", str
); 
1356             errln("Error match found at %d %d", strsrch
->getMatchedStart(),  
1357                   strsrch
->getMatchedLength()); 
1362         status 
= U_ZERO_ERROR
; 
1363         strsrch
->getMatchedText(matchtext
); 
1364         if (matchtext
.length() != matchlength 
|| U_FAILURE(status
)){ 
1365             errln("Error getting match text"); 
1367         matchindex 
= search
.offset
[count
]; 
1369     status 
= U_ZERO_ERROR
; 
1370     strsrch
->next(status
); 
1371     if (strsrch
->getMatchedStart()  != USEARCH_DONE 
||  
1372         strsrch
->getMatchedLength() != 0) { 
1373         errln("Error end of match not found"); 
1375     status 
= U_ZERO_ERROR
; 
1376     strsrch
->getMatchedText(matchtext
); 
1377     if (matchtext
.length() != 0) { 
1378         errln("Error getting null matches"); 
1383 void StringSearchTest::TestSetMatch() 
1386     while (MATCH
[count
].text 
!= NULL
) { 
1387         SearchData     search 
= MATCH
[count
]; 
1389         UErrorCode status 
= U_ZERO_ERROR
; 
1390         u_unescape(search
.text
, temp
, 128); 
1392         text
.setTo(temp
, u_strlen(temp
)); 
1393         u_unescape(search
.pattern
, temp
, 128); 
1394         UnicodeString pattern
; 
1395         pattern
.setTo(temp
, u_strlen(temp
)); 
1397         StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
,  
1399         if (U_FAILURE(status
)) { 
1400             errln("Error opening string search %s", u_errorName(status
)); 
1401             if (strsrch 
!= NULL
) { 
1408         while (search
.offset
[size
] != -1) { 
1412         if (strsrch
->first(status
) != search
.offset
[0] || U_FAILURE(status
)) { 
1413             errln("Error getting first match"); 
1415         if (strsrch
->last(status
) != search
.offset
[size 
-1] || 
1416             U_FAILURE(status
)) { 
1417             errln("Error getting last match"); 
1421         while (index 
< size
) { 
1422             if (index 
+ 2 < size
) { 
1423                 if (strsrch
->following(search
.offset
[index 
+ 2] - 1, status
)  
1424                          != search
.offset
[index 
+ 2] || U_FAILURE(status
)) { 
1425                     errln("Error getting following match at index %d",  
1426                           search
.offset
[index 
+ 2] - 1); 
1429             if (index 
+ 1 < size
) { 
1430                 if (strsrch
->preceding(search
.offset
[index 
+ 1] +  
1431                                                 search
.size
[index 
+ 1] + 1,  
1432                                        status
) != search
.offset
[index 
+ 1] || 
1433                     U_FAILURE(status
)) { 
1434                     errln("Error getting preceeding match at index %d",  
1435                           search
.offset
[index 
+ 1] + 1); 
1440         status 
= U_ZERO_ERROR
; 
1441         if (strsrch
->following(text
.length(), status
) != USEARCH_DONE
) { 
1442             errln("Error expecting out of bounds match"); 
1444         if (strsrch
->preceding(0, status
) != USEARCH_DONE
) { 
1445             errln("Error expecting out of bounds match"); 
1452 void StringSearchTest::TestReset() 
1454     UErrorCode     status  
= U_ZERO_ERROR
; 
1455     UnicodeString  
text("fish fish"); 
1456     UnicodeString  
pattern("s"); 
1457     StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1459     if (U_FAILURE(status
)) { 
1460         errln("Error opening string search %s", u_errorName(status
)); 
1461         if (strsrch 
!= NULL
) { 
1466     strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_ON
, status
); 
1467     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1468     strsrch
->setOffset(9, status
); 
1469     if (U_FAILURE(status
)) { 
1470         errln("Error setting attributes and offsets"); 
1474         if (strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_OFF 
|| 
1475             strsrch
->getAttribute(USEARCH_CANONICAL_MATCH
) != USEARCH_OFF 
|| 
1476             strsrch
->getOffset() != 0 || strsrch
->getMatchedLength() != 0 || 
1477             strsrch
->getMatchedStart() != USEARCH_DONE
) { 
1478             errln("Error resetting string search"); 
1480         strsrch
->previous(status
); 
1481         if (strsrch
->getMatchedStart() != 7 || 
1482             strsrch
->getMatchedLength() != 1) { 
1483             errln("Error resetting string search\n"); 
1489 void StringSearchTest::TestSupplementary() 
1492     while (SUPPLEMENTARY
[count
].text 
!= NULL
) { 
1493         if (!assertEqual(&SUPPLEMENTARY
[count
])) { 
1494             errln("Error at test number %d", count
); 
1500 void StringSearchTest::TestContraction() 
1503     UErrorCode status 
= U_ZERO_ERROR
; 
1505     u_unescape(CONTRACTIONRULE
, temp
, 128); 
1506     UnicodeString rules
; 
1507     rules
.setTo(temp
, u_strlen(temp
)); 
1508     RuleBasedCollator 
*collator 
= new RuleBasedCollator(rules
,  
1509         getECollationStrength(UCOL_TERTIARY
), UCOL_ON
, status
);  
1510     if (U_FAILURE(status
)) { 
1511         errln("Error opening collator %s", u_errorName(status
)); 
1513     UnicodeString 
text("text"); 
1514     UnicodeString 
pattern("pattern"); 
1515     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, collator
, NULL
,  
1517     if (U_FAILURE(status
)) { 
1518         errln("Error opening string search %s", u_errorName(status
)); 
1522     while (CONTRACTION
[count
].text 
!= NULL
) { 
1523         u_unescape(CONTRACTION
[count
].text
, temp
, 128); 
1524         text
.setTo(temp
, u_strlen(temp
)); 
1525         u_unescape(CONTRACTION
[count
].pattern
, temp
, 128); 
1526         pattern
.setTo(temp
, u_strlen(temp
)); 
1527         strsrch
->setText(text
, status
); 
1528         strsrch
->setPattern(pattern
, status
); 
1529         if (!assertEqualWithStringSearch(strsrch
, &CONTRACTION
[count
])) { 
1530             errln("Error at test number %d", count
); 
1538 void StringSearchTest::TestIgnorable() 
1541     u_unescape(IGNORABLERULE
, temp
, 128); 
1542     UnicodeString rules
; 
1543     rules
.setTo(temp
, u_strlen(temp
)); 
1544     UErrorCode status 
= U_ZERO_ERROR
; 
1546     RuleBasedCollator 
*collator 
= new RuleBasedCollator(rules
,   
1547                             getECollationStrength(IGNORABLE
[count
].strength
),  
1549     if (U_FAILURE(status
)) { 
1550         errln("Error opening collator %s", u_errorName(status
)); 
1553     UnicodeString 
pattern("pattern"); 
1554     UnicodeString 
text("text"); 
1555     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, collator
, NULL
,  
1557     if (U_FAILURE(status
)) { 
1558         errln("Error opening string search %s", u_errorName(status
)); 
1563     while (IGNORABLE
[count
].text 
!= NULL
) { 
1564         u_unescape(IGNORABLE
[count
].text
, temp
, 128); 
1565         text
.setTo(temp
, u_strlen(temp
)); 
1566         u_unescape(IGNORABLE
[count
].pattern
, temp
, 128); 
1567         pattern
.setTo(temp
, u_strlen(temp
)); 
1568         strsrch
->setText(text
, status
); 
1569         strsrch
->setPattern(pattern
, status
); 
1570         if (!assertEqualWithStringSearch(strsrch
, &IGNORABLE
[count
])) { 
1571             errln("Error at test number %d", count
); 
1579 void StringSearchTest::TestDiacriticMatch() 
1582     UErrorCode status 
= U_ZERO_ERROR
; 
1584     RuleBasedCollator
* coll 
= NULL
; 
1585     StringSearch 
*strsrch 
= NULL
; 
1587     UnicodeString 
pattern("pattern"); 
1588     UnicodeString 
text("text"); 
1590     const SearchData 
*search
;  
1592     search 
= &(DIACRITICMATCH
[count
]); 
1593     while (search
->text 
!= NULL
) { 
1594                 coll 
= getCollator(search
->collator
); 
1595         coll
->setStrength(getECollationStrength(search
->strength
)); 
1596         strsrch 
= new StringSearch(pattern
, text
, coll
, getBreakIterator(search
->breaker
), status
); 
1597         if (U_FAILURE(status
)) { 
1598                 errln("Error opening string search %s", u_errorName(status
)); 
1601         u_unescape(search
->text
, temp
, 128); 
1602         text
.setTo(temp
, u_strlen(temp
)); 
1603         u_unescape(search
->pattern
, temp
, 128); 
1604         pattern
.setTo(temp
, u_strlen(temp
)); 
1605         strsrch
->setText(text
, status
); 
1606         strsrch
->setPattern(pattern
, status
); 
1607         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
1608             errln("Error at test number %d", count
); 
1610         search 
= &(DIACRITICMATCH
[++count
]); 
1616 void StringSearchTest::TestCanonical() 
1619     while (BASICCANONICAL
[count
].text 
!= NULL
) { 
1620         if (!assertCanonicalEqual(&BASICCANONICAL
[count
])) { 
1621             errln("Error at test number %d", count
); 
1627 void StringSearchTest::TestNormCanonical() 
1629     UErrorCode status 
= U_ZERO_ERROR
; 
1630     m_en_us_
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_ON
, status
); 
1632     while (NORMCANONICAL
[count
].text 
!= NULL
) { 
1633         if (!assertCanonicalEqual(&NORMCANONICAL
[count
])) { 
1634             errln("Error at test number %d", count
); 
1638     m_en_us_
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_OFF
, status
); 
1641 void StringSearchTest::TestStrengthCanonical() 
1644     while (STRENGTHCANONICAL
[count
].text 
!= NULL
) { 
1645         if (!assertCanonicalEqual(&STRENGTHCANONICAL
[count
])) { 
1646             errln("Error at test number %d", count
); 
1652 #if !UCONFIG_NO_BREAK_ITERATION 
1654 void StringSearchTest::TestBreakIteratorCanonical() 
1656     UErrorCode status 
= U_ZERO_ERROR
; 
1660         // special purposes for tests numbers 0-3 
1662         const SearchData     
*search   
= &(BREAKITERATORCANONICAL
[count
]);      
1664         u_unescape(search
->text
, temp
, 128); 
1666         text
.setTo(temp
, u_strlen(temp
)); 
1667         u_unescape(search
->pattern
, temp
, 128); 
1668         UnicodeString pattern
; 
1669         pattern
.setTo(temp
, u_strlen(temp
)); 
1670         RuleBasedCollator 
*collator 
= getCollator(search
->collator
); 
1671         collator
->setStrength(getECollationStrength(search
->strength
)); 
1673         BreakIterator 
*breaker 
= getBreakIterator(search
->breaker
); 
1674         StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, collator
,  
1676         if (U_FAILURE(status
)) { 
1677             errln("Error creating string search data"); 
1680         strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1681         if (U_FAILURE(status
) ||  
1682             strsrch
->getBreakIterator() != breaker
) { 
1683             errln("Error setting break iterator"); 
1687         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
1688             collator
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1692         search  
= &(BREAKITERATOREXACT
[count 
+ 1]); 
1693         breaker 
= getBreakIterator(search
->breaker
); 
1694         if (breaker 
== NULL
) { 
1695             errln("Error creating BreakIterator"); 
1698         breaker
->setText(strsrch
->getText()); 
1699         strsrch
->setBreakIterator(breaker
, status
); 
1700         if (U_FAILURE(status
) || strsrch
->getBreakIterator() != breaker
) { 
1701             errln("Error setting break iterator"); 
1706         strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1707         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
1708              errln("Error at test number %d", count
); 
1715     while (BREAKITERATORCANONICAL
[count
].text 
!= NULL
) { 
1716          if (!assertEqual(&BREAKITERATORCANONICAL
[count
])) { 
1717              errln("Error at test number %d", count
); 
1726 void StringSearchTest::TestVariableCanonical() 
1729     UErrorCode status 
= U_ZERO_ERROR
; 
1730     m_en_us_
->setAttribute(UCOL_ALTERNATE_HANDLING
, UCOL_SHIFTED
, status
); 
1731     if (U_FAILURE(status
)) { 
1732         errln("Error setting collation alternate attribute %s",  
1733               u_errorName(status
)); 
1735     while (VARIABLE
[count
].text 
!= NULL
) { 
1736         logln("variable %d", count
); 
1737         if (!assertCanonicalEqual(&VARIABLE
[count
])) { 
1738             errln("Error at test number %d", count
); 
1742     m_en_us_
->setAttribute(UCOL_ALTERNATE_HANDLING
, UCOL_NON_IGNORABLE
,  
1746 void StringSearchTest::TestOverlapCanonical() 
1749     while (OVERLAPCANONICAL
[count
].text 
!= NULL
) { 
1750         if (!assertEqualWithAttribute(&OVERLAPCANONICAL
[count
], USEARCH_ON
,  
1752             errln("Error at overlap test number %d", count
); 
1757     while (NONOVERLAP
[count
].text 
!= NULL
) { 
1758         if (!assertCanonicalEqual(&NONOVERLAPCANONICAL
[count
])) { 
1759             errln("Error at non overlap test number %d", count
); 
1767         const SearchData 
*search 
= &(OVERLAPCANONICAL
[count
]);      
1768               UErrorCode  status 
= U_ZERO_ERROR
; 
1770         u_unescape(search
->text
, temp
, 128); 
1772         text
.setTo(temp
, u_strlen(temp
)); 
1773         u_unescape(search
->pattern
, temp
, 128); 
1774         UnicodeString pattern
; 
1775         pattern
.setTo(temp
, u_strlen(temp
)); 
1776         RuleBasedCollator 
*collator 
= getCollator(search
->collator
); 
1777         StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, collator
,  
1779         strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1780         strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_ON
, status
); 
1781         if (U_FAILURE(status
) || 
1782             strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_ON
) { 
1783             errln("Error setting overlap option"); 
1785         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
1789         search 
= &(NONOVERLAPCANONICAL
[count
]); 
1790         strsrch
->setAttribute(USEARCH_OVERLAP
, USEARCH_OFF
, status
); 
1791         if (U_FAILURE(status
) || 
1792             strsrch
->getAttribute(USEARCH_OVERLAP
) != USEARCH_OFF
) { 
1793             errln("Error setting overlap option"); 
1796         if (!assertEqualWithStringSearch(strsrch
, search
)) { 
1798             errln("Error at test number %d", count
); 
1806 void StringSearchTest::TestCollatorCanonical() 
1808     /* test collator that thinks "o" and "p" are the same thing */ 
1810     u_unescape(COLLATORCANONICAL
[0].text
, temp
, 128); 
1812     text
.setTo(temp
, u_strlen(temp
)); 
1813     u_unescape(COLLATORCANONICAL
[0].pattern
, temp
, 128); 
1814     UnicodeString pattern
; 
1815     pattern
.setTo(temp
, u_strlen(temp
)); 
1817     UErrorCode    status  
= U_ZERO_ERROR
; 
1818     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
,  
1820     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1821     if (U_FAILURE(status
)) { 
1822         errln("Error opening string search %s", u_errorName(status
)); 
1824     if (!assertEqualWithStringSearch(strsrch
, &COLLATORCANONICAL
[0])) { 
1829     u_unescape(TESTCOLLATORRULE
, temp
, 128); 
1830     UnicodeString rules
; 
1831     rules
.setTo(temp
, u_strlen(temp
)); 
1832     RuleBasedCollator 
*tailored 
= new RuleBasedCollator(rules
,  
1833         getECollationStrength(COLLATORCANONICAL
[1].strength
),  
1836     if (U_FAILURE(status
)) { 
1837         errln("Error opening rule based collator %s", u_errorName(status
)); 
1840     strsrch
->setCollator(tailored
, status
); 
1841     if (U_FAILURE(status
) || *(strsrch
->getCollator()) != *tailored
) { 
1842         errln("Error setting rule based collator"); 
1845     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1846     if (!assertEqualWithStringSearch(strsrch
, &COLLATORCANONICAL
[1])) { 
1848         if (tailored 
!= NULL
) { 
1855     strsrch
->setCollator(m_en_us_
, status
); 
1857     if (U_FAILURE(status
) || *(strsrch
->getCollator()) != *m_en_us_
) { 
1858         errln("Error setting rule based collator"); 
1860     if (!assertEqualWithStringSearch(strsrch
, &COLLATORCANONICAL
[0])) { 
1863     if (tailored 
!= NULL
) { 
1868 void StringSearchTest::TestPatternCanonical() 
1873     u_unescape(PATTERNCANONICAL
[0].text
, temp
, 128); 
1875     text
.setTo(temp
, u_strlen(temp
)); 
1876     u_unescape(PATTERNCANONICAL
[0].pattern
, temp
, 128); 
1877     UnicodeString pattern
; 
1878     pattern
.setTo(temp
, u_strlen(temp
)); 
1880     m_en_us_
->setStrength( 
1881                       getECollationStrength(PATTERNCANONICAL
[0].strength
)); 
1883     UErrorCode    status  
= U_ZERO_ERROR
; 
1884     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1886     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1887     if (U_FAILURE(status
)) { 
1888         errln("Error opening string search %s", u_errorName(status
)); 
1889         goto ENDTESTPATTERN
; 
1891     if (pattern 
!= strsrch
->getPattern()) { 
1892         errln("Error setting pattern"); 
1894     if (!assertEqualWithStringSearch(strsrch
, &PATTERNCANONICAL
[0])) { 
1895         goto ENDTESTPATTERN
; 
1898     u_unescape(PATTERNCANONICAL
[1].pattern
, temp
, 128); 
1899     pattern
.setTo(temp
, u_strlen(temp
)); 
1900     strsrch
->setPattern(pattern
, status
); 
1901     if (pattern 
!= strsrch
->getPattern()) { 
1902         errln("Error setting pattern"); 
1903         goto ENDTESTPATTERN
; 
1906     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1907     if (U_FAILURE(status
)) { 
1908         errln("Error setting pattern %s", u_errorName(status
)); 
1910     if (!assertEqualWithStringSearch(strsrch
, &PATTERNCANONICAL
[1])) { 
1911         goto ENDTESTPATTERN
; 
1914     u_unescape(PATTERNCANONICAL
[0].pattern
, temp
, 128); 
1915     pattern
.setTo(temp
, u_strlen(temp
)); 
1916     strsrch
->setPattern(pattern
, status
); 
1917     if (pattern 
!= strsrch
->getPattern()) { 
1918         errln("Error setting pattern"); 
1919         goto ENDTESTPATTERN
; 
1922     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1923     if (U_FAILURE(status
)) { 
1924         errln("Error setting pattern %s", u_errorName(status
)); 
1926     if (!assertEqualWithStringSearch(strsrch
, &PATTERNCANONICAL
[0])) { 
1927         goto ENDTESTPATTERN
; 
1930     m_en_us_
->setStrength(getECollationStrength(UCOL_TERTIARY
)); 
1931     if (strsrch 
!= NULL
) { 
1936 void StringSearchTest::TestTextCanonical() 
1939     u_unescape(TEXTCANONICAL
[0].text
, temp
, 128); 
1941     text
.setTo(temp
, u_strlen(temp
)); 
1942     u_unescape(TEXTCANONICAL
[0].pattern
, temp
, 128); 
1943     UnicodeString pattern
; 
1944     pattern
.setTo(temp
, u_strlen(temp
)); 
1946     UErrorCode    status  
= U_ZERO_ERROR
; 
1947     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
1949     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
1951     if (U_FAILURE(status
)) { 
1952         errln("Error opening string search %s", u_errorName(status
)); 
1953         goto ENDTESTPATTERN
; 
1955     if (text 
!= strsrch
->getText()) { 
1956         errln("Error setting text"); 
1958     if (!assertEqualWithStringSearch(strsrch
, &TEXTCANONICAL
[0])) { 
1959         goto ENDTESTPATTERN
; 
1962     u_unescape(TEXTCANONICAL
[1].text
, temp
, 128); 
1963     text
.setTo(temp
, u_strlen(temp
)); 
1964     strsrch
->setText(text
, status
); 
1965     if (text 
!= strsrch
->getText()) { 
1966         errln("Error setting text"); 
1967         goto ENDTESTPATTERN
; 
1969     if (U_FAILURE(status
)) { 
1970         errln("Error setting text %s", u_errorName(status
)); 
1972     if (!assertEqualWithStringSearch(strsrch
, &TEXTCANONICAL
[1])) { 
1973         goto ENDTESTPATTERN
; 
1976     u_unescape(TEXTCANONICAL
[0].text
, temp
, 128); 
1977     text
.setTo(temp
, u_strlen(temp
)); 
1978     strsrch
->setText(text
, status
); 
1979     if (text 
!= strsrch
->getText()) { 
1980         errln("Error setting text"); 
1981         goto ENDTESTPATTERN
; 
1983     if (U_FAILURE(status
)) { 
1984         errln("Error setting pattern %s", u_errorName(status
)); 
1986     if (!assertEqualWithStringSearch(strsrch
, &TEXTCANONICAL
[0])) { 
1987         goto ENDTESTPATTERN
; 
1990     if (strsrch 
!= NULL
) { 
1995 void StringSearchTest::TestCompositeBoundariesCanonical() 
1998     while (COMPOSITEBOUNDARIESCANONICAL
[count
].text 
!= NULL
) {  
1999         logln("composite %d", count
); 
2000         if (!assertCanonicalEqual(&COMPOSITEBOUNDARIESCANONICAL
[count
])) { 
2001             errln("Error at test number %d", count
); 
2007 void StringSearchTest::TestGetSetOffsetCanonical() 
2010     UErrorCode     status  
= U_ZERO_ERROR
; 
2011     UnicodeString  
text("text"); 
2012     UnicodeString  
pattern("pattern"); 
2013     StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
2015     Collator 
*collator 
= strsrch
->getCollator(); 
2017     collator
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_ON
, status
); 
2019     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
2020     /* testing out of bounds error */ 
2021     strsrch
->setOffset(-1, status
); 
2022     if (U_SUCCESS(status
)) { 
2023         errln("Error expecting set offset error"); 
2025     strsrch
->setOffset(128, status
); 
2026     if (U_SUCCESS(status
)) { 
2027         errln("Error expecting set offset error"); 
2031     while (BASICCANONICAL
[index
].text 
!= NULL
) { 
2032         SearchData  search      
= BASICCANONICAL
[index 
++]; 
2033         if (BASICCANONICAL
[index
].text 
== NULL
) { 
2034             /* skip the last one */ 
2038         u_unescape(search
.text
, temp
, 128); 
2039         text
.setTo(temp
, u_strlen(temp
)); 
2040         u_unescape(search
.pattern
, temp
, 128); 
2041         pattern
.setTo(temp
, u_strlen(temp
)); 
2043         UErrorCode  status      
= U_ZERO_ERROR
; 
2044         strsrch
->setText(text
, status
); 
2046         strsrch
->setPattern(pattern
, status
); 
2049         int32_t matchindex  
= search
.offset
[count
]; 
2050         while (U_SUCCESS(status
) && matchindex 
>= 0) { 
2051             int32_t matchlength 
= search
.size
[count
]; 
2052             strsrch
->next(status
); 
2053             if (matchindex 
!= strsrch
->getMatchedStart() ||  
2054                 matchlength 
!= strsrch
->getMatchedLength()) { 
2055                 char *str 
= toCharString(strsrch
->getText()); 
2056                 errln("Text: %s", str
); 
2057                 str 
= toCharString(strsrch
->getPattern()); 
2058                 errln("Pattern: %s", str
); 
2059                 errln("Error match found at %d %d",  
2060                       strsrch
->getMatchedStart(),  
2061                       strsrch
->getMatchedLength()); 
2064             matchindex 
= search
.offset
[count 
+ 1] == -1 ? -1 :  
2065                          search
.offset
[count 
+ 2]; 
2066             if (search
.offset
[count 
+ 1] != -1) { 
2067                 strsrch
->setOffset(search
.offset
[count 
+ 1] + 1, status
); 
2068                 if (strsrch
->getOffset() != search
.offset
[count 
+ 1] + 1) { 
2069                     errln("Error setting offset"); 
2076         strsrch
->next(status
); 
2077         if (strsrch
->getMatchedStart() != USEARCH_DONE
) { 
2078             char *str 
= toCharString(strsrch
->getText()); 
2079             errln("Text: %s", str
); 
2080             str 
= toCharString(strsrch
->getPattern()); 
2081             errln("Pattern: %s", str
); 
2082             errln("Error match found at %d %d", strsrch
->getMatchedStart(),  
2083                    strsrch
->getMatchedLength()); 
2089     collator
->setAttribute(UCOL_NORMALIZATION_MODE
, UCOL_OFF
, status
); 
2093 void StringSearchTest::TestSupplementaryCanonical() 
2096     while (SUPPLEMENTARYCANONICAL
[count
].text 
!= NULL
) { 
2097         if (!assertCanonicalEqual(&SUPPLEMENTARYCANONICAL
[count
])) { 
2098             errln("Error at test number %d", count
); 
2104 void StringSearchTest::TestContractionCanonical() 
2108     u_unescape(CONTRACTIONRULE
, temp
, 128); 
2109     UnicodeString rules
; 
2110     rules
.setTo(temp
, u_strlen(temp
)); 
2112     UErrorCode         status   
= U_ZERO_ERROR
; 
2113     RuleBasedCollator 
*collator 
= new RuleBasedCollator(rules
,  
2114         getECollationStrength(UCOL_TERTIARY
), UCOL_ON
, status
);  
2115     if (U_FAILURE(status
)) { 
2116         errln("Error opening collator %s", u_errorName(status
)); 
2118     UnicodeString 
text("text"); 
2119     UnicodeString 
pattern("pattern"); 
2120     StringSearch 
*strsrch 
= new StringSearch(pattern
, text
, collator
, NULL
,  
2122     strsrch
->setAttribute(USEARCH_CANONICAL_MATCH
, USEARCH_ON
, status
); 
2123     if (U_FAILURE(status
)) { 
2124         errln("Error opening string search %s", u_errorName(status
)); 
2128     while (CONTRACTIONCANONICAL
[count
].text 
!= NULL
) { 
2129         u_unescape(CONTRACTIONCANONICAL
[count
].text
, temp
, 128); 
2130         text
.setTo(temp
, u_strlen(temp
)); 
2131         u_unescape(CONTRACTIONCANONICAL
[count
].pattern
, temp
, 128); 
2132         pattern
.setTo(temp
, u_strlen(temp
)); 
2133         strsrch
->setText(text
, status
); 
2134         strsrch
->setPattern(pattern
, status
); 
2135         if (!assertEqualWithStringSearch(strsrch
,  
2136                                              &CONTRACTIONCANONICAL
[count
])) { 
2137             errln("Error at test number %d", count
); 
2145 void StringSearchTest::TestUClassID() 
2147     char id 
= *((char *)StringSearch::getStaticClassID()); 
2149         errln("Static class id for StringSearch should be 0"); 
2151     UErrorCode     status    
= U_ZERO_ERROR
; 
2152     UnicodeString  
text("text"); 
2153     UnicodeString  
pattern("pattern"); 
2154     StringSearch  
*strsrch 
= new StringSearch(pattern
, text
, m_en_us_
, NULL
,  
2156     id 
= *((char *)strsrch
->getDynamicClassID()); 
2158         errln("Dynamic class id for StringSearch should be 0"); 
2163 class TestSearch 
: public SearchIterator
 
2166     TestSearch(const TestSearch 
&obj
); 
2167     TestSearch(const UnicodeString 
&text
,  
2168                BreakIterator 
*breakiter
, 
2169                const UnicodeString 
&pattern
); 
2172     void        setOffset(int32_t position
, UErrorCode 
&status
); 
2173     int32_t     getOffset() const; 
2174     SearchIterator
* safeClone() const; 
2178      * ICU "poor man's RTTI", returns a UClassID for the actual class. 
2182     virtual inline UClassID 
getDynamicClassID() const { return getStaticClassID(); } 
2185      * ICU "poor man's RTTI", returns a UClassID for this class. 
2189     static inline UClassID 
getStaticClassID() { return (UClassID
)&fgClassID
; } 
2191     UBool 
operator!=(const TestSearch 
&that
) const; 
2193     UnicodeString m_pattern_
; 
2196     int32_t      handleNext(int32_t position
, UErrorCode 
&status
); 
2197     int32_t      handlePrev(int32_t position
, UErrorCode 
&status
); 
2198     TestSearch 
& operator=(const TestSearch 
&that
); 
2203      * The address of this static class variable serves as this class's ID 
2204      * for ICU "poor man's RTTI". 
2206     static const char fgClassID
; 
2210 const char TestSearch::fgClassID
=0; 
2212 TestSearch::TestSearch(const TestSearch 
&obj
) : SearchIterator(obj
) 
2214     m_offset_ 
= obj
.m_offset_
; 
2215     m_pattern_ 
= obj
.m_pattern_
; 
2218 TestSearch::TestSearch(const UnicodeString 
&text
,  
2219                        BreakIterator 
*breakiter
, 
2220                        const UnicodeString 
&pattern
) : SearchIterator() 
2222     m_breakiterator_ 
= breakiter
; 
2223     m_pattern_ 
= pattern
; 
2226     m_pattern_ 
= pattern
; 
2229 TestSearch::~TestSearch() 
2234 void TestSearch::setOffset(int32_t position
, UErrorCode 
&status
) 
2236     if (position 
>= 0 && position 
<= m_text_
.length()) { 
2237         m_offset_ 
= position
; 
2240         status 
= U_INDEX_OUTOFBOUNDS_ERROR
; 
2244 int32_t TestSearch::getOffset() const 
2249 SearchIterator 
* TestSearch::safeClone() const  
2251     return new TestSearch(m_text_
, m_breakiterator_
, m_pattern_
); 
2254 UBool 
TestSearch::operator!=(const TestSearch 
&that
) const 
2256     if (SearchIterator::operator !=(that
)) { 
2259     return m_offset_ 
!= that
.m_offset_ 
|| m_pattern_ 
!= that
.m_pattern_
; 
2262 int32_t TestSearch::handleNext(int32_t start
, UErrorCode 
&status
) 
2264   if(U_SUCCESS(status
)) { 
2265     int match 
= m_text_
.indexOf(m_pattern_
, start
); 
2267         m_offset_ 
= m_text_
.length(); 
2268         setMatchStart(m_offset_
); 
2270         return USEARCH_DONE
; 
2272     setMatchStart(match
); 
2274     setMatchLength(m_pattern_
.length()); 
2277     return USEARCH_DONE
; 
2281 int32_t TestSearch::handlePrev(int32_t start
, UErrorCode 
&status
) 
2283   if(U_SUCCESS(status
)) { 
2284     int match 
= m_text_
.lastIndexOf(m_pattern_
, 0, start
); 
2287         setMatchStart(m_offset_
); 
2289         return USEARCH_DONE
; 
2291     setMatchStart(match
); 
2293     setMatchLength(m_pattern_
.length()); 
2296     return USEARCH_DONE
; 
2300 TestSearch 
& TestSearch::operator=(const TestSearch 
&that
) 
2302     SearchIterator::operator=(that
); 
2303     m_offset_ 
= that
.m_offset_
; 
2304     m_pattern_ 
= that
.m_pattern_
; 
2308 void StringSearchTest::TestSubclass() 
2310     UnicodeString 
text("abc abcd abc"); 
2311     UnicodeString 
pattern("abc"); 
2312     TestSearch 
search(text
, NULL
, pattern
); 
2313     TestSearch 
search2(search
); 
2314     int expected
[] = {0, 4, 9}; 
2315     UErrorCode status 
= U_ZERO_ERROR
;  
2317     StringCharacterIterator 
chariter(text
); 
2319     search
.setText(text
, status
); 
2320     if (search
.getText() != search2
.getText()) { 
2321         errln("Error setting text"); 
2324     search
.setText(chariter
, status
); 
2325     if (search
.getText() != search2
.getText()) { 
2326         errln("Error setting text"); 
2330     // comparing constructors 
2332     for (i 
= 0; i 
< (int)(sizeof(expected
) / sizeof(expected
[0])); i 
++) { 
2333         if (search
.next(status
) != expected
[i
]) { 
2334             errln("Error getting next match"); 
2336         if (search
.getMatchedLength() != search
.m_pattern_
.length()) { 
2337             errln("Error getting next match length"); 
2340     if (search
.next(status
) != USEARCH_DONE
) { 
2341         errln("Error should have reached the end of the iteration"); 
2343     for (i 
= sizeof(expected
) / sizeof(expected
[0]) - 1; i 
>= 0; i 
--) { 
2344         if (search
.previous(status
) != expected
[i
]) { 
2345             errln("Error getting previous match"); 
2347         if (search
.getMatchedLength() != search
.m_pattern_
.length()) { 
2348             errln("Error getting previous match length"); 
2351     if (search
.previous(status
) != USEARCH_DONE
) { 
2352         errln("Error should have reached the start of the iteration"); 
2356 class StubSearchIterator
:public SearchIterator
{ 
2358     StubSearchIterator(){} 
2359     virtual void setOffset(int32_t , UErrorCode 
&) {}; 
2360     virtual int32_t getOffset(void) const {return 0;}; 
2361     virtual SearchIterator
* safeClone(void) const {return NULL
;}; 
2362     virtual int32_t handleNext(int32_t , UErrorCode 
&){return 0;}; 
2363     virtual int32_t handlePrev(int32_t , UErrorCode 
&) {return 0;}; 
2364     virtual UClassID 
getDynamicClassID() const { 
2365         static char classID 
= 0; 
2366         return (UClassID
)&classID
;  
2370 void StringSearchTest::TestCoverage(){ 
2371     StubSearchIterator stub1
, stub2
; 
2372     UErrorCode status 
= U_ZERO_ERROR
; 
2374     if (stub1 
!= stub2
){ 
2375         errln("new StubSearchIterator should be equal"); 
2378     stub2
.setText(UnicodeString("ABC"), status
); 
2379     if (U_FAILURE(status
)) { 
2380         errln("Error: SearchIterator::SetText"); 
2384     if (stub1 
!= stub2
){ 
2385         errln("SearchIterator::operator =  assigned object should be equal"); 
2389 #endif /* !UCONFIG_NO_BREAK_ITERATION */ 
2391 #endif /* #if !UCONFIG_NO_COLLATION */