• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *****************************************************************************
3 * Copyright (C) 2001-2010, International Business Machines orporation
4 * and others. All Rights Reserved.
5 ****************************************************************************/
6 
7 #include "unicode/utypes.h"
8 
9 #if !UCONFIG_NO_COLLATION
10 
11 #include "srchtest.h"
12 #include "../cintltst/usrchdat.c"
13 #include "unicode/stsearch.h"
14 #include "unicode/ustring.h"
15 #include "unicode/schriter.h"
16 #include <string.h>
17 #include <stdio.h>
18 
19 // private definitions -----------------------------------------------------
20 
21 #define CASE(id,test)                 \
22     case id:                          \
23         name = #test;                 \
24         if (exec) {                   \
25             logln(#test "---");       \
26             logln((UnicodeString)""); \
27             if(areBroken) {           \
28                   dataerrln(__FILE__ " cannot test - failed to create collator.");  \
29             } else {                  \
30                 test();               \
31             }                         \
32         }                             \
33         break;
34 
35 // public contructors and destructors --------------------------------------
36 
StringSearchTest()37 StringSearchTest::StringSearchTest()
38 #if !UCONFIG_NO_BREAK_ITERATION
39 :
40     m_en_wordbreaker_(NULL), m_en_characterbreaker_(NULL)
41 #endif
42 {
43 #if !UCONFIG_NO_BREAK_ITERATION
44     UErrorCode    status = U_ZERO_ERROR;
45 
46     m_en_us_ = (RuleBasedCollator *)Collator::createInstance("en_US", status);
47     m_fr_fr_ = (RuleBasedCollator *)Collator::createInstance("fr_FR", status);
48     m_de_    = (RuleBasedCollator *)Collator::createInstance("de_DE", status);
49     m_es_    = (RuleBasedCollator *)Collator::createInstance("es_ES", status);
50     if(U_FAILURE(status)) {
51       delete m_en_us_;
52       delete m_fr_fr_;
53       delete m_de_;
54       delete m_es_;
55       m_en_us_ = 0;
56       m_fr_fr_ = 0;
57       m_de_ = 0;
58       m_es_ = 0;
59       errln("Collator creation failed with %s", u_errorName(status));
60       return;
61     }
62 
63 
64     UnicodeString rules;
65     rules.setTo(((RuleBasedCollator *)m_de_)->getRules());
66     UChar extrarules[128];
67     u_unescape(EXTRACOLLATIONRULE, extrarules, 128);
68     rules.append(extrarules, u_strlen(extrarules));
69     delete m_de_;
70 
71     m_de_ = new RuleBasedCollator(rules, status);
72 
73     rules.setTo(((RuleBasedCollator *)m_es_)->getRules());
74     rules.append(extrarules, u_strlen(extrarules));
75 
76     delete m_es_;
77 
78     m_es_ = new RuleBasedCollator(rules, status);
79 
80 #if !UCONFIG_NO_BREAK_ITERATION
81     m_en_wordbreaker_      = BreakIterator::createWordInstance(
82                                                     Locale::getEnglish(), status);
83     m_en_characterbreaker_ = BreakIterator::createCharacterInstance(
84                                                     Locale::getEnglish(), status);
85 #endif
86 #endif
87 }
88 
~StringSearchTest()89 StringSearchTest::~StringSearchTest()
90 {
91 #if !UCONFIG_NO_BREAK_ITERATION
92     delete m_en_us_;
93     delete m_fr_fr_;
94     delete m_de_;
95     delete m_es_;
96 #if !UCONFIG_NO_BREAK_ITERATION
97     delete m_en_wordbreaker_;
98     delete m_en_characterbreaker_;
99 #endif
100 #endif
101 }
102 
103 // public methods ----------------------------------------------------------
104 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)105 void StringSearchTest::runIndexedTest(int32_t index, UBool exec,
106                                       const char* &name, char* )
107 {
108 #if !UCONFIG_NO_BREAK_ITERATION
109     UBool areBroken = FALSE;
110     if (m_en_us_ == NULL && m_fr_fr_ == NULL && m_de_ == NULL &&
111         m_es_ == NULL && m_en_wordbreaker_ == NULL &&
112         m_en_characterbreaker_ == NULL && exec) {
113         areBroken = TRUE;
114     }
115 
116     switch (index) {
117 #if !UCONFIG_NO_FILE_IO
118         CASE(0, TestOpenClose)
119 #endif
120         CASE(1, TestInitialization)
121         CASE(2, TestBasic)
122         CASE(3, TestNormExact)
123         CASE(4, TestStrength)
124 #if UCONFIG_NO_BREAK_ITERATION
125     case 5:
126         name = "TestBreakIterator";
127         break;
128 #else
129         CASE(5, TestBreakIterator)
130 #endif
131         CASE(6, TestVariable)
132         CASE(7, TestOverlap)
133         CASE(8, TestCollator)
134         CASE(9, TestPattern)
135         CASE(10, TestText)
136         CASE(11, TestCompositeBoundaries)
137         CASE(12, TestGetSetOffset)
138         CASE(13, TestGetSetAttribute)
139         CASE(14, TestGetMatch)
140         CASE(15, TestSetMatch)
141         CASE(16, TestReset)
142         CASE(17, TestSupplementary)
143         CASE(18, TestContraction)
144         CASE(19, TestIgnorable)
145         CASE(20, TestCanonical)
146         CASE(21, TestNormCanonical)
147         CASE(22, TestStrengthCanonical)
148 #if UCONFIG_NO_BREAK_ITERATION
149     case 23:
150         name = "TestBreakIteratorCanonical";
151         break;
152 #else
153         CASE(23, TestBreakIteratorCanonical)
154 #endif
155         CASE(24, TestVariableCanonical)
156         CASE(25, TestOverlapCanonical)
157         CASE(26, TestCollatorCanonical)
158         CASE(27, TestPatternCanonical)
159         CASE(28, TestTextCanonical)
160         CASE(29, TestCompositeBoundariesCanonical)
161         CASE(30, TestGetSetOffsetCanonical)
162         CASE(31, TestSupplementaryCanonical)
163         CASE(32, TestContractionCanonical)
164         CASE(33, TestUClassID)
165         CASE(34, TestSubclass)
166         CASE(35, TestCoverage)
167         CASE(36, TestDiacriticMatch)
168         default: name = ""; break;
169     }
170 #else
171     name="";
172 #endif
173 }
174 
175 #if !UCONFIG_NO_BREAK_ITERATION
176 // private methods ------------------------------------------------------
177 
getCollator(const char * collator)178 RuleBasedCollator * StringSearchTest::getCollator(const char *collator)
179 {
180     if (collator == NULL) {
181         return m_en_us_;
182     }
183     if (strcmp(collator, "fr") == 0) {
184         return m_fr_fr_;
185     }
186     else if (strcmp(collator, "de") == 0) {
187         return m_de_;
188     }
189     else if (strcmp(collator, "es") == 0) {
190         return m_es_;
191     }
192     else {
193         return m_en_us_;
194     }
195 }
196 
getBreakIterator(const char * breaker)197 BreakIterator * StringSearchTest::getBreakIterator(const char *breaker)
198 {
199 #if UCONFIG_NO_BREAK_ITERATION
200     return NULL;
201 #else
202     if (breaker == NULL) {
203         return NULL;
204     }
205     if (strcmp(breaker, "wordbreaker") == 0) {
206         return m_en_wordbreaker_;
207     }
208     else {
209         return m_en_characterbreaker_;
210     }
211 #endif
212 }
213 
toCharString(const UnicodeString & text)214 char * StringSearchTest::toCharString(const UnicodeString &text)
215 {
216     static char   result[1024];
217            int    index  = 0;
218            int    count  = 0;
219            int    length = text.length();
220 
221     for (; count < length; count ++) {
222         UChar ch = text[count];
223         if (ch >= 0x20 && ch <= 0x7e) {
224             result[index ++] = (char)ch;
225         }
226         else {
227             sprintf(result+index, "\\u%04x", ch);
228             index += 6; /* \uxxxx */
229         }
230     }
231     result[index] = 0;
232 
233     return result;
234 }
235 
getECollationStrength(const UCollationStrength & strength) const236 Collator::ECollationStrength StringSearchTest::getECollationStrength(
237                                     const UCollationStrength &strength) const
238 {
239   switch (strength)
240   {
241   case UCOL_PRIMARY :
242     return Collator::PRIMARY;
243   case UCOL_SECONDARY :
244     return Collator::SECONDARY;
245   case UCOL_TERTIARY :
246     return Collator::TERTIARY;
247   default :
248     return Collator::IDENTICAL;
249   }
250 }
251 
assertEqualWithStringSearch(StringSearch * strsrch,const SearchData * search)252 UBool StringSearchTest::assertEqualWithStringSearch(StringSearch *strsrch,
253                                                     const SearchData *search)
254 {
255     int           count       = 0;
256     UErrorCode    status      = U_ZERO_ERROR;
257     int32_t   matchindex  = search->offset[count];
258     UnicodeString matchtext;
259 
260     strsrch->setAttribute(USEARCH_ELEMENT_COMPARISON, search->elemCompare, status);
261     if (U_FAILURE(status)) {
262         errln("Error setting USEARCH_ELEMENT_COMPARISON attribute %s", u_errorName(status));
263         return FALSE;
264     }
265 
266     if (strsrch->getMatchedStart() != USEARCH_DONE ||
267         strsrch->getMatchedLength() != 0) {
268         errln("Error with the initialization of match start and length");
269     }
270     // start of following matches
271     while (U_SUCCESS(status) && matchindex >= 0) {
272         int32_t matchlength = search->size[count];
273         strsrch->next(status);
274         if (matchindex != strsrch->getMatchedStart() ||
275             matchlength != strsrch->getMatchedLength()) {
276             char *str = toCharString(strsrch->getText());
277             errln("Text: %s", str);
278             str = toCharString(strsrch->getPattern());
279             infoln("Pattern: %s", str);
280             infoln("Error following match found at idx,len %d,%d; expected %d,%d",
281                     strsrch->getMatchedStart(), strsrch->getMatchedLength(),
282                     matchindex, matchlength);
283             return FALSE;
284         }
285         count ++;
286 
287         strsrch->getMatchedText(matchtext);
288 
289         if (U_FAILURE(status) ||
290             strsrch->getText().compareBetween(matchindex,
291                                               matchindex + matchlength,
292                                               matchtext, 0,
293                                               matchtext.length())) {
294             errln("Error getting following matched text");
295         }
296 
297         matchindex = search->offset[count];
298     }
299     strsrch->next(status);
300     if (strsrch->getMatchedStart() != USEARCH_DONE ||
301         strsrch->getMatchedLength() != 0) {
302         char *str = toCharString(strsrch->getText());
303             errln("Text: %s", str);
304             str = toCharString(strsrch->getPattern());
305             errln("Pattern: %s", str);
306             errln("Error following match found at %d %d",
307                     strsrch->getMatchedStart(), strsrch->getMatchedLength());
308             return FALSE;
309     }
310     // start of preceding matches
311     count = count == 0 ? 0 : count - 1;
312     matchindex = search->offset[count];
313     while (U_SUCCESS(status) && matchindex >= 0) {
314         int32_t matchlength = search->size[count];
315         strsrch->previous(status);
316         if (matchindex != strsrch->getMatchedStart() ||
317             matchlength != strsrch->getMatchedLength()) {
318             char *str = toCharString(strsrch->getText());
319             errln("Text: %s", str);
320             str = toCharString(strsrch->getPattern());
321             errln("Pattern: %s", str);
322             errln("Error following match found at %d %d",
323                     strsrch->getMatchedStart(), strsrch->getMatchedLength());
324             return FALSE;
325         }
326 
327         strsrch->getMatchedText(matchtext);
328 
329         if (U_FAILURE(status) ||
330             strsrch->getText().compareBetween(matchindex,
331                                               matchindex + matchlength,
332                                               matchtext, 0,
333                                               matchtext.length())) {
334             errln("Error getting following matched text");
335         }
336 
337         matchindex = count > 0 ? search->offset[count - 1] : -1;
338         count --;
339     }
340     strsrch->previous(status);
341     if (strsrch->getMatchedStart() != USEARCH_DONE ||
342         strsrch->getMatchedLength() != 0) {
343         char *str = toCharString(strsrch->getText());
344             errln("Text: %s", str);
345             str = toCharString(strsrch->getPattern());
346             errln("Pattern: %s", str);
347             errln("Error following match found at %d %d",
348                     strsrch->getMatchedStart(), strsrch->getMatchedLength());
349             return FALSE;
350     }
351     strsrch->setAttribute(USEARCH_ELEMENT_COMPARISON, USEARCH_STANDARD_ELEMENT_COMPARISON, status);
352     return TRUE;
353 }
354 
assertEqual(const SearchData * search)355 UBool StringSearchTest::assertEqual(const SearchData *search)
356 {
357     UErrorCode     status   = U_ZERO_ERROR;
358 
359     Collator      *collator = getCollator(search->collator);
360     BreakIterator *breaker  = getBreakIterator(search->breaker);
361     StringSearch  *strsrch, *strsrch2;
362     UChar          temp[128];
363 
364 #if UCONFIG_NO_BREAK_ITERATION
365     if(search->breaker) {
366       return TRUE; /* skip test */
367     }
368 #endif
369     u_unescape(search->text, temp, 128);
370     UnicodeString text;
371     text.setTo(temp);
372     u_unescape(search->pattern, temp, 128);
373     UnicodeString  pattern;
374     pattern.setTo(temp);
375 
376 #if !UCONFIG_NO_BREAK_ITERATION
377     if (breaker != NULL) {
378         breaker->setText(text);
379     }
380 #endif
381     collator->setStrength(getECollationStrength(search->strength));
382     strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
383                                breaker, status);
384     if (U_FAILURE(status)) {
385         errln("Error opening string search %s", u_errorName(status));
386         return FALSE;
387     }
388 
389     if (!assertEqualWithStringSearch(strsrch, search)) {
390         collator->setStrength(getECollationStrength(UCOL_TERTIARY));
391         delete strsrch;
392         return FALSE;
393     }
394 
395 
396     strsrch2 = strsrch->clone();
397     if( strsrch2 == strsrch || *strsrch2 != *strsrch ||
398         !assertEqualWithStringSearch(strsrch2, search)
399     ) {
400         infoln("failure with StringSearch.clone()");
401         collator->setStrength(getECollationStrength(UCOL_TERTIARY));
402         delete strsrch;
403         delete strsrch2;
404         return FALSE;
405     }
406     delete strsrch2;
407 
408     collator->setStrength(getECollationStrength(UCOL_TERTIARY));
409     delete strsrch;
410     return TRUE;
411 }
412 
assertCanonicalEqual(const SearchData * search)413 UBool StringSearchTest::assertCanonicalEqual(const SearchData *search)
414 {
415     UErrorCode     status   = U_ZERO_ERROR;
416     Collator      *collator = getCollator(search->collator);
417     BreakIterator *breaker  = getBreakIterator(search->breaker);
418     StringSearch  *strsrch;
419     UChar          temp[128];
420     UBool          result = TRUE;
421 
422 #if UCONFIG_NO_BREAK_ITERATION
423     if(search->breaker) {
424       return TRUE; /* skip test */
425     }
426 #endif
427 
428     u_unescape(search->text, temp, 128);
429     UnicodeString text;
430     text.setTo(temp);
431     u_unescape(search->pattern, temp, 128);
432     UnicodeString  pattern;
433     pattern.setTo(temp);
434 
435 #if !UCONFIG_NO_BREAK_ITERATION
436     if (breaker != NULL) {
437         breaker->setText(text);
438     }
439 #endif
440     collator->setStrength(getECollationStrength(search->strength));
441     collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
442     strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
443                                breaker, status);
444     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
445     if (U_FAILURE(status)) {
446         errln("Error opening string search %s", u_errorName(status));
447         result = FALSE;
448         goto bail;
449     }
450 
451     if (!assertEqualWithStringSearch(strsrch, search)) {
452         result = FALSE;
453         goto bail;
454     }
455 
456 bail:
457     collator->setStrength(getECollationStrength(UCOL_TERTIARY));
458     collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
459     delete strsrch;
460 
461     return result;
462 }
463 
assertEqualWithAttribute(const SearchData * search,USearchAttributeValue canonical,USearchAttributeValue overlap)464 UBool StringSearchTest::assertEqualWithAttribute(const SearchData *search,
465                                             USearchAttributeValue canonical,
466                                             USearchAttributeValue overlap)
467 {
468     UErrorCode     status   = U_ZERO_ERROR;
469     Collator      *collator = getCollator(search->collator);
470     BreakIterator *breaker  = getBreakIterator(search->breaker);
471     StringSearch  *strsrch;
472     UChar          temp[128];
473 
474 
475 #if UCONFIG_NO_BREAK_ITERATION
476     if(search->breaker) {
477       return TRUE; /* skip test */
478     }
479 #endif
480 
481     u_unescape(search->text, temp, 128);
482     UnicodeString text;
483     text.setTo(temp);
484     u_unescape(search->pattern, temp, 128);
485     UnicodeString  pattern;
486     pattern.setTo(temp);
487 
488 #if !UCONFIG_NO_BREAK_ITERATION
489     if (breaker != NULL) {
490         breaker->setText(text);
491     }
492 #endif
493     collator->setStrength(getECollationStrength(search->strength));
494     strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
495                                breaker, status);
496     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, canonical, status);
497     strsrch->setAttribute(USEARCH_OVERLAP, overlap, status);
498 
499     if (U_FAILURE(status)) {
500         errln("Error opening string search %s", u_errorName(status));
501         return FALSE;
502     }
503 
504     if (!assertEqualWithStringSearch(strsrch, search)) {
505         collator->setStrength(getECollationStrength(UCOL_TERTIARY));
506         delete strsrch;
507         return FALSE;
508     }
509     collator->setStrength(getECollationStrength(UCOL_TERTIARY));
510     delete strsrch;
511     return TRUE;
512 }
513 
TestOpenClose()514 void StringSearchTest::TestOpenClose()
515 {
516     UErrorCode               status    = U_ZERO_ERROR;
517     StringSearch            *result;
518     BreakIterator           *breakiter = m_en_wordbreaker_;
519     UnicodeString            pattern;
520     UnicodeString            text;
521     UnicodeString            temp("a");
522     StringCharacterIterator  chariter(text);
523 
524     /* testing null arguments */
525     result = new StringSearch(pattern, text, NULL, NULL, status);
526     if (U_SUCCESS(status)) {
527         errln("Error: NULL arguments should produce an error");
528     }
529     delete result;
530 
531     chariter.setText(text);
532     status = U_ZERO_ERROR;
533     result = new StringSearch(pattern, chariter, NULL, NULL, status);
534     if (U_SUCCESS(status)) {
535         errln("Error: NULL arguments should produce an error");
536     }
537     delete result;
538 
539     text.append(0, 0x1);
540     status = U_ZERO_ERROR;
541     result = new StringSearch(pattern, text, NULL, NULL, status);
542     if (U_SUCCESS(status)) {
543         errln("Error: Empty pattern should produce an error");
544     }
545     delete result;
546 
547     chariter.setText(text);
548     status = U_ZERO_ERROR;
549     result = new StringSearch(pattern, chariter, NULL, NULL, status);
550     if (U_SUCCESS(status)) {
551         errln("Error: Empty pattern should produce an error");
552     }
553     delete result;
554 
555     text.remove();
556     pattern.append(temp);
557     status = U_ZERO_ERROR;
558     result = new StringSearch(pattern, text, NULL, NULL, status);
559     if (U_SUCCESS(status)) {
560         errln("Error: Empty text should produce an error");
561     }
562     delete result;
563 
564     chariter.setText(text);
565     status = U_ZERO_ERROR;
566     result = new StringSearch(pattern, chariter, NULL, NULL, status);
567     if (U_SUCCESS(status)) {
568         errln("Error: Empty text should produce an error");
569     }
570     delete result;
571 
572     text.append(temp);
573     status = U_ZERO_ERROR;
574     result = new StringSearch(pattern, text, NULL, NULL, status);
575     if (U_SUCCESS(status)) {
576         errln("Error: NULL arguments should produce an error");
577     }
578     delete result;
579 
580     chariter.setText(text);
581     status = U_ZERO_ERROR;
582     result = new StringSearch(pattern, chariter, NULL, NULL, status);
583     if (U_SUCCESS(status)) {
584         errln("Error: NULL arguments should produce an error");
585     }
586     delete result;
587 
588     status = U_ZERO_ERROR;
589     result = new StringSearch(pattern, text, m_en_us_, NULL, status);
590     if (U_FAILURE(status)) {
591         errln("Error: NULL break iterator is valid for opening search");
592     }
593     delete result;
594 
595     status = U_ZERO_ERROR;
596     result = new StringSearch(pattern, chariter, m_en_us_, NULL, status);
597     if (U_FAILURE(status)) {
598         errln("Error: NULL break iterator is valid for opening search");
599     }
600     delete result;
601 
602     status = U_ZERO_ERROR;
603     result = new StringSearch(pattern, text, Locale::getEnglish(), NULL, status);
604     if (U_FAILURE(status) || result == NULL) {
605         errln("Error: NULL break iterator is valid for opening search");
606     }
607     delete result;
608 
609     status = U_ZERO_ERROR;
610     result = new StringSearch(pattern, chariter, Locale::getEnglish(), NULL, status);
611     if (U_FAILURE(status)) {
612         errln("Error: NULL break iterator is valid for opening search");
613     }
614     delete result;
615 
616     status = U_ZERO_ERROR;
617     result = new StringSearch(pattern, text, m_en_us_, breakiter, status);
618     if (U_FAILURE(status)) {
619         errln("Error: Break iterator is valid for opening search");
620     }
621     delete result;
622 
623     status = U_ZERO_ERROR;
624     result = new StringSearch(pattern, chariter, m_en_us_, NULL, status);
625     if (U_FAILURE(status)) {
626         errln("Error: Break iterator is valid for opening search");
627     }
628     delete result;
629 }
630 
TestInitialization()631 void StringSearchTest::TestInitialization()
632 {
633     UErrorCode     status = U_ZERO_ERROR;
634     UnicodeString  pattern;
635     UnicodeString  text;
636     UnicodeString  temp("a");
637     StringSearch  *result;
638     int count;
639 
640     /* simple test on the pattern ce construction */
641     pattern.append(temp);
642     pattern.append(temp);
643     text.append(temp);
644     text.append(temp);
645     text.append(temp);
646     result = new StringSearch(pattern, text, m_en_us_, NULL, status);
647     if (U_FAILURE(status)) {
648         errln("Error opening search %s", u_errorName(status));
649     }
650     StringSearch *copy = new StringSearch(*result);
651     if (*(copy->getCollator()) != *(result->getCollator()) ||
652         copy->getBreakIterator() != result->getBreakIterator() ||
653         copy->getMatchedLength() != result->getMatchedLength() ||
654         copy->getMatchedStart() != result->getMatchedStart() ||
655         copy->getOffset() != result->getOffset() ||
656         copy->getPattern() != result->getPattern() ||
657         copy->getText() != result->getText() ||
658         *(copy) != *(result))
659     {
660         errln("Error copying StringSearch");
661     }
662     delete copy;
663 
664     copy = (StringSearch *)result->safeClone();
665     if (*(copy->getCollator()) != *(result->getCollator()) ||
666         copy->getBreakIterator() != result->getBreakIterator() ||
667         copy->getMatchedLength() != result->getMatchedLength() ||
668         copy->getMatchedStart() != result->getMatchedStart() ||
669         copy->getOffset() != result->getOffset() ||
670         copy->getPattern() != result->getPattern() ||
671         copy->getText() != result->getText() ||
672         *(copy) != *(result)) {
673         errln("Error copying StringSearch");
674     }
675     delete result;
676 
677     /* testing if an extremely large pattern will fail the initialization */
678     for (count = 0; count < 512; count ++) {
679         pattern.append(temp);
680     }
681     result = new StringSearch(pattern, text, m_en_us_, NULL, status);
682     if (*result != *result) {
683         errln("Error: string search object expected to match itself");
684     }
685     if (*result == *copy) {
686         errln("Error: string search objects are not expected to match");
687     }
688     *copy  = *result;
689     if (*(copy->getCollator()) != *(result->getCollator()) ||
690         copy->getBreakIterator() != result->getBreakIterator() ||
691         copy->getMatchedLength() != result->getMatchedLength() ||
692         copy->getMatchedStart() != result->getMatchedStart() ||
693         copy->getOffset() != result->getOffset() ||
694         copy->getPattern() != result->getPattern() ||
695         copy->getText() != result->getText() ||
696         *(copy) != *(result)) {
697         errln("Error copying StringSearch");
698     }
699     if (U_FAILURE(status)) {
700         errln("Error opening search %s", u_errorName(status));
701     }
702     delete result;
703     delete copy;
704 }
705 
TestBasic()706 void StringSearchTest::TestBasic()
707 {
708     int count = 0;
709     while (BASIC[count].text != NULL) {
710         //printf("count %d", count);
711         if (!assertEqual(&BASIC[count])) {
712             infoln("Error at test number %d", count);
713         }
714         count ++;
715     }
716 }
717 
TestNormExact()718 void StringSearchTest::TestNormExact()
719 {
720     int count = 0;
721     UErrorCode status = U_ZERO_ERROR;
722     m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
723     if (U_FAILURE(status)) {
724         errln("Error setting collation normalization %s",
725               u_errorName(status));
726     }
727     while (BASIC[count].text != NULL) {
728         if (!assertEqual(&BASIC[count])) {
729             infoln("Error at test number %d", count);
730         }
731         count ++;
732     }
733     count = 0;
734     while (NORMEXACT[count].text != NULL) {
735         if (!assertEqual(&NORMEXACT[count])) {
736             infoln("Error at test number %d", count);
737         }
738         count ++;
739     }
740     m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
741     count = 0;
742     while (NONNORMEXACT[count].text != NULL) {
743         if (!assertEqual(&NONNORMEXACT[count])) {
744             infoln("Error at test number %d", count);
745         }
746         count ++;
747     }
748 }
749 
TestStrength()750 void StringSearchTest::TestStrength()
751 {
752     int count = 0;
753     while (STRENGTH[count].text != NULL) {
754         if (!assertEqual(&STRENGTH[count])) {
755             infoln("Error at test number %d", count);
756         }
757         count ++;
758     }
759 }
760 
761 #if !UCONFIG_NO_BREAK_ITERATION
762 
TestBreakIterator()763 void StringSearchTest::TestBreakIterator()
764 {
765     UChar temp[128];
766     u_unescape(BREAKITERATOREXACT[0].text, temp, 128);
767     UnicodeString text;
768     text.setTo(temp, u_strlen(temp));
769     u_unescape(BREAKITERATOREXACT[0].pattern, temp, 128);
770     UnicodeString pattern;
771     pattern.setTo(temp, u_strlen(temp));
772 
773     UErrorCode status = U_ZERO_ERROR;
774     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
775                                              status);
776     if (U_FAILURE(status)) {
777         errln("Error opening string search %s", u_errorName(status));
778     }
779 
780     strsrch->setBreakIterator(NULL, status);
781     if (U_FAILURE(status) || strsrch->getBreakIterator() != NULL) {
782         errln("Error usearch_getBreakIterator returned wrong object");
783     }
784 
785     strsrch->setBreakIterator(m_en_characterbreaker_, status);
786     if (U_FAILURE(status) ||
787         strsrch->getBreakIterator() != m_en_characterbreaker_) {
788         errln("Error usearch_getBreakIterator returned wrong object");
789     }
790 
791     strsrch->setBreakIterator(m_en_wordbreaker_, status);
792     if (U_FAILURE(status) ||
793         strsrch->getBreakIterator() != m_en_wordbreaker_) {
794         errln("Error usearch_getBreakIterator returned wrong object");
795     }
796 
797     delete strsrch;
798 
799     int count = 0;
800     while (count < 4) {
801         // special purposes for tests numbers 0-3
802         const SearchData        *search   = &(BREAKITERATOREXACT[count]);
803               RuleBasedCollator *collator = getCollator(search->collator);
804               BreakIterator     *breaker  = getBreakIterator(search->breaker);
805               StringSearch      *strsrch;
806 
807         u_unescape(search->text, temp, 128);
808         text.setTo(temp, u_strlen(temp));
809         u_unescape(search->pattern, temp, 128);
810         pattern.setTo(temp, u_strlen(temp));
811         if (breaker != NULL) {
812             breaker->setText(text);
813         }
814         collator->setStrength(getECollationStrength(search->strength));
815 
816         strsrch = new StringSearch(pattern, text, collator, breaker, status);
817         if (U_FAILURE(status) ||
818             strsrch->getBreakIterator() != breaker) {
819             errln("Error setting break iterator");
820             if (strsrch != NULL) {
821                 delete strsrch;
822             }
823         }
824         if (!assertEqualWithStringSearch(strsrch, search)) {
825             collator->setStrength(getECollationStrength(UCOL_TERTIARY));
826             delete strsrch;
827         }
828         search   = &(BREAKITERATOREXACT[count + 1]);
829         breaker  = getBreakIterator(search->breaker);
830         if (breaker != NULL) {
831             breaker->setText(text);
832         }
833         strsrch->setBreakIterator(breaker, status);
834         if (U_FAILURE(status) ||
835             strsrch->getBreakIterator() != breaker) {
836             errln("Error setting break iterator");
837             delete strsrch;
838         }
839         strsrch->reset();
840         if (!assertEqualWithStringSearch(strsrch, search)) {
841              infoln("Error at test number %d", count);
842         }
843         delete strsrch;
844         count += 2;
845     }
846     count = 0;
847     while (BREAKITERATOREXACT[count].text != NULL) {
848          if (!assertEqual(&BREAKITERATOREXACT[count])) {
849              infoln("Error at test number %d", count);
850          }
851          count ++;
852     }
853 }
854 
855 #endif
856 
TestVariable()857 void StringSearchTest::TestVariable()
858 {
859     int count = 0;
860     UErrorCode status = U_ZERO_ERROR;
861     m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
862     if (U_FAILURE(status)) {
863         errln("Error setting collation alternate attribute %s",
864               u_errorName(status));
865     }
866     while (VARIABLE[count].text != NULL) {
867         logln("variable %d", count);
868         if (!assertEqual(&VARIABLE[count])) {
869             infoln("Error at test number %d", count);
870         }
871         count ++;
872     }
873     m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
874                            status);
875 }
876 
TestOverlap()877 void StringSearchTest::TestOverlap()
878 {
879     int count = 0;
880     while (OVERLAP[count].text != NULL) {
881         if (!assertEqualWithAttribute(&OVERLAP[count], USEARCH_OFF,
882                                       USEARCH_ON)) {
883             errln("Error at overlap test number %d", count);
884         }
885         count ++;
886     }
887     count = 0;
888     while (NONOVERLAP[count].text != NULL) {
889         if (!assertEqual(&NONOVERLAP[count])) {
890             errln("Error at non overlap test number %d", count);
891         }
892         count ++;
893     }
894 
895     count = 0;
896     while (count < 1) {
897         const SearchData *search = &(OVERLAP[count]);
898               UChar       temp[128];
899         u_unescape(search->text, temp, 128);
900         UnicodeString text;
901         text.setTo(temp, u_strlen(temp));
902         u_unescape(search->pattern, temp, 128);
903         UnicodeString pattern;
904         pattern.setTo(temp, u_strlen(temp));
905 
906         RuleBasedCollator *collator = getCollator(search->collator);
907         UErrorCode         status   = U_ZERO_ERROR;
908         StringSearch      *strsrch  = new StringSearch(pattern, text,
909                                                        collator, NULL,
910                                                        status);
911 
912         strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
913         if (U_FAILURE(status) ||
914             strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
915             errln("Error setting overlap option");
916         }
917         if (!assertEqualWithStringSearch(strsrch, search)) {
918             delete strsrch;
919             return;
920         }
921 
922         search = &(NONOVERLAP[count]);
923         strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
924         if (U_FAILURE(status) ||
925             strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
926             errln("Error setting overlap option");
927         }
928         strsrch->reset();
929         if (!assertEqualWithStringSearch(strsrch, search)) {
930             delete strsrch;
931             errln("Error at test number %d", count);
932          }
933 
934         count ++;
935         delete strsrch;
936     }
937 }
938 
TestCollator()939 void StringSearchTest::TestCollator()
940 {
941     // test collator that thinks "o" and "p" are the same thing
942     UChar         temp[128];
943     u_unescape(COLLATOR[0].text, temp, 128);
944     UnicodeString text;
945     text.setTo(temp, u_strlen(temp));
946     u_unescape(COLLATOR[0].pattern, temp, 128);
947     UnicodeString pattern;
948     pattern.setTo(temp, u_strlen(temp));
949 
950     UErrorCode    status = U_ZERO_ERROR;
951     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
952                                              status);
953     if (U_FAILURE(status)) {
954         errln("Error opening string search %s", u_errorName(status));
955         delete strsrch;
956         return;
957     }
958     if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
959         delete strsrch;
960         return;
961     }
962 
963     u_unescape(TESTCOLLATORRULE, temp, 128);
964     UnicodeString rules;
965     rules.setTo(temp, u_strlen(temp));
966     RuleBasedCollator *tailored = new RuleBasedCollator(rules, status);
967     tailored->setStrength(getECollationStrength(COLLATOR[1].strength));
968 
969     if (U_FAILURE(status)) {
970         errln("Error opening rule based collator %s", u_errorName(status));
971         delete strsrch;
972         if (tailored != NULL) {
973             delete tailored;
974         }
975         return;
976     }
977 
978     strsrch->setCollator(tailored, status);
979     if (U_FAILURE(status) || (*strsrch->getCollator()) != (*tailored)) {
980         errln("Error setting rule based collator");
981         delete strsrch;
982         if (tailored != NULL) {
983             delete tailored;
984         }
985     }
986     strsrch->reset();
987     if (!assertEqualWithStringSearch(strsrch, &COLLATOR[1])) {
988         delete strsrch;
989         if (tailored != NULL) {
990             delete tailored;
991         }
992         return;
993     }
994 
995     strsrch->setCollator(m_en_us_, status);
996     strsrch->reset();
997     if (U_FAILURE(status) || (*strsrch->getCollator()) != (*m_en_us_)) {
998         errln("Error setting rule based collator");
999         delete strsrch;
1000         if (tailored != NULL) {
1001             delete tailored;
1002         }
1003     }
1004     if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
1005        errln("Error searching collator test");
1006     }
1007     delete strsrch;
1008     if (tailored != NULL) {
1009         delete tailored;
1010     }
1011 }
1012 
TestPattern()1013 void StringSearchTest::TestPattern()
1014 {
1015 
1016     UChar temp[512];
1017     int templength;
1018     u_unescape(PATTERN[0].text, temp, 512);
1019     UnicodeString text;
1020     text.setTo(temp, u_strlen(temp));
1021     u_unescape(PATTERN[0].pattern, temp, 512);
1022     UnicodeString pattern;
1023     pattern.setTo(temp, u_strlen(temp));
1024 
1025     m_en_us_->setStrength(getECollationStrength(PATTERN[0].strength));
1026     UErrorCode    status = U_ZERO_ERROR;
1027     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1028                                              status);
1029 
1030     if (U_FAILURE(status)) {
1031         errln("Error opening string search %s", u_errorName(status));
1032         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1033         if (strsrch != NULL) {
1034             delete strsrch;
1035         }
1036         return;
1037     }
1038     if (strsrch->getPattern() != pattern) {
1039         errln("Error setting pattern");
1040     }
1041     if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1042         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1043         if (strsrch != NULL) {
1044             delete strsrch;
1045         }
1046         return;
1047     }
1048 
1049     u_unescape(PATTERN[1].pattern, temp, 512);
1050     pattern.setTo(temp, u_strlen(temp));
1051     strsrch->setPattern(pattern, status);
1052     if (pattern != strsrch->getPattern()) {
1053         errln("Error setting pattern");
1054         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1055         if (strsrch != NULL) {
1056             delete strsrch;
1057         }
1058         return;
1059     }
1060     strsrch->reset();
1061     if (U_FAILURE(status)) {
1062         errln("Error setting pattern %s", u_errorName(status));
1063     }
1064     if (!assertEqualWithStringSearch(strsrch, &PATTERN[1])) {
1065         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1066         if (strsrch != NULL) {
1067             delete strsrch;
1068         }
1069         return;
1070     }
1071 
1072     u_unescape(PATTERN[0].pattern, temp, 512);
1073     pattern.setTo(temp, u_strlen(temp));
1074     strsrch->setPattern(pattern, status);
1075     if (pattern != strsrch->getPattern()) {
1076         errln("Error setting pattern");
1077         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1078         if (strsrch != NULL) {
1079             delete strsrch;
1080         }
1081         return;
1082     }
1083     strsrch->reset();
1084     if (U_FAILURE(status)) {
1085         errln("Error setting pattern %s", u_errorName(status));
1086     }
1087     if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1088         m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1089         if (strsrch != NULL) {
1090             delete strsrch;
1091         }
1092         return;
1093     }
1094     /* enormous pattern size to see if this crashes */
1095     for (templength = 0; templength != 512; templength ++) {
1096         temp[templength] = 0x61;
1097     }
1098     temp[511] = 0;
1099     pattern.setTo(temp, 511);
1100     strsrch->setPattern(pattern, status);
1101     if (U_FAILURE(status)) {
1102         errln("Error setting pattern with size 512, %s", u_errorName(status));
1103     }
1104     m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1105     if (strsrch != NULL) {
1106         delete strsrch;
1107     }
1108 }
1109 
TestText()1110 void StringSearchTest::TestText()
1111 {
1112     UChar temp[128];
1113     u_unescape(TEXT[0].text, temp, 128);
1114     UnicodeString text;
1115     text.setTo(temp, u_strlen(temp));
1116     u_unescape(TEXT[0].pattern, temp, 128);
1117     UnicodeString pattern;
1118     pattern.setTo(temp, u_strlen(temp));
1119 
1120     UErrorCode status = U_ZERO_ERROR;
1121     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1122                                              status);
1123     if (U_FAILURE(status)) {
1124         errln("Error opening string search %s", u_errorName(status));
1125         return;
1126     }
1127     if (text != strsrch->getText()) {
1128         errln("Error setting text");
1129     }
1130     if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1131         delete strsrch;
1132         return;
1133     }
1134 
1135     u_unescape(TEXT[1].text, temp, 128);
1136     text.setTo(temp, u_strlen(temp));
1137     strsrch->setText(text, status);
1138     if (text != strsrch->getText()) {
1139         errln("Error setting text");
1140         delete strsrch;
1141         return;
1142     }
1143     if (U_FAILURE(status)) {
1144         errln("Error setting text %s", u_errorName(status));
1145     }
1146     if (!assertEqualWithStringSearch(strsrch, &TEXT[1])) {
1147         delete strsrch;
1148         return;
1149     }
1150 
1151     u_unescape(TEXT[0].text, temp, 128);
1152     text.setTo(temp, u_strlen(temp));
1153     StringCharacterIterator chariter(text);
1154     strsrch->setText(chariter, status);
1155     if (text != strsrch->getText()) {
1156         errln("Error setting text");
1157         delete strsrch;
1158         return;
1159     }
1160     if (U_FAILURE(status)) {
1161         errln("Error setting pattern %s", u_errorName(status));
1162     }
1163     if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1164         errln("Error searching within set text");
1165     }
1166     delete strsrch;
1167 }
1168 
TestCompositeBoundaries()1169 void StringSearchTest::TestCompositeBoundaries()
1170 {
1171     int count = 0;
1172     while (COMPOSITEBOUNDARIES[count].text != NULL) {
1173         logln("composite %d", count);
1174         if (!assertEqual(&COMPOSITEBOUNDARIES[count])) {
1175             errln("Error at test number %d", count);
1176         }
1177         count ++;
1178     }
1179 }
1180 
TestGetSetOffset()1181 void StringSearchTest::TestGetSetOffset()
1182 {
1183     UErrorCode     status  = U_ZERO_ERROR;
1184     UnicodeString  pattern("1234567890123456");
1185     UnicodeString  text("12345678901234567890123456789012");
1186     StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_,
1187                                               NULL, status);
1188     /* testing out of bounds error */
1189     strsrch->setOffset(-1, status);
1190     if (U_SUCCESS(status)) {
1191         errln("Error expecting set offset error");
1192     }
1193     strsrch->setOffset(128, status);
1194     if (U_SUCCESS(status)) {
1195         errln("Error expecting set offset error");
1196     }
1197     int index   = 0;
1198     while (BASIC[index].text != NULL) {
1199         UErrorCode  status      = U_ZERO_ERROR;
1200         SearchData  search      = BASIC[index ++];
1201         UChar       temp[128];
1202 
1203         u_unescape(search.text, temp, 128);
1204         text.setTo(temp, u_strlen(temp));
1205         u_unescape(search.pattern, temp, 128);
1206         pattern.setTo(temp, u_strlen(temp));
1207         strsrch->setText(text, status);
1208         strsrch->setPattern(pattern, status);
1209         strsrch->getCollator()->setStrength(getECollationStrength(
1210                                                           search.strength));
1211         strsrch->reset();
1212 
1213         int count = 0;
1214         int32_t matchindex  = search.offset[count];
1215         while (U_SUCCESS(status) && matchindex >= 0) {
1216             int32_t matchlength = search.size[count];
1217             strsrch->next(status);
1218             if (matchindex != strsrch->getMatchedStart() ||
1219                 matchlength != strsrch->getMatchedLength()) {
1220                 char *str = toCharString(strsrch->getText());
1221                 errln("Text: %s", str);
1222                 str = toCharString(strsrch->getPattern());
1223                 errln("Pattern: %s", str);
1224                 errln("Error match found at %d %d",
1225                         strsrch->getMatchedStart(),
1226                         strsrch->getMatchedLength());
1227                 return;
1228             }
1229             matchindex = search.offset[count + 1] == -1 ? -1 :
1230                          search.offset[count + 2];
1231             if (search.offset[count + 1] != -1) {
1232                 strsrch->setOffset(search.offset[count + 1] + 1, status);
1233                 if (strsrch->getOffset() != search.offset[count + 1] + 1) {
1234                     errln("Error setting offset\n");
1235                     return;
1236                 }
1237             }
1238 
1239             count += 2;
1240         }
1241         strsrch->next(status);
1242         if (strsrch->getMatchedStart() != USEARCH_DONE) {
1243             char *str = toCharString(strsrch->getText());
1244             errln("Text: %s", str);
1245             str = toCharString(strsrch->getPattern());
1246             errln("Pattern: %s", str);
1247             errln("Error match found at %d %d",
1248                         strsrch->getMatchedStart(),
1249                         strsrch->getMatchedLength());
1250             return;
1251         }
1252     }
1253     strsrch->getCollator()->setStrength(getECollationStrength(
1254                                                              UCOL_TERTIARY));
1255     delete strsrch;
1256 }
1257 
TestGetSetAttribute()1258 void StringSearchTest::TestGetSetAttribute()
1259 {
1260     UErrorCode     status    = U_ZERO_ERROR;
1261     UnicodeString  pattern("pattern");
1262     UnicodeString  text("text");
1263     StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1264                                               status);
1265     if (U_FAILURE(status)) {
1266         errln("Error opening search %s", u_errorName(status));
1267         return;
1268     }
1269 
1270     strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_DEFAULT, status);
1271     if (U_FAILURE(status) ||
1272         strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1273         errln("Error setting overlap to the default");
1274     }
1275     strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1276     if (U_FAILURE(status) ||
1277         strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
1278         errln("Error setting overlap true");
1279     }
1280     strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
1281     if (U_FAILURE(status) ||
1282         strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1283         errln("Error setting overlap false");
1284     }
1285     strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ATTRIBUTE_VALUE_COUNT,
1286                           status);
1287     if (U_SUCCESS(status)) {
1288         errln("Error setting overlap to illegal value");
1289     }
1290     status = U_ZERO_ERROR;
1291     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT, status);
1292     if (U_FAILURE(status) ||
1293         strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF) {
1294         errln("Error setting canonical match to the default");
1295     }
1296     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1297     if (U_FAILURE(status) ||
1298         strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_ON) {
1299         errln("Error setting canonical match true");
1300     }
1301     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_OFF, status);
1302     if (U_FAILURE(status) ||
1303         strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF) {
1304         errln("Error setting canonical match false");
1305     }
1306     strsrch->setAttribute(USEARCH_CANONICAL_MATCH,
1307                           USEARCH_ATTRIBUTE_VALUE_COUNT, status);
1308     if (U_SUCCESS(status)) {
1309         errln("Error setting canonical match to illegal value");
1310     }
1311     status = U_ZERO_ERROR;
1312     strsrch->setAttribute(USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT, status);
1313     if (U_SUCCESS(status)) {
1314         errln("Error setting illegal attribute success");
1315     }
1316 
1317     delete strsrch;
1318 }
1319 
TestGetMatch()1320 void StringSearchTest::TestGetMatch()
1321 {
1322     UChar      temp[128];
1323     SearchData search = MATCH[0];
1324     u_unescape(search.text, temp, 128);
1325     UnicodeString text;
1326     text.setTo(temp, u_strlen(temp));
1327     u_unescape(search.pattern, temp, 128);
1328     UnicodeString pattern;
1329     pattern.setTo(temp, u_strlen(temp));
1330 
1331     UErrorCode    status  = U_ZERO_ERROR;
1332     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1333                                              status);
1334     if (U_FAILURE(status)) {
1335         errln("Error opening string search %s", u_errorName(status));
1336         if (strsrch != NULL) {
1337             delete strsrch;
1338         }
1339         return;
1340     }
1341 
1342     int           count      = 0;
1343     int32_t   matchindex = search.offset[count];
1344     UnicodeString matchtext;
1345     while (U_SUCCESS(status) && matchindex >= 0) {
1346         int32_t matchlength = search.size[count];
1347         strsrch->next(status);
1348         if (matchindex != strsrch->getMatchedStart() ||
1349             matchlength != strsrch->getMatchedLength()) {
1350             char *str = toCharString(strsrch->getText());
1351             errln("Text: %s", str);
1352             str = toCharString(strsrch->getPattern());
1353             errln("Pattern: %s", str);
1354             errln("Error match found at %d %d", strsrch->getMatchedStart(),
1355                   strsrch->getMatchedLength());
1356             return;
1357         }
1358         count ++;
1359 
1360         status = U_ZERO_ERROR;
1361         strsrch->getMatchedText(matchtext);
1362         if (matchtext.length() != matchlength || U_FAILURE(status)){
1363             errln("Error getting match text");
1364         }
1365         matchindex = search.offset[count];
1366     }
1367     status = U_ZERO_ERROR;
1368     strsrch->next(status);
1369     if (strsrch->getMatchedStart()  != USEARCH_DONE ||
1370         strsrch->getMatchedLength() != 0) {
1371         errln("Error end of match not found");
1372     }
1373     status = U_ZERO_ERROR;
1374     strsrch->getMatchedText(matchtext);
1375     if (matchtext.length() != 0) {
1376         errln("Error getting null matches");
1377     }
1378     delete strsrch;
1379 }
1380 
TestSetMatch()1381 void StringSearchTest::TestSetMatch()
1382 {
1383     int count = 0;
1384     while (MATCH[count].text != NULL) {
1385         SearchData     search = MATCH[count];
1386         UChar          temp[128];
1387         UErrorCode status = U_ZERO_ERROR;
1388         u_unescape(search.text, temp, 128);
1389         UnicodeString text;
1390         text.setTo(temp, u_strlen(temp));
1391         u_unescape(search.pattern, temp, 128);
1392         UnicodeString pattern;
1393         pattern.setTo(temp, u_strlen(temp));
1394 
1395         StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1396                                                  NULL, status);
1397         if (U_FAILURE(status)) {
1398             errln("Error opening string search %s", u_errorName(status));
1399             if (strsrch != NULL) {
1400                 delete strsrch;
1401             }
1402             return;
1403         }
1404 
1405         int size = 0;
1406         while (search.offset[size] != -1) {
1407             size ++;
1408         }
1409 
1410         if (strsrch->first(status) != search.offset[0] || U_FAILURE(status)) {
1411             errln("Error getting first match");
1412         }
1413         if (strsrch->last(status) != search.offset[size -1] ||
1414             U_FAILURE(status)) {
1415             errln("Error getting last match");
1416         }
1417 
1418         int index = 0;
1419         while (index < size) {
1420             if (index + 2 < size) {
1421                 if (strsrch->following(search.offset[index + 2] - 1, status)
1422                          != search.offset[index + 2] || U_FAILURE(status)) {
1423                     errln("Error getting following match at index %d",
1424                           search.offset[index + 2] - 1);
1425                 }
1426             }
1427             if (index + 1 < size) {
1428                 if (strsrch->preceding(search.offset[index + 1] +
1429                                                 search.size[index + 1] + 1,
1430                                        status) != search.offset[index + 1] ||
1431                     U_FAILURE(status)) {
1432                     errln("Error getting preceeding match at index %d",
1433                           search.offset[index + 1] + 1);
1434                 }
1435             }
1436             index += 2;
1437         }
1438         status = U_ZERO_ERROR;
1439         if (strsrch->following(text.length(), status) != USEARCH_DONE) {
1440             errln("Error expecting out of bounds match");
1441         }
1442         if (strsrch->preceding(0, status) != USEARCH_DONE) {
1443             errln("Error expecting out of bounds match");
1444         }
1445         count ++;
1446         delete strsrch;
1447     }
1448 }
1449 
TestReset()1450 void StringSearchTest::TestReset()
1451 {
1452     UErrorCode     status  = U_ZERO_ERROR;
1453     UnicodeString  text("fish fish");
1454     UnicodeString  pattern("s");
1455     StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1456                                               status);
1457     if (U_FAILURE(status)) {
1458         errln("Error opening string search %s", u_errorName(status));
1459         if (strsrch != NULL) {
1460             delete strsrch;
1461         }
1462         return;
1463     }
1464     strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1465     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1466     strsrch->setOffset(9, status);
1467     if (U_FAILURE(status)) {
1468         errln("Error setting attributes and offsets");
1469     }
1470     else {
1471         strsrch->reset();
1472         if (strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF ||
1473             strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF ||
1474             strsrch->getOffset() != 0 || strsrch->getMatchedLength() != 0 ||
1475             strsrch->getMatchedStart() != USEARCH_DONE) {
1476             errln("Error resetting string search");
1477         }
1478         strsrch->previous(status);
1479         if (strsrch->getMatchedStart() != 7 ||
1480             strsrch->getMatchedLength() != 1) {
1481             errln("Error resetting string search\n");
1482         }
1483     }
1484     delete strsrch;
1485 }
1486 
TestSupplementary()1487 void StringSearchTest::TestSupplementary()
1488 {
1489     int count = 0;
1490     while (SUPPLEMENTARY[count].text != NULL) {
1491         if (!assertEqual(&SUPPLEMENTARY[count])) {
1492             errln("Error at test number %d", count);
1493         }
1494         count ++;
1495     }
1496 }
1497 
TestContraction()1498 void StringSearchTest::TestContraction()
1499 {
1500     UChar      temp[128];
1501     UErrorCode status = U_ZERO_ERROR;
1502 
1503     u_unescape(CONTRACTIONRULE, temp, 128);
1504     UnicodeString rules;
1505     rules.setTo(temp, u_strlen(temp));
1506     RuleBasedCollator *collator = new RuleBasedCollator(rules,
1507         getECollationStrength(UCOL_TERTIARY), UCOL_ON, status);
1508     if (U_FAILURE(status)) {
1509         errln("Error opening collator %s", u_errorName(status));
1510     }
1511     UnicodeString text("text");
1512     UnicodeString pattern("pattern");
1513     StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1514                                              status);
1515     if (U_FAILURE(status)) {
1516         errln("Error opening string search %s", u_errorName(status));
1517     }
1518 
1519     int count = 0;
1520     while (CONTRACTION[count].text != NULL) {
1521         u_unescape(CONTRACTION[count].text, temp, 128);
1522         text.setTo(temp, u_strlen(temp));
1523         u_unescape(CONTRACTION[count].pattern, temp, 128);
1524         pattern.setTo(temp, u_strlen(temp));
1525         strsrch->setText(text, status);
1526         strsrch->setPattern(pattern, status);
1527         if (!assertEqualWithStringSearch(strsrch, &CONTRACTION[count])) {
1528             errln("Error at test number %d", count);
1529         }
1530         count ++;
1531     }
1532     delete strsrch;
1533     delete collator;
1534 }
1535 
TestIgnorable()1536 void StringSearchTest::TestIgnorable()
1537 {
1538     UChar temp[128];
1539     u_unescape(IGNORABLERULE, temp, 128);
1540     UnicodeString rules;
1541     rules.setTo(temp, u_strlen(temp));
1542     UErrorCode status = U_ZERO_ERROR;
1543     int        count  = 0;
1544     RuleBasedCollator *collator = new RuleBasedCollator(rules,
1545                             getECollationStrength(IGNORABLE[count].strength),
1546                             UCOL_ON, status);
1547     if (U_FAILURE(status)) {
1548         errln("Error opening collator %s", u_errorName(status));
1549         return;
1550     }
1551     UnicodeString pattern("pattern");
1552     UnicodeString text("text");
1553     StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1554                                              status);
1555     if (U_FAILURE(status)) {
1556         errln("Error opening string search %s", u_errorName(status));
1557         delete collator;
1558         return;
1559     }
1560 
1561     while (IGNORABLE[count].text != NULL) {
1562         u_unescape(IGNORABLE[count].text, temp, 128);
1563         text.setTo(temp, u_strlen(temp));
1564         u_unescape(IGNORABLE[count].pattern, temp, 128);
1565         pattern.setTo(temp, u_strlen(temp));
1566         strsrch->setText(text, status);
1567         strsrch->setPattern(pattern, status);
1568         if (!assertEqualWithStringSearch(strsrch, &IGNORABLE[count])) {
1569             errln("Error at test number %d", count);
1570         }
1571         count ++;
1572     }
1573     delete strsrch;
1574     delete collator;
1575 }
1576 
TestDiacriticMatch()1577 void StringSearchTest::TestDiacriticMatch()
1578 {
1579 	UChar temp[128];
1580     UErrorCode status = U_ZERO_ERROR;
1581     int        count  = 0;
1582     RuleBasedCollator* coll = NULL;
1583     StringSearch *strsrch = NULL;
1584 
1585     UnicodeString pattern("pattern");
1586     UnicodeString text("text");
1587 
1588     const SearchData *search;
1589 
1590     search = &(DIACRITICMATCH[count]);
1591     while (search->text != NULL) {
1592    		coll = getCollator(search->collator);
1593     	coll->setStrength(getECollationStrength(search->strength));
1594     	strsrch = new StringSearch(pattern, text, coll, getBreakIterator(search->breaker), status);
1595     	if (U_FAILURE(status)) {
1596 	        errln("Error opening string search %s", u_errorName(status));
1597 	        return;
1598 	    }
1599         u_unescape(search->text, temp, 128);
1600         text.setTo(temp, u_strlen(temp));
1601         u_unescape(search->pattern, temp, 128);
1602         pattern.setTo(temp, u_strlen(temp));
1603         strsrch->setText(text, status);
1604         strsrch->setPattern(pattern, status);
1605         if (!assertEqualWithStringSearch(strsrch, search)) {
1606             errln("Error at test number %d", count);
1607         }
1608         search = &(DIACRITICMATCH[++count]);
1609         delete strsrch;
1610     }
1611 
1612 }
1613 
TestCanonical()1614 void StringSearchTest::TestCanonical()
1615 {
1616     int count = 0;
1617     while (BASICCANONICAL[count].text != NULL) {
1618         if (!assertCanonicalEqual(&BASICCANONICAL[count])) {
1619             errln("Error at test number %d", count);
1620         }
1621         count ++;
1622     }
1623 }
1624 
TestNormCanonical()1625 void StringSearchTest::TestNormCanonical()
1626 {
1627     UErrorCode status = U_ZERO_ERROR;
1628     m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
1629     int count = 0;
1630     while (NORMCANONICAL[count].text != NULL) {
1631         if (!assertCanonicalEqual(&NORMCANONICAL[count])) {
1632             errln("Error at test number %d", count);
1633         }
1634         count ++;
1635     }
1636     m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
1637 }
1638 
TestStrengthCanonical()1639 void StringSearchTest::TestStrengthCanonical()
1640 {
1641     int count = 0;
1642     while (STRENGTHCANONICAL[count].text != NULL) {
1643         if (!assertCanonicalEqual(&STRENGTHCANONICAL[count])) {
1644             errln("Error at test number %d", count);
1645         }
1646         count ++;
1647     }
1648 }
1649 
1650 #if !UCONFIG_NO_BREAK_ITERATION
1651 
TestBreakIteratorCanonical()1652 void StringSearchTest::TestBreakIteratorCanonical()
1653 {
1654     UErrorCode status = U_ZERO_ERROR;
1655     int        count  = 0;
1656 
1657     while (count < 4) {
1658         // special purposes for tests numbers 0-3
1659               UChar           temp[128];
1660         const SearchData     *search   = &(BREAKITERATORCANONICAL[count]);
1661 
1662         u_unescape(search->text, temp, 128);
1663         UnicodeString text;
1664         text.setTo(temp, u_strlen(temp));
1665         u_unescape(search->pattern, temp, 128);
1666         UnicodeString pattern;
1667         pattern.setTo(temp, u_strlen(temp));
1668         RuleBasedCollator *collator = getCollator(search->collator);
1669         collator->setStrength(getECollationStrength(search->strength));
1670 
1671         BreakIterator *breaker = getBreakIterator(search->breaker);
1672         StringSearch  *strsrch = new StringSearch(pattern, text, collator,
1673                                                   breaker, status);
1674         if (U_FAILURE(status)) {
1675             errln("Error creating string search data");
1676             return;
1677         }
1678         strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1679         if (U_FAILURE(status) ||
1680             strsrch->getBreakIterator() != breaker) {
1681             errln("Error setting break iterator");
1682             delete strsrch;
1683             return;
1684         }
1685         if (!assertEqualWithStringSearch(strsrch, search)) {
1686             collator->setStrength(getECollationStrength(UCOL_TERTIARY));
1687             delete strsrch;
1688             return;
1689         }
1690         search  = &(BREAKITERATOREXACT[count + 1]);
1691         breaker = getBreakIterator(search->breaker);
1692         if (breaker == NULL) {
1693             errln("Error creating BreakIterator");
1694             return;
1695         }
1696         breaker->setText(strsrch->getText());
1697         strsrch->setBreakIterator(breaker, status);
1698         if (U_FAILURE(status) || strsrch->getBreakIterator() != breaker) {
1699             errln("Error setting break iterator");
1700             delete strsrch;
1701             return;
1702         }
1703         strsrch->reset();
1704         strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1705         if (!assertEqualWithStringSearch(strsrch, search)) {
1706              errln("Error at test number %d", count);
1707              return;
1708         }
1709         delete strsrch;
1710         count += 2;
1711     }
1712     count = 0;
1713     while (BREAKITERATORCANONICAL[count].text != NULL) {
1714          if (!assertEqual(&BREAKITERATORCANONICAL[count])) {
1715              errln("Error at test number %d", count);
1716              return;
1717          }
1718          count ++;
1719     }
1720 }
1721 
1722 #endif
1723 
TestVariableCanonical()1724 void StringSearchTest::TestVariableCanonical()
1725 {
1726     int count = 0;
1727     UErrorCode status = U_ZERO_ERROR;
1728     m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
1729     if (U_FAILURE(status)) {
1730         errln("Error setting collation alternate attribute %s",
1731               u_errorName(status));
1732     }
1733     while (VARIABLE[count].text != NULL) {
1734         logln("variable %d", count);
1735         if (!assertCanonicalEqual(&VARIABLE[count])) {
1736             errln("Error at test number %d", count);
1737         }
1738         count ++;
1739     }
1740     m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
1741                            status);
1742 }
1743 
TestOverlapCanonical()1744 void StringSearchTest::TestOverlapCanonical()
1745 {
1746     int count = 0;
1747     while (OVERLAPCANONICAL[count].text != NULL) {
1748         if (!assertEqualWithAttribute(&OVERLAPCANONICAL[count], USEARCH_ON,
1749                                       USEARCH_ON)) {
1750             errln("Error at overlap test number %d", count);
1751         }
1752         count ++;
1753     }
1754     count = 0;
1755     while (NONOVERLAP[count].text != NULL) {
1756         if (!assertCanonicalEqual(&NONOVERLAPCANONICAL[count])) {
1757             errln("Error at non overlap test number %d", count);
1758         }
1759         count ++;
1760     }
1761 
1762     count = 0;
1763     while (count < 1) {
1764               UChar       temp[128];
1765         const SearchData *search = &(OVERLAPCANONICAL[count]);
1766               UErrorCode  status = U_ZERO_ERROR;
1767 
1768         u_unescape(search->text, temp, 128);
1769         UnicodeString text;
1770         text.setTo(temp, u_strlen(temp));
1771         u_unescape(search->pattern, temp, 128);
1772         UnicodeString pattern;
1773         pattern.setTo(temp, u_strlen(temp));
1774         RuleBasedCollator *collator = getCollator(search->collator);
1775         StringSearch *strsrch = new StringSearch(pattern, text, collator,
1776                                                  NULL, status);
1777         strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1778         strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1779         if (U_FAILURE(status) ||
1780             strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
1781             errln("Error setting overlap option");
1782         }
1783         if (!assertEqualWithStringSearch(strsrch, search)) {
1784             delete strsrch;
1785             return;
1786         }
1787         search = &(NONOVERLAPCANONICAL[count]);
1788         strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
1789         if (U_FAILURE(status) ||
1790             strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1791             errln("Error setting overlap option");
1792         }
1793         strsrch->reset();
1794         if (!assertEqualWithStringSearch(strsrch, search)) {
1795             delete strsrch;
1796             errln("Error at test number %d", count);
1797          }
1798 
1799         count ++;
1800         delete strsrch;
1801     }
1802 }
1803 
TestCollatorCanonical()1804 void StringSearchTest::TestCollatorCanonical()
1805 {
1806     /* test collator that thinks "o" and "p" are the same thing */
1807     UChar temp[128];
1808     u_unescape(COLLATORCANONICAL[0].text, temp, 128);
1809     UnicodeString text;
1810     text.setTo(temp, u_strlen(temp));
1811     u_unescape(COLLATORCANONICAL[0].pattern, temp, 128);
1812     UnicodeString pattern;
1813     pattern.setTo(temp, u_strlen(temp));
1814 
1815     UErrorCode    status  = U_ZERO_ERROR;
1816     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1817                                              NULL, status);
1818     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1819     if (U_FAILURE(status)) {
1820         errln("Error opening string search %s", u_errorName(status));
1821     }
1822     if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1823         delete strsrch;
1824         return;
1825     }
1826 
1827     u_unescape(TESTCOLLATORRULE, temp, 128);
1828     UnicodeString rules;
1829     rules.setTo(temp, u_strlen(temp));
1830     RuleBasedCollator *tailored = new RuleBasedCollator(rules,
1831         getECollationStrength(COLLATORCANONICAL[1].strength),
1832         UCOL_ON, status);
1833 
1834     if (U_FAILURE(status)) {
1835         errln("Error opening rule based collator %s", u_errorName(status));
1836     }
1837 
1838     strsrch->setCollator(tailored, status);
1839     if (U_FAILURE(status) || *(strsrch->getCollator()) != *tailored) {
1840         errln("Error setting rule based collator");
1841     }
1842     strsrch->reset();
1843     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1844     if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[1])) {
1845         delete strsrch;
1846         if (tailored != NULL) {
1847             delete tailored;
1848         }
1849 
1850         return;
1851     }
1852 
1853     strsrch->setCollator(m_en_us_, status);
1854     strsrch->reset();
1855     if (U_FAILURE(status) || *(strsrch->getCollator()) != *m_en_us_) {
1856         errln("Error setting rule based collator");
1857     }
1858     if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1859     }
1860     delete strsrch;
1861     if (tailored != NULL) {
1862         delete tailored;
1863     }
1864 }
1865 
TestPatternCanonical()1866 void StringSearchTest::TestPatternCanonical()
1867 {
1868 
1869     UChar temp[128];
1870 
1871     u_unescape(PATTERNCANONICAL[0].text, temp, 128);
1872     UnicodeString text;
1873     text.setTo(temp, u_strlen(temp));
1874     u_unescape(PATTERNCANONICAL[0].pattern, temp, 128);
1875     UnicodeString pattern;
1876     pattern.setTo(temp, u_strlen(temp));
1877 
1878     m_en_us_->setStrength(
1879                       getECollationStrength(PATTERNCANONICAL[0].strength));
1880 
1881     UErrorCode    status  = U_ZERO_ERROR;
1882     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1883                                              status);
1884     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1885     if (U_FAILURE(status)) {
1886         errln("Error opening string search %s", u_errorName(status));
1887         goto ENDTESTPATTERN;
1888     }
1889     if (pattern != strsrch->getPattern()) {
1890         errln("Error setting pattern");
1891     }
1892     if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1893         goto ENDTESTPATTERN;
1894     }
1895 
1896     u_unescape(PATTERNCANONICAL[1].pattern, temp, 128);
1897     pattern.setTo(temp, u_strlen(temp));
1898     strsrch->setPattern(pattern, status);
1899     if (pattern != strsrch->getPattern()) {
1900         errln("Error setting pattern");
1901         goto ENDTESTPATTERN;
1902     }
1903     strsrch->reset();
1904     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1905     if (U_FAILURE(status)) {
1906         errln("Error setting pattern %s", u_errorName(status));
1907     }
1908     if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[1])) {
1909         goto ENDTESTPATTERN;
1910     }
1911 
1912     u_unescape(PATTERNCANONICAL[0].pattern, temp, 128);
1913     pattern.setTo(temp, u_strlen(temp));
1914     strsrch->setPattern(pattern, status);
1915     if (pattern != strsrch->getPattern()) {
1916         errln("Error setting pattern");
1917         goto ENDTESTPATTERN;
1918     }
1919     strsrch->reset();
1920     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1921     if (U_FAILURE(status)) {
1922         errln("Error setting pattern %s", u_errorName(status));
1923     }
1924     if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1925         goto ENDTESTPATTERN;
1926     }
1927 ENDTESTPATTERN:
1928     m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1929     if (strsrch != NULL) {
1930         delete strsrch;
1931     }
1932 }
1933 
TestTextCanonical()1934 void StringSearchTest::TestTextCanonical()
1935 {
1936     UChar temp[128];
1937     u_unescape(TEXTCANONICAL[0].text, temp, 128);
1938     UnicodeString text;
1939     text.setTo(temp, u_strlen(temp));
1940     u_unescape(TEXTCANONICAL[0].pattern, temp, 128);
1941     UnicodeString pattern;
1942     pattern.setTo(temp, u_strlen(temp));
1943 
1944     UErrorCode    status  = U_ZERO_ERROR;
1945     StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1946                                              status);
1947     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1948 
1949     if (U_FAILURE(status)) {
1950         errln("Error opening string search %s", u_errorName(status));
1951         goto ENDTESTPATTERN;
1952     }
1953     if (text != strsrch->getText()) {
1954         errln("Error setting text");
1955     }
1956     if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1957         goto ENDTESTPATTERN;
1958     }
1959 
1960     u_unescape(TEXTCANONICAL[1].text, temp, 128);
1961     text.setTo(temp, u_strlen(temp));
1962     strsrch->setText(text, status);
1963     if (text != strsrch->getText()) {
1964         errln("Error setting text");
1965         goto ENDTESTPATTERN;
1966     }
1967     if (U_FAILURE(status)) {
1968         errln("Error setting text %s", u_errorName(status));
1969     }
1970     if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[1])) {
1971         goto ENDTESTPATTERN;
1972     }
1973 
1974     u_unescape(TEXTCANONICAL[0].text, temp, 128);
1975     text.setTo(temp, u_strlen(temp));
1976     strsrch->setText(text, status);
1977     if (text != strsrch->getText()) {
1978         errln("Error setting text");
1979         goto ENDTESTPATTERN;
1980     }
1981     if (U_FAILURE(status)) {
1982         errln("Error setting pattern %s", u_errorName(status));
1983     }
1984     if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1985         goto ENDTESTPATTERN;
1986     }
1987 ENDTESTPATTERN:
1988     if (strsrch != NULL) {
1989         delete strsrch;
1990     }
1991 }
1992 
TestCompositeBoundariesCanonical()1993 void StringSearchTest::TestCompositeBoundariesCanonical()
1994 {
1995     int count = 0;
1996     while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
1997         logln("composite %d", count);
1998         if (!assertCanonicalEqual(&COMPOSITEBOUNDARIESCANONICAL[count])) {
1999             errln("Error at test number %d", count);
2000         }
2001         count ++;
2002     }
2003 }
2004 
TestGetSetOffsetCanonical()2005 void StringSearchTest::TestGetSetOffsetCanonical()
2006 {
2007 
2008     UErrorCode     status  = U_ZERO_ERROR;
2009     UnicodeString  text("text");
2010     UnicodeString  pattern("pattern");
2011     StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
2012                                               status);
2013     Collator *collator = strsrch->getCollator();
2014 
2015     collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
2016 
2017     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
2018     /* testing out of bounds error */
2019     strsrch->setOffset(-1, status);
2020     if (U_SUCCESS(status)) {
2021         errln("Error expecting set offset error");
2022     }
2023     strsrch->setOffset(128, status);
2024     if (U_SUCCESS(status)) {
2025         errln("Error expecting set offset error");
2026     }
2027     int   index   = 0;
2028     UChar temp[128];
2029     while (BASICCANONICAL[index].text != NULL) {
2030         SearchData  search      = BASICCANONICAL[index ++];
2031         if (BASICCANONICAL[index].text == NULL) {
2032             /* skip the last one */
2033             break;
2034         }
2035 
2036         u_unescape(search.text, temp, 128);
2037         text.setTo(temp, u_strlen(temp));
2038         u_unescape(search.pattern, temp, 128);
2039         pattern.setTo(temp, u_strlen(temp));
2040 
2041         UErrorCode  status      = U_ZERO_ERROR;
2042         strsrch->setText(text, status);
2043 
2044         strsrch->setPattern(pattern, status);
2045 
2046         int         count       = 0;
2047         int32_t matchindex  = search.offset[count];
2048         while (U_SUCCESS(status) && matchindex >= 0) {
2049             int32_t matchlength = search.size[count];
2050             strsrch->next(status);
2051             if (matchindex != strsrch->getMatchedStart() ||
2052                 matchlength != strsrch->getMatchedLength()) {
2053                 char *str = toCharString(strsrch->getText());
2054                 errln("Text: %s", str);
2055                 str = toCharString(strsrch->getPattern());
2056                 errln("Pattern: %s", str);
2057                 errln("Error match found at %d %d",
2058                       strsrch->getMatchedStart(),
2059                       strsrch->getMatchedLength());
2060                 goto bail;
2061             }
2062             matchindex = search.offset[count + 1] == -1 ? -1 :
2063                          search.offset[count + 2];
2064             if (search.offset[count + 1] != -1) {
2065                 strsrch->setOffset(search.offset[count + 1] + 1, status);
2066                 if (strsrch->getOffset() != search.offset[count + 1] + 1) {
2067                     errln("Error setting offset");
2068                     goto bail;
2069                 }
2070             }
2071 
2072             count += 2;
2073         }
2074         strsrch->next(status);
2075         if (strsrch->getMatchedStart() != USEARCH_DONE) {
2076             char *str = toCharString(strsrch->getText());
2077             errln("Text: %s", str);
2078             str = toCharString(strsrch->getPattern());
2079             errln("Pattern: %s", str);
2080             errln("Error match found at %d %d", strsrch->getMatchedStart(),
2081                    strsrch->getMatchedLength());
2082             goto bail;
2083         }
2084     }
2085 
2086 bail:
2087     collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
2088     delete strsrch;
2089 }
2090 
TestSupplementaryCanonical()2091 void StringSearchTest::TestSupplementaryCanonical()
2092 {
2093     int count = 0;
2094     while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
2095         if (!assertCanonicalEqual(&SUPPLEMENTARYCANONICAL[count])) {
2096             errln("Error at test number %d", count);
2097         }
2098         count ++;
2099     }
2100 }
2101 
TestContractionCanonical()2102 void StringSearchTest::TestContractionCanonical()
2103 {
2104     UChar          temp[128];
2105 
2106     u_unescape(CONTRACTIONRULE, temp, 128);
2107     UnicodeString rules;
2108     rules.setTo(temp, u_strlen(temp));
2109 
2110     UErrorCode         status   = U_ZERO_ERROR;
2111     RuleBasedCollator *collator = new RuleBasedCollator(rules,
2112         getECollationStrength(UCOL_TERTIARY), UCOL_ON, status);
2113     if (U_FAILURE(status)) {
2114         errln("Error opening collator %s", u_errorName(status));
2115     }
2116     UnicodeString text("text");
2117     UnicodeString pattern("pattern");
2118     StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
2119                                              status);
2120     strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
2121     if (U_FAILURE(status)) {
2122         errln("Error opening string search %s", u_errorName(status));
2123     }
2124 
2125     int count = 0;
2126     while (CONTRACTIONCANONICAL[count].text != NULL) {
2127         u_unescape(CONTRACTIONCANONICAL[count].text, temp, 128);
2128         text.setTo(temp, u_strlen(temp));
2129         u_unescape(CONTRACTIONCANONICAL[count].pattern, temp, 128);
2130         pattern.setTo(temp, u_strlen(temp));
2131         strsrch->setText(text, status);
2132         strsrch->setPattern(pattern, status);
2133         if (!assertEqualWithStringSearch(strsrch,
2134                                              &CONTRACTIONCANONICAL[count])) {
2135             errln("Error at test number %d", count);
2136         }
2137         count ++;
2138     }
2139     delete strsrch;
2140     delete collator;
2141 }
2142 
TestUClassID()2143 void StringSearchTest::TestUClassID()
2144 {
2145     char id = *((char *)StringSearch::getStaticClassID());
2146     if (id != 0) {
2147         errln("Static class id for StringSearch should be 0");
2148     }
2149     UErrorCode     status    = U_ZERO_ERROR;
2150     UnicodeString  text("text");
2151     UnicodeString  pattern("pattern");
2152     StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
2153                                               status);
2154     id = *((char *)strsrch->getDynamicClassID());
2155     if (id != 0) {
2156         errln("Dynamic class id for StringSearch should be 0");
2157     }
2158     delete strsrch;
2159 }
2160 
2161 class TestSearch : public SearchIterator
2162 {
2163 public:
2164     TestSearch(const TestSearch &obj);
2165     TestSearch(const UnicodeString &text,
2166                BreakIterator *breakiter,
2167                const UnicodeString &pattern);
2168     ~TestSearch();
2169 
2170     void        setOffset(int32_t position, UErrorCode &status);
2171     int32_t     getOffset() const;
2172     SearchIterator* safeClone() const;
2173 
2174 
2175     /**
2176      * ICU "poor man's RTTI", returns a UClassID for the actual class.
2177      *
2178      * @draft ICU 2.2
2179      */
getDynamicClassID() const2180     virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
2181 
2182     /**
2183      * ICU "poor man's RTTI", returns a UClassID for this class.
2184      *
2185      * @draft ICU 2.2
2186      */
getStaticClassID()2187     static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
2188 
2189     UBool operator!=(const TestSearch &that) const;
2190 
2191     UnicodeString m_pattern_;
2192 
2193 protected:
2194     int32_t      handleNext(int32_t position, UErrorCode &status);
2195     int32_t      handlePrev(int32_t position, UErrorCode &status);
2196     TestSearch & operator=(const TestSearch &that);
2197 
2198 private:
2199 
2200     /**
2201      * The address of this static class variable serves as this class's ID
2202      * for ICU "poor man's RTTI".
2203      */
2204     static const char fgClassID;
2205     uint32_t m_offset_;
2206 };
2207 
2208 const char TestSearch::fgClassID=0;
2209 
TestSearch(const TestSearch & obj)2210 TestSearch::TestSearch(const TestSearch &obj) : SearchIterator(obj)
2211 {
2212     m_offset_ = obj.m_offset_;
2213     m_pattern_ = obj.m_pattern_;
2214 }
2215 
TestSearch(const UnicodeString & text,BreakIterator * breakiter,const UnicodeString & pattern)2216 TestSearch::TestSearch(const UnicodeString &text,
2217                        BreakIterator *breakiter,
2218                        const UnicodeString &pattern) : SearchIterator()
2219 {
2220     m_breakiterator_ = breakiter;
2221     m_pattern_ = pattern;
2222     m_text_ = text;
2223     m_offset_ = 0;
2224     m_pattern_ = pattern;
2225 }
2226 
~TestSearch()2227 TestSearch::~TestSearch()
2228 {
2229 }
2230 
2231 
setOffset(int32_t position,UErrorCode & status)2232 void TestSearch::setOffset(int32_t position, UErrorCode &status)
2233 {
2234     if (position >= 0 && position <= m_text_.length()) {
2235         m_offset_ = position;
2236     }
2237     else {
2238         status = U_INDEX_OUTOFBOUNDS_ERROR;
2239     }
2240 }
2241 
getOffset() const2242 int32_t TestSearch::getOffset() const
2243 {
2244     return m_offset_;
2245 }
2246 
safeClone() const2247 SearchIterator * TestSearch::safeClone() const
2248 {
2249     return new TestSearch(m_text_, m_breakiterator_, m_pattern_);
2250 }
2251 
operator !=(const TestSearch & that) const2252 UBool TestSearch::operator!=(const TestSearch &that) const
2253 {
2254     if (SearchIterator::operator !=(that)) {
2255         return FALSE;
2256     }
2257     return m_offset_ != that.m_offset_ || m_pattern_ != that.m_pattern_;
2258 }
2259 
handleNext(int32_t start,UErrorCode & status)2260 int32_t TestSearch::handleNext(int32_t start, UErrorCode &status)
2261 {
2262   if(U_SUCCESS(status)) {
2263     int match = m_text_.indexOf(m_pattern_, start);
2264     if (match < 0) {
2265         m_offset_ = m_text_.length();
2266         setMatchStart(m_offset_);
2267         setMatchLength(0);
2268         return USEARCH_DONE;
2269     }
2270     setMatchStart(match);
2271     m_offset_ = match;
2272     setMatchLength(m_pattern_.length());
2273     return match;
2274   } else {
2275     return USEARCH_DONE;
2276   }
2277 }
2278 
handlePrev(int32_t start,UErrorCode & status)2279 int32_t TestSearch::handlePrev(int32_t start, UErrorCode &status)
2280 {
2281   if(U_SUCCESS(status)) {
2282     int match = m_text_.lastIndexOf(m_pattern_, 0, start);
2283     if (match < 0) {
2284         m_offset_ = 0;
2285         setMatchStart(m_offset_);
2286         setMatchLength(0);
2287         return USEARCH_DONE;
2288     }
2289     setMatchStart(match);
2290     m_offset_ = match;
2291     setMatchLength(m_pattern_.length());
2292     return match;
2293   } else {
2294     return USEARCH_DONE;
2295   }
2296 }
2297 
operator =(const TestSearch & that)2298 TestSearch & TestSearch::operator=(const TestSearch &that)
2299 {
2300     SearchIterator::operator=(that);
2301     m_offset_ = that.m_offset_;
2302     m_pattern_ = that.m_pattern_;
2303     return *this;
2304 }
2305 
TestSubclass()2306 void StringSearchTest::TestSubclass()
2307 {
2308     UnicodeString text("abc abcd abc");
2309     UnicodeString pattern("abc");
2310     TestSearch search(text, NULL, pattern);
2311     TestSearch search2(search);
2312     int expected[] = {0, 4, 9};
2313     UErrorCode status = U_ZERO_ERROR;
2314     int i;
2315     StringCharacterIterator chariter(text);
2316 
2317     search.setText(text, status);
2318     if (search.getText() != search2.getText()) {
2319         errln("Error setting text");
2320     }
2321 
2322     search.setText(chariter, status);
2323     if (search.getText() != search2.getText()) {
2324         errln("Error setting text");
2325     }
2326 
2327     search.reset();
2328     // comparing constructors
2329 
2330     for (i = 0; i < (int)(sizeof(expected) / sizeof(expected[0])); i ++) {
2331         if (search.next(status) != expected[i]) {
2332             errln("Error getting next match");
2333         }
2334         if (search.getMatchedLength() != search.m_pattern_.length()) {
2335             errln("Error getting next match length");
2336         }
2337     }
2338     if (search.next(status) != USEARCH_DONE) {
2339         errln("Error should have reached the end of the iteration");
2340     }
2341     for (i = sizeof(expected) / sizeof(expected[0]) - 1; i >= 0; i --) {
2342         if (search.previous(status) != expected[i]) {
2343             errln("Error getting previous match");
2344         }
2345         if (search.getMatchedLength() != search.m_pattern_.length()) {
2346             errln("Error getting previous match length");
2347         }
2348     }
2349     if (search.previous(status) != USEARCH_DONE) {
2350         errln("Error should have reached the start of the iteration");
2351     }
2352 }
2353 
2354 class StubSearchIterator:public SearchIterator{
2355 public:
StubSearchIterator()2356     StubSearchIterator(){}
setOffset(int32_t,UErrorCode &)2357     virtual void setOffset(int32_t , UErrorCode &) {};
getOffset(void) const2358     virtual int32_t getOffset(void) const {return 0;};
safeClone(void) const2359     virtual SearchIterator* safeClone(void) const {return NULL;};
handleNext(int32_t,UErrorCode &)2360     virtual int32_t handleNext(int32_t , UErrorCode &){return 0;};
handlePrev(int32_t,UErrorCode &)2361     virtual int32_t handlePrev(int32_t , UErrorCode &) {return 0;};
getDynamicClassID() const2362     virtual UClassID getDynamicClassID() const {
2363         static char classID = 0;
2364         return (UClassID)&classID;
2365     }
2366 };
2367 
TestCoverage()2368 void StringSearchTest::TestCoverage(){
2369     StubSearchIterator stub1, stub2;
2370     UErrorCode status = U_ZERO_ERROR;
2371 
2372     if (stub1 != stub2){
2373         errln("new StubSearchIterator should be equal");
2374     }
2375 
2376     stub2.setText(UnicodeString("ABC"), status);
2377     if (U_FAILURE(status)) {
2378         errln("Error: SearchIterator::SetText");
2379     }
2380 
2381     stub1 = stub2;
2382     if (stub1 != stub2){
2383         errln("SearchIterator::operator =  assigned object should be equal");
2384     }
2385 }
2386 
2387 #endif /* !UCONFIG_NO_BREAK_ITERATION */
2388 
2389 #endif /* #if !UCONFIG_NO_COLLATION */
2390