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#if !UCONFIG_NO_BREAK_ITERATION
13#include "../cintltst/usrchdat.c"
14#endif
15#include "unicode/stsearch.h"
16#include "unicode/ustring.h"
17#include "unicode/schriter.h"
18#include <string.h>
19#include <stdio.h>
20
21// private definitions -----------------------------------------------------
22
23#define CASE(id,test)                 \
24    case id:                          \
25        name = #test;                 \
26        if (exec) {                   \
27            logln(#test "---");       \
28            logln((UnicodeString)""); \
29            if(areBroken) {           \
30                  dataerrln(__FILE__ " cannot test - failed to create collator.");  \
31            } else {                  \
32                test();               \
33            }                         \
34        }                             \
35        break;
36
37// public contructors and destructors --------------------------------------
38
39StringSearchTest::StringSearchTest()
40#if !UCONFIG_NO_BREAK_ITERATION
41:
42    m_en_wordbreaker_(NULL), m_en_characterbreaker_(NULL)
43#endif
44{
45#if !UCONFIG_NO_BREAK_ITERATION
46    UErrorCode    status = U_ZERO_ERROR;
47
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)) {
53      delete m_en_us_;
54      delete m_fr_fr_;
55      delete m_de_;
56      delete m_es_;
57      m_en_us_ = 0;
58      m_fr_fr_ = 0;
59      m_de_ = 0;
60      m_es_ = 0;
61      errln("Collator creation failed with %s", u_errorName(status));
62      return;
63    }
64
65
66    UnicodeString rules;
67    rules.setTo(((RuleBasedCollator *)m_de_)->getRules());
68    UChar extrarules[128];
69    u_unescape(EXTRACOLLATIONRULE, extrarules, 128);
70    rules.append(extrarules, u_strlen(extrarules));
71    delete m_de_;
72
73    m_de_ = new RuleBasedCollator(rules, status);
74
75    rules.setTo(((RuleBasedCollator *)m_es_)->getRules());
76    rules.append(extrarules, u_strlen(extrarules));
77
78    delete m_es_;
79
80    m_es_ = new RuleBasedCollator(rules, status);
81
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);
87#endif
88#endif
89}
90
91StringSearchTest::~StringSearchTest()
92{
93#if !UCONFIG_NO_BREAK_ITERATION
94    delete m_en_us_;
95    delete m_fr_fr_;
96    delete m_de_;
97    delete m_es_;
98#if !UCONFIG_NO_BREAK_ITERATION
99    delete m_en_wordbreaker_;
100    delete m_en_characterbreaker_;
101#endif
102#endif
103}
104
105// public methods ----------------------------------------------------------
106
107void StringSearchTest::runIndexedTest(int32_t index, UBool exec,
108                                      const char* &name, char* )
109{
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) {
115        areBroken = TRUE;
116    }
117
118    switch (index) {
119#if !UCONFIG_NO_FILE_IO
120        CASE(0, TestOpenClose)
121#endif
122        CASE(1, TestInitialization)
123        CASE(2, TestBasic)
124        CASE(3, TestNormExact)
125        CASE(4, TestStrength)
126#if UCONFIG_NO_BREAK_ITERATION
127    case 5:
128        name = "TestBreakIterator";
129        break;
130#else
131        CASE(5, TestBreakIterator)
132#endif
133        CASE(6, TestVariable)
134        CASE(7, TestOverlap)
135        CASE(8, TestCollator)
136        CASE(9, TestPattern)
137        CASE(10, TestText)
138        CASE(11, TestCompositeBoundaries)
139        CASE(12, TestGetSetOffset)
140        CASE(13, TestGetSetAttribute)
141        CASE(14, TestGetMatch)
142        CASE(15, TestSetMatch)
143        CASE(16, TestReset)
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
151    case 23:
152        name = "TestBreakIteratorCanonical";
153        break;
154#else
155        CASE(23, TestBreakIteratorCanonical)
156#endif
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;
171    }
172#else
173    name="";
174#endif
175}
176
177#if !UCONFIG_NO_BREAK_ITERATION
178// private methods ------------------------------------------------------
179
180RuleBasedCollator * StringSearchTest::getCollator(const char *collator)
181{
182    if (collator == NULL) {
183        return m_en_us_;
184    }
185    if (strcmp(collator, "fr") == 0) {
186        return m_fr_fr_;
187    }
188    else if (strcmp(collator, "de") == 0) {
189        return m_de_;
190    }
191    else if (strcmp(collator, "es") == 0) {
192        return m_es_;
193    }
194    else {
195        return m_en_us_;
196    }
197}
198
199BreakIterator * StringSearchTest::getBreakIterator(const char *breaker)
200{
201#if UCONFIG_NO_BREAK_ITERATION
202    return NULL;
203#else
204    if (breaker == NULL) {
205        return NULL;
206    }
207    if (strcmp(breaker, "wordbreaker") == 0) {
208        return m_en_wordbreaker_;
209    }
210    else {
211        return m_en_characterbreaker_;
212    }
213#endif
214}
215
216char * StringSearchTest::toCharString(const UnicodeString &text)
217{
218    static char   result[1024];
219           int    index  = 0;
220           int    count  = 0;
221           int    length = text.length();
222
223    for (; count < length; count ++) {
224        UChar ch = text[count];
225        if (ch >= 0x20 && ch <= 0x7e) {
226            result[index ++] = (char)ch;
227        }
228        else {
229            sprintf(result+index, "\\u%04x", ch);
230            index += 6; /* \uxxxx */
231        }
232    }
233    result[index] = 0;
234
235    return result;
236}
237
238Collator::ECollationStrength StringSearchTest::getECollationStrength(
239                                    const UCollationStrength &strength) const
240{
241  switch (strength)
242  {
243  case UCOL_PRIMARY :
244    return Collator::PRIMARY;
245  case UCOL_SECONDARY :
246    return Collator::SECONDARY;
247  case UCOL_TERTIARY :
248    return Collator::TERTIARY;
249  default :
250    return Collator::IDENTICAL;
251  }
252}
253
254UBool StringSearchTest::assertEqualWithStringSearch(StringSearch *strsrch,
255                                                    const SearchData *search)
256{
257    int           count       = 0;
258    UErrorCode    status      = U_ZERO_ERROR;
259    int32_t   matchindex  = search->offset[count];
260    UnicodeString matchtext;
261
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));
265        return FALSE;
266    }
267
268    if (strsrch->getMatchedStart() != USEARCH_DONE ||
269        strsrch->getMatchedLength() != 0) {
270        errln("Error with the initialization of match start and length");
271    }
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);
285            return FALSE;
286        }
287        count ++;
288
289        strsrch->getMatchedText(matchtext);
290
291        if (U_FAILURE(status) ||
292            strsrch->getText().compareBetween(matchindex,
293                                              matchindex + matchlength,
294                                              matchtext, 0,
295                                              matchtext.length())) {
296            errln("Error getting following matched text");
297        }
298
299        matchindex = search->offset[count];
300    }
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());
310            return FALSE;
311    }
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());
326            return FALSE;
327        }
328
329        strsrch->getMatchedText(matchtext);
330
331        if (U_FAILURE(status) ||
332            strsrch->getText().compareBetween(matchindex,
333                                              matchindex + matchlength,
334                                              matchtext, 0,
335                                              matchtext.length())) {
336            errln("Error getting following matched text");
337        }
338
339        matchindex = count > 0 ? search->offset[count - 1] : -1;
340        count --;
341    }
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());
351            return FALSE;
352    }
353    strsrch->setAttribute(USEARCH_ELEMENT_COMPARISON, USEARCH_STANDARD_ELEMENT_COMPARISON, status);
354    return TRUE;
355}
356
357UBool StringSearchTest::assertEqual(const SearchData *search)
358{
359    UErrorCode     status   = U_ZERO_ERROR;
360
361    Collator      *collator = getCollator(search->collator);
362    BreakIterator *breaker  = getBreakIterator(search->breaker);
363    StringSearch  *strsrch, *strsrch2;
364    UChar          temp[128];
365
366#if UCONFIG_NO_BREAK_ITERATION
367    if(search->breaker) {
368      return TRUE; /* skip test */
369    }
370#endif
371    u_unescape(search->text, temp, 128);
372    UnicodeString text;
373    text.setTo(temp);
374    u_unescape(search->pattern, temp, 128);
375    UnicodeString  pattern;
376    pattern.setTo(temp);
377
378#if !UCONFIG_NO_BREAK_ITERATION
379    if (breaker != NULL) {
380        breaker->setText(text);
381    }
382#endif
383    collator->setStrength(getECollationStrength(search->strength));
384    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
385                               breaker, status);
386    if (U_FAILURE(status)) {
387        errln("Error opening string search %s", u_errorName(status));
388        return FALSE;
389    }
390
391    if (!assertEqualWithStringSearch(strsrch, search)) {
392        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
393        delete strsrch;
394        return FALSE;
395    }
396
397
398    strsrch2 = strsrch->clone();
399    if( strsrch2 == strsrch || *strsrch2 != *strsrch ||
400        !assertEqualWithStringSearch(strsrch2, search)
401    ) {
402        infoln("failure with StringSearch.clone()");
403        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
404        delete strsrch;
405        delete strsrch2;
406        return FALSE;
407    }
408    delete strsrch2;
409
410    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
411    delete strsrch;
412    return TRUE;
413}
414
415UBool StringSearchTest::assertCanonicalEqual(const SearchData *search)
416{
417    UErrorCode     status   = U_ZERO_ERROR;
418    Collator      *collator = getCollator(search->collator);
419    BreakIterator *breaker  = getBreakIterator(search->breaker);
420    StringSearch  *strsrch;
421    UChar          temp[128];
422    UBool          result = TRUE;
423
424#if UCONFIG_NO_BREAK_ITERATION
425    if(search->breaker) {
426      return TRUE; /* skip test */
427    }
428#endif
429
430    u_unescape(search->text, temp, 128);
431    UnicodeString text;
432    text.setTo(temp);
433    u_unescape(search->pattern, temp, 128);
434    UnicodeString  pattern;
435    pattern.setTo(temp);
436
437#if !UCONFIG_NO_BREAK_ITERATION
438    if (breaker != NULL) {
439        breaker->setText(text);
440    }
441#endif
442    collator->setStrength(getECollationStrength(search->strength));
443    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
444    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
445                               breaker, status);
446    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
447    if (U_FAILURE(status)) {
448        errln("Error opening string search %s", u_errorName(status));
449        result = FALSE;
450        goto bail;
451    }
452
453    if (!assertEqualWithStringSearch(strsrch, search)) {
454        result = FALSE;
455        goto bail;
456    }
457
458bail:
459    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
460    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
461    delete strsrch;
462
463    return result;
464}
465
466UBool StringSearchTest::assertEqualWithAttribute(const SearchData *search,
467                                            USearchAttributeValue canonical,
468                                            USearchAttributeValue overlap)
469{
470    UErrorCode     status   = U_ZERO_ERROR;
471    Collator      *collator = getCollator(search->collator);
472    BreakIterator *breaker  = getBreakIterator(search->breaker);
473    StringSearch  *strsrch;
474    UChar          temp[128];
475
476
477#if UCONFIG_NO_BREAK_ITERATION
478    if(search->breaker) {
479      return TRUE; /* skip test */
480    }
481#endif
482
483    u_unescape(search->text, temp, 128);
484    UnicodeString text;
485    text.setTo(temp);
486    u_unescape(search->pattern, temp, 128);
487    UnicodeString  pattern;
488    pattern.setTo(temp);
489
490#if !UCONFIG_NO_BREAK_ITERATION
491    if (breaker != NULL) {
492        breaker->setText(text);
493    }
494#endif
495    collator->setStrength(getECollationStrength(search->strength));
496    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
497                               breaker, status);
498    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, canonical, status);
499    strsrch->setAttribute(USEARCH_OVERLAP, overlap, status);
500
501    if (U_FAILURE(status)) {
502        errln("Error opening string search %s", u_errorName(status));
503        return FALSE;
504    }
505
506    if (!assertEqualWithStringSearch(strsrch, search)) {
507        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
508        delete strsrch;
509        return FALSE;
510    }
511    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
512    delete strsrch;
513    return TRUE;
514}
515
516void StringSearchTest::TestOpenClose()
517{
518    UErrorCode               status    = U_ZERO_ERROR;
519    StringSearch            *result;
520    BreakIterator           *breakiter = m_en_wordbreaker_;
521    UnicodeString            pattern;
522    UnicodeString            text;
523    UnicodeString            temp("a");
524    StringCharacterIterator  chariter(text);
525
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");
530    }
531    delete result;
532
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");
538    }
539    delete result;
540
541    text.append(0, 0x1);
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");
546    }
547    delete result;
548
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");
554    }
555    delete result;
556
557    text.remove();
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");
563    }
564    delete result;
565
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");
571    }
572    delete result;
573
574    text.append(temp);
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");
579    }
580    delete result;
581
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");
587    }
588    delete result;
589
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");
594    }
595    delete result;
596
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");
601    }
602    delete result;
603
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");
608    }
609    delete result;
610
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");
615    }
616    delete result;
617
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");
622    }
623    delete result;
624
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");
629    }
630    delete result;
631}
632
633void StringSearchTest::TestInitialization()
634{
635    UErrorCode     status = U_ZERO_ERROR;
636    UnicodeString  pattern;
637    UnicodeString  text;
638    UnicodeString  temp("a");
639    StringSearch  *result;
640    int count;
641
642    /* simple test on the pattern ce construction */
643    pattern.append(temp);
644    pattern.append(temp);
645    text.append(temp);
646    text.append(temp);
647    text.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));
651    }
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))
661    {
662        errln("Error copying StringSearch");
663    }
664    delete copy;
665
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");
676    }
677    delete result;
678
679    /* testing if an extremely large pattern will fail the initialization */
680    for (count = 0; count < 512; count ++) {
681        pattern.append(temp);
682    }
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");
686    }
687    if (*result == *copy) {
688        errln("Error: string search objects are not expected to match");
689    }
690    *copy  = *result;
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");
700    }
701    if (U_FAILURE(status)) {
702        errln("Error opening search %s", u_errorName(status));
703    }
704    delete result;
705    delete copy;
706}
707
708void StringSearchTest::TestBasic()
709{
710    int count = 0;
711    while (BASIC[count].text != NULL) {
712        //printf("count %d", count);
713        if (!assertEqual(&BASIC[count])) {
714            infoln("Error at test number %d", count);
715        }
716        count ++;
717    }
718}
719
720void StringSearchTest::TestNormExact()
721{
722    int count = 0;
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));
728    }
729    while (BASIC[count].text != NULL) {
730        if (!assertEqual(&BASIC[count])) {
731            infoln("Error at test number %d", count);
732        }
733        count ++;
734    }
735    count = 0;
736    while (NORMEXACT[count].text != NULL) {
737        if (!assertEqual(&NORMEXACT[count])) {
738            infoln("Error at test number %d", count);
739        }
740        count ++;
741    }
742    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
743    count = 0;
744    while (NONNORMEXACT[count].text != NULL) {
745        if (!assertEqual(&NONNORMEXACT[count])) {
746            infoln("Error at test number %d", count);
747        }
748        count ++;
749    }
750}
751
752void StringSearchTest::TestStrength()
753{
754    int count = 0;
755    while (STRENGTH[count].text != NULL) {
756        if (!assertEqual(&STRENGTH[count])) {
757            infoln("Error at test number %d", count);
758        }
759        count ++;
760    }
761}
762
763#if !UCONFIG_NO_BREAK_ITERATION
764
765void StringSearchTest::TestBreakIterator()
766{
767    UChar temp[128];
768    u_unescape(BREAKITERATOREXACT[0].text, temp, 128);
769    UnicodeString text;
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));
774
775    UErrorCode status = U_ZERO_ERROR;
776    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
777                                             status);
778    if (U_FAILURE(status)) {
779        errln("Error opening string search %s", u_errorName(status));
780    }
781
782    strsrch->setBreakIterator(NULL, status);
783    if (U_FAILURE(status) || strsrch->getBreakIterator() != NULL) {
784        errln("Error usearch_getBreakIterator returned wrong object");
785    }
786
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");
791    }
792
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");
797    }
798
799    delete strsrch;
800
801    int count = 0;
802    while (count < 4) {
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;
808
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);
815        }
816        collator->setStrength(getECollationStrength(search->strength));
817
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) {
823                delete strsrch;
824            }
825        }
826        if (!assertEqualWithStringSearch(strsrch, search)) {
827            collator->setStrength(getECollationStrength(UCOL_TERTIARY));
828            delete strsrch;
829        }
830        search   = &(BREAKITERATOREXACT[count + 1]);
831        breaker  = getBreakIterator(search->breaker);
832        if (breaker != NULL) {
833            breaker->setText(text);
834        }
835        strsrch->setBreakIterator(breaker, status);
836        if (U_FAILURE(status) ||
837            strsrch->getBreakIterator() != breaker) {
838            errln("Error setting break iterator");
839            delete strsrch;
840        }
841        strsrch->reset();
842        if (!assertEqualWithStringSearch(strsrch, search)) {
843             infoln("Error at test number %d", count);
844        }
845        delete strsrch;
846        count += 2;
847    }
848    count = 0;
849    while (BREAKITERATOREXACT[count].text != NULL) {
850         if (!assertEqual(&BREAKITERATOREXACT[count])) {
851             infoln("Error at test number %d", count);
852         }
853         count ++;
854    }
855}
856
857#endif
858
859void StringSearchTest::TestVariable()
860{
861    int count = 0;
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));
867    }
868    while (VARIABLE[count].text != NULL) {
869        logln("variable %d", count);
870        if (!assertEqual(&VARIABLE[count])) {
871            infoln("Error at test number %d", count);
872        }
873        count ++;
874    }
875    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
876                           status);
877}
878
879void StringSearchTest::TestOverlap()
880{
881    int count = 0;
882    while (OVERLAP[count].text != NULL) {
883        if (!assertEqualWithAttribute(&OVERLAP[count], USEARCH_OFF,
884                                      USEARCH_ON)) {
885            errln("Error at overlap test number %d", count);
886        }
887        count ++;
888    }
889    count = 0;
890    while (NONOVERLAP[count].text != NULL) {
891        if (!assertEqual(&NONOVERLAP[count])) {
892            errln("Error at non overlap test number %d", count);
893        }
894        count ++;
895    }
896
897    count = 0;
898    while (count < 1) {
899        const SearchData *search = &(OVERLAP[count]);
900              UChar       temp[128];
901        u_unescape(search->text, temp, 128);
902        UnicodeString text;
903        text.setTo(temp, u_strlen(temp));
904        u_unescape(search->pattern, temp, 128);
905        UnicodeString pattern;
906        pattern.setTo(temp, u_strlen(temp));
907
908        RuleBasedCollator *collator = getCollator(search->collator);
909        UErrorCode         status   = U_ZERO_ERROR;
910        StringSearch      *strsrch  = new StringSearch(pattern, text,
911                                                       collator, NULL,
912                                                       status);
913
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");
918        }
919        if (!assertEqualWithStringSearch(strsrch, search)) {
920            delete strsrch;
921            return;
922        }
923
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");
929        }
930        strsrch->reset();
931        if (!assertEqualWithStringSearch(strsrch, search)) {
932            delete strsrch;
933            errln("Error at test number %d", count);
934         }
935
936        count ++;
937        delete strsrch;
938    }
939}
940
941void StringSearchTest::TestCollator()
942{
943    // test collator that thinks "o" and "p" are the same thing
944    UChar         temp[128];
945    u_unescape(COLLATOR[0].text, temp, 128);
946    UnicodeString text;
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));
951
952    UErrorCode    status = U_ZERO_ERROR;
953    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
954                                             status);
955    if (U_FAILURE(status)) {
956        errln("Error opening string search %s", u_errorName(status));
957        delete strsrch;
958        return;
959    }
960    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
961        delete strsrch;
962        return;
963    }
964
965    u_unescape(TESTCOLLATORRULE, temp, 128);
966    UnicodeString rules;
967    rules.setTo(temp, u_strlen(temp));
968    RuleBasedCollator *tailored = new RuleBasedCollator(rules, status);
969    tailored->setStrength(getECollationStrength(COLLATOR[1].strength));
970
971    if (U_FAILURE(status)) {
972        errln("Error opening rule based collator %s", u_errorName(status));
973        delete strsrch;
974        if (tailored != NULL) {
975            delete tailored;
976        }
977        return;
978    }
979
980    strsrch->setCollator(tailored, status);
981    if (U_FAILURE(status) || (*strsrch->getCollator()) != (*tailored)) {
982        errln("Error setting rule based collator");
983        delete strsrch;
984        if (tailored != NULL) {
985            delete tailored;
986        }
987    }
988    strsrch->reset();
989    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[1])) {
990        delete strsrch;
991        if (tailored != NULL) {
992            delete tailored;
993        }
994        return;
995    }
996
997    strsrch->setCollator(m_en_us_, status);
998    strsrch->reset();
999    if (U_FAILURE(status) || (*strsrch->getCollator()) != (*m_en_us_)) {
1000        errln("Error setting rule based collator");
1001        delete strsrch;
1002        if (tailored != NULL) {
1003            delete tailored;
1004        }
1005    }
1006    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
1007       errln("Error searching collator test");
1008    }
1009    delete strsrch;
1010    if (tailored != NULL) {
1011        delete tailored;
1012    }
1013}
1014
1015void StringSearchTest::TestPattern()
1016{
1017
1018    UChar temp[512];
1019    int templength;
1020    u_unescape(PATTERN[0].text, temp, 512);
1021    UnicodeString text;
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));
1026
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,
1030                                             status);
1031
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) {
1036            delete strsrch;
1037        }
1038        return;
1039    }
1040    if (strsrch->getPattern() != pattern) {
1041        errln("Error setting pattern");
1042    }
1043    if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1044        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1045        if (strsrch != NULL) {
1046            delete strsrch;
1047        }
1048        return;
1049    }
1050
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) {
1058            delete strsrch;
1059        }
1060        return;
1061    }
1062    strsrch->reset();
1063    if (U_FAILURE(status)) {
1064        errln("Error setting pattern %s", u_errorName(status));
1065    }
1066    if (!assertEqualWithStringSearch(strsrch, &PATTERN[1])) {
1067        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1068        if (strsrch != NULL) {
1069            delete strsrch;
1070        }
1071        return;
1072    }
1073
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) {
1081            delete strsrch;
1082        }
1083        return;
1084    }
1085    strsrch->reset();
1086    if (U_FAILURE(status)) {
1087        errln("Error setting pattern %s", u_errorName(status));
1088    }
1089    if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1090        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1091        if (strsrch != NULL) {
1092            delete strsrch;
1093        }
1094        return;
1095    }
1096    /* enormous pattern size to see if this crashes */
1097    for (templength = 0; templength != 512; templength ++) {
1098        temp[templength] = 0x61;
1099    }
1100    temp[511] = 0;
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));
1105    }
1106    m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1107    if (strsrch != NULL) {
1108        delete strsrch;
1109    }
1110}
1111
1112void StringSearchTest::TestText()
1113{
1114    UChar temp[128];
1115    u_unescape(TEXT[0].text, temp, 128);
1116    UnicodeString text;
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));
1121
1122    UErrorCode status = U_ZERO_ERROR;
1123    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1124                                             status);
1125    if (U_FAILURE(status)) {
1126        errln("Error opening string search %s", u_errorName(status));
1127        return;
1128    }
1129    if (text != strsrch->getText()) {
1130        errln("Error setting text");
1131    }
1132    if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1133        delete strsrch;
1134        return;
1135    }
1136
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");
1142        delete strsrch;
1143        return;
1144    }
1145    if (U_FAILURE(status)) {
1146        errln("Error setting text %s", u_errorName(status));
1147    }
1148    if (!assertEqualWithStringSearch(strsrch, &TEXT[1])) {
1149        delete strsrch;
1150        return;
1151    }
1152
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");
1159        delete strsrch;
1160        return;
1161    }
1162    if (U_FAILURE(status)) {
1163        errln("Error setting pattern %s", u_errorName(status));
1164    }
1165    if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1166        errln("Error searching within set text");
1167    }
1168    delete strsrch;
1169}
1170
1171void StringSearchTest::TestCompositeBoundaries()
1172{
1173    int count = 0;
1174    while (COMPOSITEBOUNDARIES[count].text != NULL) {
1175        logln("composite %d", count);
1176        if (!assertEqual(&COMPOSITEBOUNDARIES[count])) {
1177            errln("Error at test number %d", count);
1178        }
1179        count ++;
1180    }
1181}
1182
1183void StringSearchTest::TestGetSetOffset()
1184{
1185    UErrorCode     status  = U_ZERO_ERROR;
1186    UnicodeString  pattern("1234567890123456");
1187    UnicodeString  text("12345678901234567890123456789012");
1188    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_,
1189                                              NULL, status);
1190    /* testing out of bounds error */
1191    strsrch->setOffset(-1, status);
1192    if (U_SUCCESS(status)) {
1193        errln("Error expecting set offset error");
1194    }
1195    strsrch->setOffset(128, status);
1196    if (U_SUCCESS(status)) {
1197        errln("Error expecting set offset error");
1198    }
1199    int index   = 0;
1200    while (BASIC[index].text != NULL) {
1201        UErrorCode  status      = U_ZERO_ERROR;
1202        SearchData  search      = BASIC[index ++];
1203        UChar       temp[128];
1204
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(
1212                                                          search.strength));
1213        strsrch->reset();
1214
1215        int count = 0;
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());
1229                return;
1230            }
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");
1237                    return;
1238                }
1239            }
1240
1241            count += 2;
1242        }
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());
1252            return;
1253        }
1254    }
1255    strsrch->getCollator()->setStrength(getECollationStrength(
1256                                                             UCOL_TERTIARY));
1257    delete strsrch;
1258}
1259
1260void StringSearchTest::TestGetSetAttribute()
1261{
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,
1266                                              status);
1267    if (U_FAILURE(status)) {
1268        errln("Error opening search %s", u_errorName(status));
1269        return;
1270    }
1271
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");
1276    }
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");
1281    }
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");
1286    }
1287    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ATTRIBUTE_VALUE_COUNT,
1288                          status);
1289    if (U_SUCCESS(status)) {
1290        errln("Error setting overlap to illegal value");
1291    }
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");
1297    }
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");
1302    }
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");
1307    }
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");
1312    }
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");
1317    }
1318
1319    delete strsrch;
1320}
1321
1322void StringSearchTest::TestGetMatch()
1323{
1324    UChar      temp[128];
1325    SearchData search = MATCH[0];
1326    u_unescape(search.text, temp, 128);
1327    UnicodeString text;
1328    text.setTo(temp, u_strlen(temp));
1329    u_unescape(search.pattern, temp, 128);
1330    UnicodeString pattern;
1331    pattern.setTo(temp, u_strlen(temp));
1332
1333    UErrorCode    status  = U_ZERO_ERROR;
1334    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1335                                             status);
1336    if (U_FAILURE(status)) {
1337        errln("Error opening string search %s", u_errorName(status));
1338        if (strsrch != NULL) {
1339            delete strsrch;
1340        }
1341        return;
1342    }
1343
1344    int           count      = 0;
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());
1358            return;
1359        }
1360        count ++;
1361
1362        status = U_ZERO_ERROR;
1363        strsrch->getMatchedText(matchtext);
1364        if (matchtext.length() != matchlength || U_FAILURE(status)){
1365            errln("Error getting match text");
1366        }
1367        matchindex = search.offset[count];
1368    }
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");
1374    }
1375    status = U_ZERO_ERROR;
1376    strsrch->getMatchedText(matchtext);
1377    if (matchtext.length() != 0) {
1378        errln("Error getting null matches");
1379    }
1380    delete strsrch;
1381}
1382
1383void StringSearchTest::TestSetMatch()
1384{
1385    int count = 0;
1386    while (MATCH[count].text != NULL) {
1387        SearchData     search = MATCH[count];
1388        UChar          temp[128];
1389        UErrorCode status = U_ZERO_ERROR;
1390        u_unescape(search.text, temp, 128);
1391        UnicodeString text;
1392        text.setTo(temp, u_strlen(temp));
1393        u_unescape(search.pattern, temp, 128);
1394        UnicodeString pattern;
1395        pattern.setTo(temp, u_strlen(temp));
1396
1397        StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1398                                                 NULL, status);
1399        if (U_FAILURE(status)) {
1400            errln("Error opening string search %s", u_errorName(status));
1401            if (strsrch != NULL) {
1402                delete strsrch;
1403            }
1404            return;
1405        }
1406
1407        int size = 0;
1408        while (search.offset[size] != -1) {
1409            size ++;
1410        }
1411
1412        if (strsrch->first(status) != search.offset[0] || U_FAILURE(status)) {
1413            errln("Error getting first match");
1414        }
1415        if (strsrch->last(status) != search.offset[size -1] ||
1416            U_FAILURE(status)) {
1417            errln("Error getting last match");
1418        }
1419
1420        int index = 0;
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);
1427                }
1428            }
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);
1436                }
1437            }
1438            index += 2;
1439        }
1440        status = U_ZERO_ERROR;
1441        if (strsrch->following(text.length(), status) != USEARCH_DONE) {
1442            errln("Error expecting out of bounds match");
1443        }
1444        if (strsrch->preceding(0, status) != USEARCH_DONE) {
1445            errln("Error expecting out of bounds match");
1446        }
1447        count ++;
1448        delete strsrch;
1449    }
1450}
1451
1452void StringSearchTest::TestReset()
1453{
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,
1458                                              status);
1459    if (U_FAILURE(status)) {
1460        errln("Error opening string search %s", u_errorName(status));
1461        if (strsrch != NULL) {
1462            delete strsrch;
1463        }
1464        return;
1465    }
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");
1471    }
1472    else {
1473        strsrch->reset();
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");
1479        }
1480        strsrch->previous(status);
1481        if (strsrch->getMatchedStart() != 7 ||
1482            strsrch->getMatchedLength() != 1) {
1483            errln("Error resetting string search\n");
1484        }
1485    }
1486    delete strsrch;
1487}
1488
1489void StringSearchTest::TestSupplementary()
1490{
1491    int count = 0;
1492    while (SUPPLEMENTARY[count].text != NULL) {
1493        if (!assertEqual(&SUPPLEMENTARY[count])) {
1494            errln("Error at test number %d", count);
1495        }
1496        count ++;
1497    }
1498}
1499
1500void StringSearchTest::TestContraction()
1501{
1502    UChar      temp[128];
1503    UErrorCode status = U_ZERO_ERROR;
1504
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));
1512    }
1513    UnicodeString text("text");
1514    UnicodeString pattern("pattern");
1515    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1516                                             status);
1517    if (U_FAILURE(status)) {
1518        errln("Error opening string search %s", u_errorName(status));
1519    }
1520
1521    int count = 0;
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);
1531        }
1532        count ++;
1533    }
1534    delete strsrch;
1535    delete collator;
1536}
1537
1538void StringSearchTest::TestIgnorable()
1539{
1540    UChar temp[128];
1541    u_unescape(IGNORABLERULE, temp, 128);
1542    UnicodeString rules;
1543    rules.setTo(temp, u_strlen(temp));
1544    UErrorCode status = U_ZERO_ERROR;
1545    int        count  = 0;
1546    RuleBasedCollator *collator = new RuleBasedCollator(rules,
1547                            getECollationStrength(IGNORABLE[count].strength),
1548                            UCOL_ON, status);
1549    if (U_FAILURE(status)) {
1550        errln("Error opening collator %s", u_errorName(status));
1551        return;
1552    }
1553    UnicodeString pattern("pattern");
1554    UnicodeString text("text");
1555    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1556                                             status);
1557    if (U_FAILURE(status)) {
1558        errln("Error opening string search %s", u_errorName(status));
1559        delete collator;
1560        return;
1561    }
1562
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);
1572        }
1573        count ++;
1574    }
1575    delete strsrch;
1576    delete collator;
1577}
1578
1579void StringSearchTest::TestDiacriticMatch()
1580{
1581	UChar temp[128];
1582    UErrorCode status = U_ZERO_ERROR;
1583    int        count  = 0;
1584    RuleBasedCollator* coll = NULL;
1585    StringSearch *strsrch = NULL;
1586
1587    UnicodeString pattern("pattern");
1588    UnicodeString text("text");
1589
1590    const SearchData *search;
1591
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));
1599	        return;
1600	    }
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);
1609        }
1610        search = &(DIACRITICMATCH[++count]);
1611        delete strsrch;
1612    }
1613
1614}
1615
1616void StringSearchTest::TestCanonical()
1617{
1618    int count = 0;
1619    while (BASICCANONICAL[count].text != NULL) {
1620        if (!assertCanonicalEqual(&BASICCANONICAL[count])) {
1621            errln("Error at test number %d", count);
1622        }
1623        count ++;
1624    }
1625}
1626
1627void StringSearchTest::TestNormCanonical()
1628{
1629    UErrorCode status = U_ZERO_ERROR;
1630    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
1631    int count = 0;
1632    while (NORMCANONICAL[count].text != NULL) {
1633        if (!assertCanonicalEqual(&NORMCANONICAL[count])) {
1634            errln("Error at test number %d", count);
1635        }
1636        count ++;
1637    }
1638    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
1639}
1640
1641void StringSearchTest::TestStrengthCanonical()
1642{
1643    int count = 0;
1644    while (STRENGTHCANONICAL[count].text != NULL) {
1645        if (!assertCanonicalEqual(&STRENGTHCANONICAL[count])) {
1646            errln("Error at test number %d", count);
1647        }
1648        count ++;
1649    }
1650}
1651
1652#if !UCONFIG_NO_BREAK_ITERATION
1653
1654void StringSearchTest::TestBreakIteratorCanonical()
1655{
1656    UErrorCode status = U_ZERO_ERROR;
1657    int        count  = 0;
1658
1659    while (count < 4) {
1660        // special purposes for tests numbers 0-3
1661              UChar           temp[128];
1662        const SearchData     *search   = &(BREAKITERATORCANONICAL[count]);
1663
1664        u_unescape(search->text, temp, 128);
1665        UnicodeString text;
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));
1672
1673        BreakIterator *breaker = getBreakIterator(search->breaker);
1674        StringSearch  *strsrch = new StringSearch(pattern, text, collator,
1675                                                  breaker, status);
1676        if (U_FAILURE(status)) {
1677            errln("Error creating string search data");
1678            return;
1679        }
1680        strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1681        if (U_FAILURE(status) ||
1682            strsrch->getBreakIterator() != breaker) {
1683            errln("Error setting break iterator");
1684            delete strsrch;
1685            return;
1686        }
1687        if (!assertEqualWithStringSearch(strsrch, search)) {
1688            collator->setStrength(getECollationStrength(UCOL_TERTIARY));
1689            delete strsrch;
1690            return;
1691        }
1692        search  = &(BREAKITERATOREXACT[count + 1]);
1693        breaker = getBreakIterator(search->breaker);
1694        if (breaker == NULL) {
1695            errln("Error creating BreakIterator");
1696            return;
1697        }
1698        breaker->setText(strsrch->getText());
1699        strsrch->setBreakIterator(breaker, status);
1700        if (U_FAILURE(status) || strsrch->getBreakIterator() != breaker) {
1701            errln("Error setting break iterator");
1702            delete strsrch;
1703            return;
1704        }
1705        strsrch->reset();
1706        strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1707        if (!assertEqualWithStringSearch(strsrch, search)) {
1708             errln("Error at test number %d", count);
1709             return;
1710        }
1711        delete strsrch;
1712        count += 2;
1713    }
1714    count = 0;
1715    while (BREAKITERATORCANONICAL[count].text != NULL) {
1716         if (!assertEqual(&BREAKITERATORCANONICAL[count])) {
1717             errln("Error at test number %d", count);
1718             return;
1719         }
1720         count ++;
1721    }
1722}
1723
1724#endif
1725
1726void StringSearchTest::TestVariableCanonical()
1727{
1728    int count = 0;
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));
1734    }
1735    while (VARIABLE[count].text != NULL) {
1736        logln("variable %d", count);
1737        if (!assertCanonicalEqual(&VARIABLE[count])) {
1738            errln("Error at test number %d", count);
1739        }
1740        count ++;
1741    }
1742    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
1743                           status);
1744}
1745
1746void StringSearchTest::TestOverlapCanonical()
1747{
1748    int count = 0;
1749    while (OVERLAPCANONICAL[count].text != NULL) {
1750        if (!assertEqualWithAttribute(&OVERLAPCANONICAL[count], USEARCH_ON,
1751                                      USEARCH_ON)) {
1752            errln("Error at overlap test number %d", count);
1753        }
1754        count ++;
1755    }
1756    count = 0;
1757    while (NONOVERLAP[count].text != NULL) {
1758        if (!assertCanonicalEqual(&NONOVERLAPCANONICAL[count])) {
1759            errln("Error at non overlap test number %d", count);
1760        }
1761        count ++;
1762    }
1763
1764    count = 0;
1765    while (count < 1) {
1766              UChar       temp[128];
1767        const SearchData *search = &(OVERLAPCANONICAL[count]);
1768              UErrorCode  status = U_ZERO_ERROR;
1769
1770        u_unescape(search->text, temp, 128);
1771        UnicodeString text;
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,
1778                                                 NULL, status);
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");
1784        }
1785        if (!assertEqualWithStringSearch(strsrch, search)) {
1786            delete strsrch;
1787            return;
1788        }
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");
1794        }
1795        strsrch->reset();
1796        if (!assertEqualWithStringSearch(strsrch, search)) {
1797            delete strsrch;
1798            errln("Error at test number %d", count);
1799         }
1800
1801        count ++;
1802        delete strsrch;
1803    }
1804}
1805
1806void StringSearchTest::TestCollatorCanonical()
1807{
1808    /* test collator that thinks "o" and "p" are the same thing */
1809    UChar temp[128];
1810    u_unescape(COLLATORCANONICAL[0].text, temp, 128);
1811    UnicodeString text;
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));
1816
1817    UErrorCode    status  = U_ZERO_ERROR;
1818    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1819                                             NULL, status);
1820    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1821    if (U_FAILURE(status)) {
1822        errln("Error opening string search %s", u_errorName(status));
1823    }
1824    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1825        delete strsrch;
1826        return;
1827    }
1828
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),
1834        UCOL_ON, status);
1835
1836    if (U_FAILURE(status)) {
1837        errln("Error opening rule based collator %s", u_errorName(status));
1838    }
1839
1840    strsrch->setCollator(tailored, status);
1841    if (U_FAILURE(status) || *(strsrch->getCollator()) != *tailored) {
1842        errln("Error setting rule based collator");
1843    }
1844    strsrch->reset();
1845    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1846    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[1])) {
1847        delete strsrch;
1848        if (tailored != NULL) {
1849            delete tailored;
1850        }
1851
1852        return;
1853    }
1854
1855    strsrch->setCollator(m_en_us_, status);
1856    strsrch->reset();
1857    if (U_FAILURE(status) || *(strsrch->getCollator()) != *m_en_us_) {
1858        errln("Error setting rule based collator");
1859    }
1860    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1861    }
1862    delete strsrch;
1863    if (tailored != NULL) {
1864        delete tailored;
1865    }
1866}
1867
1868void StringSearchTest::TestPatternCanonical()
1869{
1870
1871    UChar temp[128];
1872
1873    u_unescape(PATTERNCANONICAL[0].text, temp, 128);
1874    UnicodeString text;
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));
1879
1880    m_en_us_->setStrength(
1881                      getECollationStrength(PATTERNCANONICAL[0].strength));
1882
1883    UErrorCode    status  = U_ZERO_ERROR;
1884    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1885                                             status);
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;
1890    }
1891    if (pattern != strsrch->getPattern()) {
1892        errln("Error setting pattern");
1893    }
1894    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1895        goto ENDTESTPATTERN;
1896    }
1897
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;
1904    }
1905    strsrch->reset();
1906    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1907    if (U_FAILURE(status)) {
1908        errln("Error setting pattern %s", u_errorName(status));
1909    }
1910    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[1])) {
1911        goto ENDTESTPATTERN;
1912    }
1913
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;
1920    }
1921    strsrch->reset();
1922    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1923    if (U_FAILURE(status)) {
1924        errln("Error setting pattern %s", u_errorName(status));
1925    }
1926    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1927        goto ENDTESTPATTERN;
1928    }
1929ENDTESTPATTERN:
1930    m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1931    if (strsrch != NULL) {
1932        delete strsrch;
1933    }
1934}
1935
1936void StringSearchTest::TestTextCanonical()
1937{
1938    UChar temp[128];
1939    u_unescape(TEXTCANONICAL[0].text, temp, 128);
1940    UnicodeString text;
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));
1945
1946    UErrorCode    status  = U_ZERO_ERROR;
1947    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1948                                             status);
1949    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1950
1951    if (U_FAILURE(status)) {
1952        errln("Error opening string search %s", u_errorName(status));
1953        goto ENDTESTPATTERN;
1954    }
1955    if (text != strsrch->getText()) {
1956        errln("Error setting text");
1957    }
1958    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1959        goto ENDTESTPATTERN;
1960    }
1961
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;
1968    }
1969    if (U_FAILURE(status)) {
1970        errln("Error setting text %s", u_errorName(status));
1971    }
1972    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[1])) {
1973        goto ENDTESTPATTERN;
1974    }
1975
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;
1982    }
1983    if (U_FAILURE(status)) {
1984        errln("Error setting pattern %s", u_errorName(status));
1985    }
1986    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1987        goto ENDTESTPATTERN;
1988    }
1989ENDTESTPATTERN:
1990    if (strsrch != NULL) {
1991        delete strsrch;
1992    }
1993}
1994
1995void StringSearchTest::TestCompositeBoundariesCanonical()
1996{
1997    int count = 0;
1998    while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
1999        logln("composite %d", count);
2000        if (!assertCanonicalEqual(&COMPOSITEBOUNDARIESCANONICAL[count])) {
2001            errln("Error at test number %d", count);
2002        }
2003        count ++;
2004    }
2005}
2006
2007void StringSearchTest::TestGetSetOffsetCanonical()
2008{
2009
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,
2014                                              status);
2015    Collator *collator = strsrch->getCollator();
2016
2017    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
2018
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");
2024    }
2025    strsrch->setOffset(128, status);
2026    if (U_SUCCESS(status)) {
2027        errln("Error expecting set offset error");
2028    }
2029    int   index   = 0;
2030    UChar temp[128];
2031    while (BASICCANONICAL[index].text != NULL) {
2032        SearchData  search      = BASICCANONICAL[index ++];
2033        if (BASICCANONICAL[index].text == NULL) {
2034            /* skip the last one */
2035            break;
2036        }
2037
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));
2042
2043        UErrorCode  status      = U_ZERO_ERROR;
2044        strsrch->setText(text, status);
2045
2046        strsrch->setPattern(pattern, status);
2047
2048        int         count       = 0;
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());
2062                goto bail;
2063            }
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");
2070                    goto bail;
2071                }
2072            }
2073
2074            count += 2;
2075        }
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());
2084            goto bail;
2085        }
2086    }
2087
2088bail:
2089    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
2090    delete strsrch;
2091}
2092
2093void StringSearchTest::TestSupplementaryCanonical()
2094{
2095    int count = 0;
2096    while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
2097        if (!assertCanonicalEqual(&SUPPLEMENTARYCANONICAL[count])) {
2098            errln("Error at test number %d", count);
2099        }
2100        count ++;
2101    }
2102}
2103
2104void StringSearchTest::TestContractionCanonical()
2105{
2106    UChar          temp[128];
2107
2108    u_unescape(CONTRACTIONRULE, temp, 128);
2109    UnicodeString rules;
2110    rules.setTo(temp, u_strlen(temp));
2111
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));
2117    }
2118    UnicodeString text("text");
2119    UnicodeString pattern("pattern");
2120    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
2121                                             status);
2122    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
2123    if (U_FAILURE(status)) {
2124        errln("Error opening string search %s", u_errorName(status));
2125    }
2126
2127    int count = 0;
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);
2138        }
2139        count ++;
2140    }
2141    delete strsrch;
2142    delete collator;
2143}
2144
2145void StringSearchTest::TestUClassID()
2146{
2147    char id = *((char *)StringSearch::getStaticClassID());
2148    if (id != 0) {
2149        errln("Static class id for StringSearch should be 0");
2150    }
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,
2155                                              status);
2156    id = *((char *)strsrch->getDynamicClassID());
2157    if (id != 0) {
2158        errln("Dynamic class id for StringSearch should be 0");
2159    }
2160    delete strsrch;
2161}
2162
2163class TestSearch : public SearchIterator
2164{
2165public:
2166    TestSearch(const TestSearch &obj);
2167    TestSearch(const UnicodeString &text,
2168               BreakIterator *breakiter,
2169               const UnicodeString &pattern);
2170    ~TestSearch();
2171
2172    void        setOffset(int32_t position, UErrorCode &status);
2173    int32_t     getOffset() const;
2174    SearchIterator* safeClone() const;
2175
2176
2177    /**
2178     * ICU "poor man's RTTI", returns a UClassID for the actual class.
2179     *
2180     * @draft ICU 2.2
2181     */
2182    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
2183
2184    /**
2185     * ICU "poor man's RTTI", returns a UClassID for this class.
2186     *
2187     * @draft ICU 2.2
2188     */
2189    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
2190
2191    UBool operator!=(const TestSearch &that) const;
2192
2193    UnicodeString m_pattern_;
2194
2195protected:
2196    int32_t      handleNext(int32_t position, UErrorCode &status);
2197    int32_t      handlePrev(int32_t position, UErrorCode &status);
2198    TestSearch & operator=(const TestSearch &that);
2199
2200private:
2201
2202    /**
2203     * The address of this static class variable serves as this class's ID
2204     * for ICU "poor man's RTTI".
2205     */
2206    static const char fgClassID;
2207    uint32_t m_offset_;
2208};
2209
2210const char TestSearch::fgClassID=0;
2211
2212TestSearch::TestSearch(const TestSearch &obj) : SearchIterator(obj)
2213{
2214    m_offset_ = obj.m_offset_;
2215    m_pattern_ = obj.m_pattern_;
2216}
2217
2218TestSearch::TestSearch(const UnicodeString &text,
2219                       BreakIterator *breakiter,
2220                       const UnicodeString &pattern) : SearchIterator()
2221{
2222    m_breakiterator_ = breakiter;
2223    m_pattern_ = pattern;
2224    m_text_ = text;
2225    m_offset_ = 0;
2226    m_pattern_ = pattern;
2227}
2228
2229TestSearch::~TestSearch()
2230{
2231}
2232
2233
2234void TestSearch::setOffset(int32_t position, UErrorCode &status)
2235{
2236    if (position >= 0 && position <= m_text_.length()) {
2237        m_offset_ = position;
2238    }
2239    else {
2240        status = U_INDEX_OUTOFBOUNDS_ERROR;
2241    }
2242}
2243
2244int32_t TestSearch::getOffset() const
2245{
2246    return m_offset_;
2247}
2248
2249SearchIterator * TestSearch::safeClone() const
2250{
2251    return new TestSearch(m_text_, m_breakiterator_, m_pattern_);
2252}
2253
2254UBool TestSearch::operator!=(const TestSearch &that) const
2255{
2256    if (SearchIterator::operator !=(that)) {
2257        return FALSE;
2258    }
2259    return m_offset_ != that.m_offset_ || m_pattern_ != that.m_pattern_;
2260}
2261
2262int32_t TestSearch::handleNext(int32_t start, UErrorCode &status)
2263{
2264  if(U_SUCCESS(status)) {
2265    int match = m_text_.indexOf(m_pattern_, start);
2266    if (match < 0) {
2267        m_offset_ = m_text_.length();
2268        setMatchStart(m_offset_);
2269        setMatchLength(0);
2270        return USEARCH_DONE;
2271    }
2272    setMatchStart(match);
2273    m_offset_ = match;
2274    setMatchLength(m_pattern_.length());
2275    return match;
2276  } else {
2277    return USEARCH_DONE;
2278  }
2279}
2280
2281int32_t TestSearch::handlePrev(int32_t start, UErrorCode &status)
2282{
2283  if(U_SUCCESS(status)) {
2284    int match = m_text_.lastIndexOf(m_pattern_, 0, start);
2285    if (match < 0) {
2286        m_offset_ = 0;
2287        setMatchStart(m_offset_);
2288        setMatchLength(0);
2289        return USEARCH_DONE;
2290    }
2291    setMatchStart(match);
2292    m_offset_ = match;
2293    setMatchLength(m_pattern_.length());
2294    return match;
2295  } else {
2296    return USEARCH_DONE;
2297  }
2298}
2299
2300TestSearch & TestSearch::operator=(const TestSearch &that)
2301{
2302    SearchIterator::operator=(that);
2303    m_offset_ = that.m_offset_;
2304    m_pattern_ = that.m_pattern_;
2305    return *this;
2306}
2307
2308void StringSearchTest::TestSubclass()
2309{
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;
2316    int i;
2317    StringCharacterIterator chariter(text);
2318
2319    search.setText(text, status);
2320    if (search.getText() != search2.getText()) {
2321        errln("Error setting text");
2322    }
2323
2324    search.setText(chariter, status);
2325    if (search.getText() != search2.getText()) {
2326        errln("Error setting text");
2327    }
2328
2329    search.reset();
2330    // comparing constructors
2331
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");
2335        }
2336        if (search.getMatchedLength() != search.m_pattern_.length()) {
2337            errln("Error getting next match length");
2338        }
2339    }
2340    if (search.next(status) != USEARCH_DONE) {
2341        errln("Error should have reached the end of the iteration");
2342    }
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");
2346        }
2347        if (search.getMatchedLength() != search.m_pattern_.length()) {
2348            errln("Error getting previous match length");
2349        }
2350    }
2351    if (search.previous(status) != USEARCH_DONE) {
2352        errln("Error should have reached the start of the iteration");
2353    }
2354}
2355
2356class StubSearchIterator:public SearchIterator{
2357public:
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;
2367    }
2368};
2369
2370void StringSearchTest::TestCoverage(){
2371    StubSearchIterator stub1, stub2;
2372    UErrorCode status = U_ZERO_ERROR;
2373
2374    if (stub1 != stub2){
2375        errln("new StubSearchIterator should be equal");
2376    }
2377
2378    stub2.setText(UnicodeString("ABC"), status);
2379    if (U_FAILURE(status)) {
2380        errln("Error: SearchIterator::SetText");
2381    }
2382
2383    stub1 = stub2;
2384    if (stub1 != stub2){
2385        errln("SearchIterator::operator =  assigned object should be equal");
2386    }
2387}
2388
2389#endif /* !UCONFIG_NO_BREAK_ITERATION */
2390
2391#endif /* #if !UCONFIG_NO_COLLATION */
2392