Home | History | Annotate | Download | only in intltest
      1 /****************************************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2006, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  * Modification History:
      6  *
      7  *   Date          Name        Description
      8  *   05/22/2000    Madhu       Added tests for testing new API for utf16 support and more
      9  ****************************************************************************************/
     10 
     11 #include <string.h>
     12 #include "unicode/chariter.h"
     13 #include "unicode/ustring.h"
     14 #include "unicode/unistr.h"
     15 #include "unicode/schriter.h"
     16 #include "unicode/uchriter.h"
     17 #include "unicode/uiter.h"
     18 #include "unicode/putil.h"
     19 #include "citrtest.h"
     20 
     21 
     22 class  SCharacterIterator : public CharacterIterator {
     23 public:
     24     SCharacterIterator(const UnicodeString& textStr){
     25         text = textStr;
     26         pos=0;
     27         textLength = textStr.length();
     28         begin = 0;
     29         end=textLength;
     30 
     31     }
     32 
     33     virtual ~SCharacterIterator(){};
     34 
     35 
     36     void setText(const UnicodeString& newText){
     37         text = newText;
     38     }
     39 
     40     virtual void getText(UnicodeString& result) {
     41         text.extract(0,text.length(),result);
     42     }
     43     static UClassID getStaticClassID(void){
     44         return (UClassID)(&fgClassID);
     45     }
     46     virtual UClassID getDynamicClassID(void) const{
     47         return getStaticClassID();
     48     }
     49 
     50     virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{
     51         return TRUE;
     52     }
     53 
     54     virtual CharacterIterator* clone(void) const {
     55         return NULL;
     56     }
     57     virtual int32_t hashCode(void) const{
     58         return DONE;
     59     }
     60     virtual UChar nextPostInc(void){ return text.charAt(pos++);}
     61     virtual UChar32 next32PostInc(void){return text.char32At(pos++);}
     62     virtual UBool hasNext() { return TRUE;};
     63     virtual UChar first(){return DONE;};
     64     virtual UChar32 first32(){return DONE;};
     65     virtual UChar last(){return DONE;};
     66     virtual UChar32 last32(){return DONE;};
     67     virtual UChar setIndex(int32_t /*pos*/){return DONE;};
     68     virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;};
     69     virtual UChar current() const{return DONE;};
     70     virtual UChar32 current32() const{return DONE;};
     71     virtual UChar next(){return DONE;};
     72     virtual UChar32 next32(){return DONE;};
     73     virtual UChar previous(){return DONE;};
     74     virtual UChar32 previous32(){return DONE;};
     75     virtual int32_t move(int32_t delta,CharacterIterator::EOrigin origin){
     76         switch(origin) {
     77         case kStart:
     78             pos = begin + delta;
     79             break;
     80         case kCurrent:
     81             pos += delta;
     82             break;
     83         case kEnd:
     84             pos = end + delta;
     85             break;
     86         default:
     87             break;
     88         }
     89 
     90         if(pos < begin) {
     91             pos = begin;
     92         } else if(pos > end) {
     93             pos = end;
     94         }
     95 
     96         return pos;
     97     };
     98     virtual int32_t move32(int32_t delta, CharacterIterator::EOrigin origin){
     99         switch(origin) {
    100         case kStart:
    101             pos = begin;
    102             if(delta > 0) {
    103                 UTF_FWD_N(text, pos, end, delta);
    104             }
    105             break;
    106         case kCurrent:
    107             if(delta > 0) {
    108                 UTF_FWD_N(text, pos, end, delta);
    109             } else {
    110                 UTF_BACK_N(text, begin, pos, -delta);
    111             }
    112             break;
    113         case kEnd:
    114             pos = end;
    115             if(delta < 0) {
    116                 UTF_BACK_N(text, begin, pos, -delta);
    117             }
    118             break;
    119         default:
    120             break;
    121         }
    122 
    123         return pos;
    124     };
    125     virtual UBool hasPrevious() {return TRUE;};
    126 
    127   SCharacterIterator&  operator=(const SCharacterIterator&    that){
    128      text = that.text;
    129      return *this;
    130   }
    131 
    132 
    133 private:
    134     UnicodeString text;
    135     static const char fgClassID;
    136 };
    137 const char SCharacterIterator::fgClassID=0;
    138 
    139 #define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0])))
    140 
    141 CharIterTest::CharIterTest()
    142 {
    143 }
    144 void CharIterTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
    145 {
    146     if (exec) logln("TestSuite CharIterTest: ");
    147     switch (index) {
    148         case 0: name = "TestConstructionAndEquality"; if (exec) TestConstructionAndEquality(); break;
    149         case 1: name = "TestConstructionAndEqualityUChariter"; if (exec) TestConstructionAndEqualityUChariter(); break;
    150         case 2: name = "TestIteration"; if (exec) TestIteration(); break;
    151         case 3: name = "TestIterationUChar32"; if (exec) TestIterationUChar32(); break;
    152         case 4: name = "TestUCharIterator"; if (exec) TestUCharIterator(); break;
    153         case 5: name = "TestCoverage"; if(exec) TestCoverage(); break;
    154         case 6: name = "TestCharIteratorSubClasses"; if (exec) TestCharIteratorSubClasses(); break;
    155         default: name = ""; break; //needed to end loop
    156     }
    157 }
    158 
    159 void CharIterTest::TestCoverage(){
    160     UnicodeString  testText("Now is the time for all good men to come to the aid of their country.");
    161     UnicodeString testText2("\\ud800\\udc01deadbeef");
    162     testText2 = testText2.unescape();
    163     SCharacterIterator* test = new SCharacterIterator(testText);
    164     if(test->firstPostInc()!= 0x004E){
    165         errln("Failed: firstPostInc() failed");
    166     }
    167     if(test->getIndex()!=1){
    168         errln("Failed: getIndex().");
    169     }
    170     if(test->getLength()!=testText.length()){
    171         errln("Failed: getLength()");
    172     }
    173     test->setToStart();
    174     if(test->getIndex()!=0){
    175         errln("Failed: setToStart().");
    176     }
    177     test->setToEnd();
    178     if(test->getIndex()!=testText.length()){
    179         errln("Failed: setToEnd().");
    180     }
    181     if(test->startIndex() != 0){
    182         errln("Failed: startIndex()");
    183     }
    184     test->setText(testText2);
    185     if(test->first32PostInc()!= testText2.char32At(0)){
    186         errln("Failed: first32PostInc() failed");
    187     }
    188 
    189     delete test;
    190 
    191 }
    192 void CharIterTest::TestConstructionAndEquality() {
    193     UnicodeString  testText("Now is the time for all good men to come to the aid of their country.");
    194     UnicodeString  testText2("Don't bother using this string.");
    195     UnicodeString result1, result2, result3;
    196 
    197     CharacterIterator* test1 = new StringCharacterIterator(testText);
    198     CharacterIterator* test1b= new StringCharacterIterator(testText, -1);
    199     CharacterIterator* test1c= new StringCharacterIterator(testText, 100);
    200     CharacterIterator* test1d= new StringCharacterIterator(testText, -2, 100, 5);
    201     CharacterIterator* test1e= new StringCharacterIterator(testText, 100, 20, 5);
    202     CharacterIterator* test2 = new StringCharacterIterator(testText, 5);
    203     CharacterIterator* test3 = new StringCharacterIterator(testText, 2, 20, 5);
    204     CharacterIterator* test4 = new StringCharacterIterator(testText2);
    205     CharacterIterator* test5 = test1->clone();
    206 
    207     if (test1d->startIndex() < 0)
    208         errln("Construction failed: startIndex is negative");
    209     if (test1d->endIndex() > testText.length())
    210         errln("Construction failed: endIndex is greater than the text length");
    211     if (test1d->getIndex() < test1d->startIndex() || test1d->endIndex() < test1d->getIndex())
    212         errln("Construction failed: index is invalid");
    213 
    214     if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4)
    215         errln("Construction or operator== failed: Unequal objects compared equal");
    216     if (*test1 != *test5)
    217         errln("clone() or equals() failed: Two clones tested unequal");
    218 
    219     if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode()
    220                     || test1->hashCode() == test4->hashCode())
    221         errln("hashCode() failed:  different objects have same hash code");
    222 
    223     if (test1->hashCode() != test5->hashCode())
    224         errln("hashCode() failed:  identical objects have different hash codes");
    225 
    226     if(test1->getLength() != testText.length()){
    227         errln("getLength of CharacterIterator failed");
    228     }
    229     test1->getText(result1);
    230     test1b->getText(result2);
    231     test1c->getText(result3);
    232     if(result1 != result2 ||  result1 != result3)
    233         errln("construction failed or getText() failed");
    234 
    235 
    236     test1->setIndex(5);
    237     if (*test1 != *test2 || *test1 == *test5)
    238         errln("setIndex() failed");
    239 
    240     *((StringCharacterIterator*)test1) = *((StringCharacterIterator*)test3);
    241     if (*test1 != *test3 || *test1 == *test5)
    242         errln("operator= failed");
    243 
    244     delete test2;
    245     delete test3;
    246     delete test4;
    247     delete test5;
    248     delete test1b;
    249     delete test1c;
    250     delete test1d;
    251     delete test1e;
    252 
    253 
    254     StringCharacterIterator* testChar1=new StringCharacterIterator(testText);
    255     StringCharacterIterator* testChar2=new StringCharacterIterator(testText2);
    256     StringCharacterIterator* testChar3=(StringCharacterIterator*)test1->clone();
    257 
    258     testChar1->getText(result1);
    259     testChar2->getText(result2);
    260     testChar3->getText(result3);
    261     if(result1 != result3 || result1 == result2)
    262         errln("getText() failed");
    263     testChar3->setText(testText2);
    264     testChar3->getText(result3);
    265     if(result1 == result3 || result2 != result3)
    266         errln("setText() or getText() failed");
    267     testChar3->setText(testText);
    268     testChar3->getText(result3);
    269     if(result1 != result3 || result1 == result2)
    270         errln("setText() or getText() round-trip failed");
    271 
    272     delete testChar1;
    273     delete testChar2;
    274     delete testChar3;
    275     delete test1;
    276 
    277 }
    278 void CharIterTest::TestConstructionAndEqualityUChariter() {
    279     U_STRING_DECL(testText, "Now is the time for all good men to come to the aid of their country.", 69);
    280     U_STRING_DECL(testText2, "Don't bother using this string.", 31);
    281 
    282     U_STRING_INIT(testText, "Now is the time for all good men to come to the aid of their country.", 69);
    283     U_STRING_INIT(testText2, "Don't bother using this string.", 31);
    284 
    285     UnicodeString result, result4, result5;
    286 
    287     UCharCharacterIterator* test1 = new UCharCharacterIterator(testText, u_strlen(testText));
    288     UCharCharacterIterator* test2 = new UCharCharacterIterator(testText, u_strlen(testText), 5);
    289     UCharCharacterIterator* test3 = new UCharCharacterIterator(testText, u_strlen(testText), 2, 20, 5);
    290     UCharCharacterIterator* test4 = new UCharCharacterIterator(testText2, u_strlen(testText2));
    291     UCharCharacterIterator* test5 = (UCharCharacterIterator*)test1->clone();
    292     UCharCharacterIterator* test6 = new UCharCharacterIterator(*test1);
    293 
    294     // j785: length=-1 will use u_strlen()
    295     UCharCharacterIterator* test7a = new UCharCharacterIterator(testText, -1);
    296     UCharCharacterIterator* test7b = new UCharCharacterIterator(testText, -1);
    297     UCharCharacterIterator* test7c = new UCharCharacterIterator(testText, -1, 2, 20, 5);
    298 
    299     // Bad parameters.
    300     UCharCharacterIterator* test8a = new UCharCharacterIterator(testText, -1, -1, 20, 5);
    301     UCharCharacterIterator* test8b = new UCharCharacterIterator(testText, -1, 2, 100, 5);
    302     UCharCharacterIterator* test8c = new UCharCharacterIterator(testText, -1, 2, 20, 100);
    303 
    304     if (test8a->startIndex() < 0)
    305         errln("Construction failed: startIndex is negative");
    306     if (test8b->endIndex() != u_strlen(testText))
    307         errln("Construction failed: endIndex is different from the text length");
    308     if (test8c->getIndex() < test8c->startIndex() || test8c->endIndex() < test8c->getIndex())
    309         errln("Construction failed: index is invalid");
    310 
    311     if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4 )
    312         errln("Construction or operator== failed: Unequal objects compared equal");
    313     if (*test1 != *test5 )
    314         errln("clone() or equals() failed: Two clones tested unequal");
    315 
    316     if (*test6 != *test1 )
    317         errln("copy construction or equals() failed: Two copies tested unequal");
    318 
    319     if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode()
    320                     || test1->hashCode() == test4->hashCode())
    321         errln("hashCode() failed:  different objects have same hash code");
    322 
    323     if (test1->hashCode() != test5->hashCode())
    324         errln("hashCode() failed:  identical objects have different hash codes");
    325 
    326     test7a->getText(result);
    327     test7b->getText(result4);
    328     test7c->getText(result5);
    329 
    330     if(result != UnicodeString(testText) || result4 != result || result5 != result)
    331         errln("error in construction");
    332 
    333     test1->getText(result);
    334     test4->getText(result4);
    335     test5->getText(result5);
    336     if(result != result5 || result == result4)
    337         errln("getText() failed");
    338     test5->setText(testText2, u_strlen(testText2));
    339     test5->getText(result5);
    340     if(result == result5 || result4 != result5)
    341         errln("setText() or getText() failed");
    342     test5->setText(testText, u_strlen(testText));
    343     test5->getText(result5);
    344     if(result != result5 || result == result4)
    345         errln("setText() or getText() round-trip failed");
    346 
    347 
    348     test1->setIndex(5);
    349     if (*test1 != *test2 || *test1 == *test5)
    350         errln("setIndex() failed");
    351     test8b->setIndex32(5);
    352     if (test8b->getIndex()!=5)
    353         errln("setIndex32() failed");
    354 
    355     *test1 = *test3;
    356     if (*test1 != *test3 || *test1 == *test5)
    357         errln("operator= failed");
    358 
    359     delete test1;
    360     delete test2;
    361     delete test3;
    362     delete test4;
    363     delete test5;
    364     delete test6;
    365     delete test7a;
    366     delete test7b;
    367     delete test7c;
    368     delete test8a;
    369     delete test8b;
    370     delete test8c;
    371 }
    372 
    373 
    374 void CharIterTest::TestIteration() {
    375     UnicodeString text("Now is the time for all good men to come to the aid of their country.");
    376 
    377     UChar c;
    378     int32_t i;
    379     {
    380         StringCharacterIterator   iter(text, 5);
    381 
    382         UnicodeString iterText;
    383         iter.getText(iterText);
    384         if (iterText != text)
    385           errln("iter.getText() failed");
    386 
    387         if (iter.current() != text[(int32_t)5])
    388             errln("Iterator didn't start out in the right place.");
    389 
    390         c = iter.first();
    391         i = 0;
    392 
    393         if (iter.startIndex() != 0 || iter.endIndex() != text.length())
    394             errln("startIndex() or endIndex() failed");
    395 
    396         logln("Testing forward iteration...");
    397         do {
    398             if (c == CharacterIterator::DONE && i != text.length())
    399                 errln("Iterator reached end prematurely");
    400             else if (c != text[i])
    401                 errln((UnicodeString)"Character mismatch at position " + i +
    402                                     ", iterator has " + UCharToUnicodeString(c) +
    403                                     ", string has " + UCharToUnicodeString(text[i]));
    404 
    405             if (iter.current() != c)
    406                 errln("current() isn't working right");
    407             if (iter.getIndex() != i)
    408                 errln("getIndex() isn't working right");
    409 
    410             if (c != CharacterIterator::DONE) {
    411                 c = iter.next();
    412                 i++;
    413             }
    414         } while (c != CharacterIterator::DONE);
    415         c=iter.next();
    416         if(c!= CharacterIterator::DONE)
    417             errln("next() didn't return DONE at the end");
    418         c=iter.setIndex(text.length()+1);
    419         if(c!= CharacterIterator::DONE)
    420             errln("setIndex(len+1) didn't return DONE");
    421 
    422         c = iter.last();
    423         i = text.length() - 1;
    424 
    425         logln("Testing backward iteration...");
    426         do {
    427             if (c == CharacterIterator::DONE && i >= 0)
    428                 errln("Iterator reached end prematurely");
    429             else if (c != text[i])
    430                 errln((UnicodeString)"Character mismatch at position " + i +
    431                                     ", iterator has " + UCharToUnicodeString(c) +
    432                                     ", string has " + UCharToUnicodeString(text[i]));
    433 
    434             if (iter.current() != c)
    435                 errln("current() isn't working right");
    436             if (iter.getIndex() != i)
    437                 errln("getIndex() isn't working right");
    438             if(iter.setIndex(i) != c)
    439                 errln("setIndex() isn't working right");
    440 
    441             if (c != CharacterIterator::DONE) {
    442                 c = iter.previous();
    443                 i--;
    444             }
    445         } while (c != CharacterIterator::DONE);
    446 
    447         c=iter.previous();
    448         if(c!= CharacterIterator::DONE)
    449             errln("previous didn't return DONE at the beginning");
    450 
    451 
    452         //testing firstPostInc, nextPostInc, setTostart
    453         i = 0;
    454         c=iter.firstPostInc();
    455         if(c != text[i])
    456             errln((UnicodeString)"firstPostInc failed.  Expected->" +
    457                          UCharToUnicodeString(text[i]) + " Got->" + UCharToUnicodeString(c));
    458         if(iter.getIndex() != i+1)
    459             errln((UnicodeString)"getIndex() after firstPostInc() failed");
    460 
    461         iter.setToStart();
    462         i=0;
    463         if (iter.startIndex() != 0)
    464             errln("setToStart failed");
    465 
    466         logln("Testing forward iteration...");
    467         do {
    468             if (c != CharacterIterator::DONE)
    469                 c = iter.nextPostInc();
    470 
    471             if(c != text[i])
    472                 errln((UnicodeString)"Character mismatch at position " + i +
    473                                     (UnicodeString)", iterator has " + UCharToUnicodeString(c) +
    474                                     (UnicodeString)", string has " + UCharToUnicodeString(text[i]));
    475 
    476             i++;
    477             if(iter.getIndex() != i)
    478                 errln("getIndex() aftr nextPostInc() isn't working right");
    479             if(iter.current() != text[i])
    480                 errln("current() after nextPostInc() isn't working right");
    481         } while (iter.hasNext());
    482         c=iter.nextPostInc();
    483         if(c!= CharacterIterator::DONE)
    484             errln("nextPostInc() didn't return DONE at the beginning");
    485     }
    486 
    487     {
    488         StringCharacterIterator iter(text, 5, 15, 10);
    489         if (iter.startIndex() != 5 || iter.endIndex() != 15)
    490             errln("creation of a restricted-range iterator failed");
    491 
    492         if (iter.getIndex() != 10 || iter.current() != text[(int32_t)10])
    493             errln("starting the iterator in the middle didn't work");
    494 
    495         c = iter.first();
    496         i = 5;
    497 
    498         logln("Testing forward iteration over a range...");
    499         do {
    500             if (c == CharacterIterator::DONE && i != 15)
    501                 errln("Iterator reached end prematurely");
    502             else if (c != text[i])
    503                 errln((UnicodeString)"Character mismatch at position " + i +
    504                                     ", iterator has " + UCharToUnicodeString(c) +
    505                                     ", string has " + UCharToUnicodeString(text[i]));
    506 
    507             if (iter.current() != c)
    508                 errln("current() isn't working right");
    509             if (iter.getIndex() != i)
    510                 errln("getIndex() isn't working right");
    511             if(iter.setIndex(i) != c)
    512                 errln("setIndex() isn't working right");
    513 
    514             if (c != CharacterIterator::DONE) {
    515                 c = iter.next();
    516                 i++;
    517             }
    518         } while (c != CharacterIterator::DONE);
    519 
    520         c = iter.last();
    521         i = 14;
    522 
    523         logln("Testing backward iteration over a range...");
    524         do {
    525             if (c == CharacterIterator::DONE && i >= 5)
    526                 errln("Iterator reached end prematurely");
    527             else if (c != text[i])
    528                 errln((UnicodeString)"Character mismatch at position " + i +
    529                                     ", iterator has " + UCharToUnicodeString(c) +
    530                                     ", string has " + UCharToUnicodeString(text[i]));
    531 
    532             if (iter.current() != c)
    533                 errln("current() isn't working right");
    534             if (iter.getIndex() != i)
    535                 errln("getIndex() isn't working right");
    536 
    537             if (c != CharacterIterator::DONE) {
    538                 c = iter.previous();
    539                 i--;
    540             }
    541         } while (c != CharacterIterator::DONE);
    542 
    543 
    544     }
    545 }
    546 
    547 //Tests for new API for utf-16 support
    548 void CharIterTest::TestIterationUChar32() {
    549     UChar textChars[]={ 0x0061, 0x0062, 0xd841, 0xdc02, 0x20ac, 0xd7ff, 0xd842, 0xdc06, 0xd801, 0xdc00, 0x0061, 0x0000};
    550     UnicodeString text(textChars);
    551     UChar32 c;
    552     int32_t i;
    553     {
    554         StringCharacterIterator   iter(text, 1);
    555 
    556         UnicodeString iterText;
    557         iter.getText(iterText);
    558         if (iterText != text)
    559           errln("iter.getText() failed");
    560 
    561         if (iter.current32() != text[(int32_t)1])
    562             errln("Iterator didn't start out in the right place.");
    563 
    564         c=iter.setToStart();
    565         i=0;
    566         i=iter.move32(1, CharacterIterator::kStart);
    567         c=iter.current32();
    568         if(c != text.char32At(1) || i!=1)
    569             errln("move32(1, kStart) didn't work correctly expected %X got %X", c, text.char32At(1) );
    570 
    571         i=iter.move32(2, CharacterIterator::kCurrent);
    572         c=iter.current32();
    573         if(c != text.char32At(4) || i!=4)
    574             errln("move32(2, kCurrent) didn't work correctly expected %X got %X i=%ld", c, text.char32At(4), i);
    575 
    576         i=iter.move32(-2, CharacterIterator::kCurrent);
    577         c=iter.current32();
    578         if(c != text.char32At(1) || i!=1)
    579             errln("move32(-2, kCurrent) didn't work correctly expected %X got %X i=%d", c, text.char32At(1), i);
    580 
    581 
    582         i=iter.move32(-2, CharacterIterator::kEnd);
    583         c=iter.current32();
    584         if(c != text.char32At((text.length()-3)) || i!=(text.length()-3))
    585             errln("move32(-2, kEnd) didn't work correctly expected %X got %X i=%d", c, text.char32At((text.length()-3)), i);
    586 
    587 
    588         c = iter.first32();
    589         i = 0;
    590 
    591         if (iter.startIndex() != 0 || iter.endIndex() != text.length())
    592             errln("startIndex() or endIndex() failed");
    593 
    594         logln("Testing forward iteration...");
    595         do {
    596             /* logln("c=%d i=%d char32At=%d", c, i, text.char32At(i)); */
    597             if (c == CharacterIterator::DONE && i != text.length())
    598                 errln("Iterator reached end prematurely");
    599             else if(iter.hasNext() == FALSE && i != text.length())
    600                 errln("Iterator reached end prematurely.  Failed at hasNext");
    601             else if (c != text.char32At(i))
    602                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
    603 
    604             if (iter.current32() != c)
    605                 errln("current32() isn't working right");
    606             if(iter.setIndex32(i) != c)
    607                 errln("setIndex32() isn't working right");
    608             if (c != CharacterIterator::DONE) {
    609                 c = iter.next32();
    610                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
    611             }
    612         } while (c != CharacterIterator::DONE);
    613         if(iter.hasNext() == TRUE)
    614            errln("hasNext() returned true at the end of the string");
    615 
    616 
    617 
    618         c=iter.setToEnd();
    619         if(iter.getIndex() != text.length() || iter.hasNext() != FALSE)
    620             errln("setToEnd failed");
    621 
    622         c=iter.next32();
    623         if(c!= CharacterIterator::DONE)
    624             errln("next32 didn't return DONE at the end");
    625         c=iter.setIndex32(text.length()+1);
    626         if(c!= CharacterIterator::DONE)
    627             errln("setIndex32(len+1) didn't return DONE");
    628 
    629 
    630         c = iter.last32();
    631         i = text.length()-1;
    632         logln("Testing backward iteration...");
    633         do {
    634             if (c == CharacterIterator::DONE && i >= 0)
    635                 errln((UnicodeString)"Iterator reached start prematurely for i=" + i);
    636             else if(iter.hasPrevious() == FALSE && i>0)
    637                 errln((UnicodeString)"Iterator reached start prematurely for i=" + i);
    638             else if (c != text.char32At(i))
    639                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
    640 
    641             if (iter.current32() != c)
    642                 errln("current32() isn't working right");
    643             if(iter.setIndex32(i) != c)
    644                 errln("setIndex32() isn't working right");
    645             if (iter.getIndex() != i)
    646                 errln("getIndex() isn't working right");
    647             if (c != CharacterIterator::DONE) {
    648                 c = iter.previous32();
    649                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1;
    650             }
    651         } while (c != CharacterIterator::DONE);
    652         if(iter.hasPrevious() == TRUE)
    653             errln("hasPrevious returned true after reaching the start");
    654 
    655         c=iter.previous32();
    656         if(c!= CharacterIterator::DONE)
    657             errln("previous32 didn't return DONE at the beginning");
    658 
    659 
    660 
    661 
    662         //testing first32PostInc, next32PostInc, setTostart
    663         i = 0;
    664         c=iter.first32PostInc();
    665         if(c != text.char32At(i))
    666             errln("first32PostInc failed.  Expected->%X Got->%X", text.char32At(i), c);
    667         if(iter.getIndex() != UTF16_CHAR_LENGTH(c) + i)
    668             errln((UnicodeString)"getIndex() after first32PostInc() failed");
    669 
    670         iter.setToStart();
    671         i=0;
    672         if (iter.startIndex() != 0)
    673             errln("setToStart failed");
    674 
    675         logln("Testing forward iteration...");
    676         do {
    677             if (c != CharacterIterator::DONE)
    678                 c = iter.next32PostInc();
    679 
    680             if(c != text.char32At(i))
    681                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
    682 
    683             i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
    684             if(iter.getIndex() != i)
    685                 errln("getIndex() aftr next32PostInc() isn't working right");
    686             if(iter.current32() != text.char32At(i))
    687                 errln("current() after next32PostInc() isn't working right");
    688         } while (iter.hasNext());
    689         c=iter.next32PostInc();
    690         if(c!= CharacterIterator::DONE)
    691             errln("next32PostInc() didn't return DONE at the beginning");
    692 
    693 
    694     }
    695 
    696     {
    697         StringCharacterIterator iter(text, 1, 11, 10);
    698         if (iter.startIndex() != 1 || iter.endIndex() != 11)
    699             errln("creation of a restricted-range iterator failed");
    700 
    701         if (iter.getIndex() != 10 || iter.current32() != text.char32At(10))
    702             errln("starting the iterator in the middle didn't work");
    703 
    704         c = iter.first32();
    705 
    706         i = 1;
    707 
    708         logln("Testing forward iteration over a range...");
    709         do {
    710             if (c == CharacterIterator::DONE && i != 11)
    711                 errln("Iterator reached end prematurely");
    712             else if(iter.hasNext() == FALSE)
    713                 errln("Iterator reached end prematurely");
    714             else if (c != text.char32At(i))
    715                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
    716 
    717             if (iter.current32() != c)
    718                 errln("current32() isn't working right");
    719             if(iter.setIndex32(i) != c)
    720                 errln("setIndex32() isn't working right");
    721 
    722             if (c != CharacterIterator::DONE) {
    723                 c = iter.next32();
    724                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
    725             }
    726         } while (c != CharacterIterator::DONE);
    727         c=iter.next32();
    728         if(c != CharacterIterator::DONE)
    729             errln("error in next32()");
    730 
    731 
    732 
    733         c=iter.last32();
    734         i = 10;
    735         logln("Testing backward iteration over a range...");
    736         do {
    737             if (c == CharacterIterator::DONE && i >= 5)
    738                 errln("Iterator reached start prematurely");
    739             else if(iter.hasPrevious() == FALSE && i > 5)
    740                 errln("Iterator reached start prematurely");
    741             else if (c != text.char32At(i))
    742                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
    743             if (iter.current32() != c)
    744                 errln("current32() isn't working right");
    745             if (iter.getIndex() != i)
    746                 errln("getIndex() isn't working right");
    747             if(iter.setIndex32(i) != c)
    748                 errln("setIndex32() isn't working right");
    749 
    750             if (c != CharacterIterator::DONE) {
    751                 c = iter.previous32();
    752                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1;
    753             }
    754 
    755         } while (c != CharacterIterator::DONE);
    756         c=iter.previous32();
    757         if(c!= CharacterIterator::DONE)
    758             errln("error on previous32");
    759 
    760 
    761     }
    762 }
    763 
    764 void CharIterTest::TestUCharIterator(UCharIterator *iter, CharacterIterator &ci,
    765                                      const char *moves, const char *which) {
    766     int32_t m;
    767     UChar32 c, c2;
    768     UBool h, h2;
    769 
    770     for(m=0;; ++m) {
    771         // move both iter and s[index]
    772         switch(moves[m]) {
    773         case '0':
    774             h=iter->hasNext(iter);
    775             h2=ci.hasNext();
    776             c=iter->current(iter);
    777             c2=ci.current();
    778             break;
    779         case '|':
    780             h=iter->hasNext(iter);
    781             h2=ci.hasNext();
    782             c=uiter_current32(iter);
    783             c2=ci.current32();
    784             break;
    785 
    786         case '+':
    787             h=iter->hasNext(iter);
    788             h2=ci.hasNext();
    789             c=iter->next(iter);
    790             c2=ci.nextPostInc();
    791             break;
    792         case '>':
    793             h=iter->hasNext(iter);
    794             h2=ci.hasNext();
    795             c=uiter_next32(iter);
    796             c2=ci.next32PostInc();
    797             break;
    798 
    799         case '-':
    800             h=iter->hasPrevious(iter);
    801             h2=ci.hasPrevious();
    802             c=iter->previous(iter);
    803             c2=ci.previous();
    804             break;
    805         case '<':
    806             h=iter->hasPrevious(iter);
    807             h2=ci.hasPrevious();
    808             c=uiter_previous32(iter);
    809             c2=ci.previous32();
    810             break;
    811 
    812         case '2':
    813             h=h2=FALSE;
    814             c=(UChar32)iter->move(iter, 2, UITER_CURRENT);
    815             c2=(UChar32)ci.move(2, CharacterIterator::kCurrent);
    816             break;
    817 
    818         case '8':
    819             h=h2=FALSE;
    820             c=(UChar32)iter->move(iter, -2, UITER_CURRENT);
    821             c2=(UChar32)ci.move(-2, CharacterIterator::kCurrent);
    822             break;
    823 
    824         case 0:
    825             return;
    826         default:
    827             errln("error: unexpected move character '%c' in \"%s\"", moves[m], moves);
    828             return;
    829         }
    830 
    831         // compare results
    832         if(c2==0xffff) {
    833             c2=(UChar32)-1;
    834         }
    835         if(c!=c2 || h!=h2 || ci.getIndex()!=iter->getIndex(iter, UITER_CURRENT)) {
    836             errln("error: UCharIterator(%s) misbehaving at \"%s\"[%d]='%c'", which, moves, m, moves[m]);
    837         }
    838     }
    839 }
    840 
    841 void CharIterTest::TestUCharIterator() {
    842     // test string of length 8
    843     UnicodeString s=UnicodeString("a \\U00010001b\\U0010fffdz", "").unescape();
    844     const char *const moves=
    845         "0+++++++++" // 10 moves per line
    846         "----0-----"
    847         ">>|>>>>>>>"
    848         "<<|<<<<<<<"
    849         "22+>8>-8+2";
    850 
    851     StringCharacterIterator sci(s), compareCI(s);
    852 
    853     UCharIterator sIter, cIter, rIter;
    854 
    855     uiter_setString(&sIter, s.getBuffer(), s.length());
    856     uiter_setCharacterIterator(&cIter, &sci);
    857     uiter_setReplaceable(&rIter, &s);
    858 
    859     TestUCharIterator(&sIter, compareCI, moves, "uiter_setString");
    860     compareCI.setIndex(0);
    861     TestUCharIterator(&cIter, compareCI, moves, "uiter_setCharacterIterator");
    862     compareCI.setIndex(0);
    863     TestUCharIterator(&rIter, compareCI, moves, "uiter_setReplaceable");
    864 
    865     // test move & getIndex some more
    866     sIter.start=2;
    867     sIter.index=3;
    868     sIter.limit=5;
    869     if( sIter.getIndex(&sIter, UITER_ZERO)!=0 ||
    870         sIter.getIndex(&sIter, UITER_START)!=2 ||
    871         sIter.getIndex(&sIter, UITER_CURRENT)!=3 ||
    872         sIter.getIndex(&sIter, UITER_LIMIT)!=5 ||
    873         sIter.getIndex(&sIter, UITER_LENGTH)!=s.length()
    874     ) {
    875         errln("error: UCharIterator(string).getIndex returns wrong index");
    876     }
    877 
    878     if( sIter.move(&sIter, 4, UITER_ZERO)!=4 ||
    879         sIter.move(&sIter, 1, UITER_START)!=3 ||
    880         sIter.move(&sIter, 3, UITER_CURRENT)!=5 ||
    881         sIter.move(&sIter, -1, UITER_LIMIT)!=4 ||
    882         sIter.move(&sIter, -5, UITER_LENGTH)!=3 ||
    883         sIter.move(&sIter, 0, UITER_CURRENT)!=sIter.getIndex(&sIter, UITER_CURRENT) ||
    884         sIter.getIndex(&sIter, UITER_CURRENT)!=3
    885     ) {
    886         errln("error: UCharIterator(string).move sets/returns wrong index");
    887     }
    888 
    889     sci=StringCharacterIterator(s, 2, 5, 3);
    890     uiter_setCharacterIterator(&cIter, &sci);
    891     if( cIter.getIndex(&cIter, UITER_ZERO)!=0 ||
    892         cIter.getIndex(&cIter, UITER_START)!=2 ||
    893         cIter.getIndex(&cIter, UITER_CURRENT)!=3 ||
    894         cIter.getIndex(&cIter, UITER_LIMIT)!=5 ||
    895         cIter.getIndex(&cIter, UITER_LENGTH)!=s.length()
    896     ) {
    897         errln("error: UCharIterator(character iterator).getIndex returns wrong index");
    898     }
    899 
    900     if( cIter.move(&cIter, 4, UITER_ZERO)!=4 ||
    901         cIter.move(&cIter, 1, UITER_START)!=3 ||
    902         cIter.move(&cIter, 3, UITER_CURRENT)!=5 ||
    903         cIter.move(&cIter, -1, UITER_LIMIT)!=4 ||
    904         cIter.move(&cIter, -5, UITER_LENGTH)!=3 ||
    905         cIter.move(&cIter, 0, UITER_CURRENT)!=cIter.getIndex(&cIter, UITER_CURRENT) ||
    906         cIter.getIndex(&cIter, UITER_CURRENT)!=3
    907     ) {
    908         errln("error: UCharIterator(character iterator).move sets/returns wrong index");
    909     }
    910 
    911 
    912     if(cIter.getIndex(&cIter, (enum UCharIteratorOrigin)-1) != -1)
    913     {
    914         errln("error: UCharIterator(char iter).getIndex did not return error value");
    915     }
    916 
    917     if(cIter.move(&cIter, 0, (enum UCharIteratorOrigin)-1) != -1)
    918     {
    919         errln("error: UCharIterator(char iter).move did not return error value");
    920     }
    921 
    922 
    923     if(rIter.getIndex(&rIter, (enum UCharIteratorOrigin)-1) != -1)
    924     {
    925         errln("error: UCharIterator(repl iter).getIndex did not return error value");
    926     }
    927 
    928     if(rIter.move(&rIter, 0, (enum UCharIteratorOrigin)-1) != -1)
    929     {
    930         errln("error: UCharIterator(repl iter).move did not return error value");
    931     }
    932 
    933 
    934     if(sIter.getIndex(&sIter, (enum UCharIteratorOrigin)-1) != -1)
    935     {
    936         errln("error: UCharIterator(string iter).getIndex did not return error value");
    937     }
    938 
    939     if(sIter.move(&sIter, 0, (enum UCharIteratorOrigin)-1) != -1)
    940     {
    941         errln("error: UCharIterator(string iter).move did not return error value");
    942     }
    943 
    944     /* Testing function coverage on bad input */
    945     UErrorCode status = U_ZERO_ERROR;
    946     uiter_setString(&sIter, NULL, 1);
    947     uiter_setState(&sIter, 1, &status);
    948     if (status != U_UNSUPPORTED_ERROR) {
    949         errln("error: uiter_setState returned %s instead of U_UNSUPPORTED_ERROR", u_errorName(status));
    950     }
    951     status = U_ZERO_ERROR;
    952     uiter_setState(NULL, 1, &status);
    953     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
    954         errln("error: uiter_setState returned %s instead of U_ILLEGAL_ARGUMENT_ERROR", u_errorName(status));
    955     }
    956     if (uiter_getState(&sIter) != UITER_NO_STATE) {
    957         errln("error: uiter_getState did not return UITER_NO_STATE on bad input");
    958     }
    959 }
    960 
    961 // subclass test, and completing API coverage -------------------------------
    962 
    963 class SubCharIter : public CharacterIterator {
    964 public:
    965     // public default constructor, to get coverage of CharacterIterator()
    966     SubCharIter() : CharacterIterator() {
    967         textLength=end=LENGTHOF(s);
    968         s[0]=0x61;      // 'a'
    969         s[1]=0xd900;    // U+50400
    970         s[2]=0xdd00;
    971         s[3]=0x2029;    // PS
    972     }
    973 
    974     // useful stuff, mostly dummy but testing coverage and subclassability
    975     virtual UChar nextPostInc() {
    976         if(pos<LENGTHOF(s)) {
    977             return s[pos++];
    978         } else {
    979             return DONE;
    980         }
    981     }
    982 
    983     virtual UChar32 next32PostInc() {
    984         if(pos<LENGTHOF(s)) {
    985             UChar32 c;
    986             U16_NEXT(s, pos, LENGTHOF(s), c);
    987             return c;
    988         } else {
    989             return DONE;
    990         }
    991     }
    992 
    993     virtual UBool hasNext() {
    994         return pos<LENGTHOF(s);
    995     }
    996 
    997     virtual UChar first() {
    998         pos=0;
    999         return s[0];
   1000     }
   1001 
   1002     virtual UChar32 first32() {
   1003         UChar32 c;
   1004         pos=0;
   1005         U16_NEXT(s, pos, LENGTHOF(s), c);
   1006         pos=0;
   1007         return c;
   1008     }
   1009 
   1010     virtual UChar setIndex(int32_t position) {
   1011         if(0<=position && position<=LENGTHOF(s)) {
   1012             pos=position;
   1013             if(pos<LENGTHOF(s)) {
   1014                 return s[pos];
   1015             }
   1016         }
   1017         return DONE;
   1018     }
   1019 
   1020     virtual UChar32 setIndex32(int32_t position) {
   1021         if(0<=position && position<=LENGTHOF(s)) {
   1022             pos=position;
   1023             if(pos<LENGTHOF(s)) {
   1024                 UChar32 c;
   1025                 U16_GET(s, 0, pos, LENGTHOF(s), c);
   1026                 return c;
   1027             }
   1028         }
   1029         return DONE;
   1030     }
   1031 
   1032     virtual UChar current() const {
   1033         if(pos<LENGTHOF(s)) {
   1034             return s[pos];
   1035         } else {
   1036             return DONE;
   1037         }
   1038     }
   1039 
   1040     virtual UChar32 current32() const {
   1041         if(pos<LENGTHOF(s)) {
   1042             UChar32 c;
   1043             U16_GET(s, 0, pos, LENGTHOF(s), c);
   1044             return c;
   1045         } else {
   1046             return DONE;
   1047         }
   1048     }
   1049 
   1050     virtual UChar next() {
   1051         if(pos<LENGTHOF(s) && ++pos<LENGTHOF(s)) {
   1052             return s[pos];
   1053         } else {
   1054             return DONE;
   1055         }
   1056     }
   1057 
   1058     virtual UChar32 next32() {
   1059         if(pos<LENGTHOF(s)) {
   1060             U16_FWD_1(s, pos, LENGTHOF(s));
   1061         }
   1062         if(pos<LENGTHOF(s)) {
   1063             UChar32 c;
   1064             int32_t i=pos;
   1065             U16_NEXT(s, i, LENGTHOF(s), c);
   1066             return c;
   1067         } else {
   1068             return DONE;
   1069         }
   1070     }
   1071 
   1072     virtual UBool hasPrevious() {
   1073         return pos>0;
   1074     }
   1075 
   1076     virtual void getText(UnicodeString &result) {
   1077         result.setTo(s, LENGTHOF(s));
   1078     }
   1079 
   1080     // dummy implementations of other pure virtual base class functions
   1081     virtual UBool operator==(const ForwardCharacterIterator &that) const {
   1082         return
   1083             this==&that ||
   1084             getDynamicClassID()==that.getDynamicClassID() && pos==((SubCharIter &)that).pos;
   1085     }
   1086 
   1087     virtual int32_t hashCode() const {
   1088         return 2;
   1089     }
   1090 
   1091     virtual CharacterIterator *clone() const {
   1092         return NULL;
   1093     }
   1094 
   1095     virtual UChar last() {
   1096         return 0;
   1097     }
   1098 
   1099     virtual UChar32 last32() {
   1100         return 0;
   1101     }
   1102 
   1103     virtual UChar previous() {
   1104         return 0;
   1105     }
   1106 
   1107     virtual UChar32 previous32() {
   1108         return 0;
   1109     }
   1110 
   1111     virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) {
   1112         return 0;
   1113     }
   1114 
   1115     virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) {
   1116         return 0;
   1117     }
   1118 
   1119     // RTTI
   1120     static UClassID getStaticClassID() {
   1121         return (UClassID)(&fgClassID);
   1122     }
   1123 
   1124     virtual UClassID getDynamicClassID() const {
   1125         return getStaticClassID();
   1126     }
   1127 
   1128 private:
   1129     // dummy string data
   1130     UChar s[4];
   1131 
   1132     static const char fgClassID;
   1133 };
   1134 
   1135 const char SubCharIter::fgClassID = 0;
   1136 
   1137 class SubStringCharIter : public StringCharacterIterator {
   1138 public:
   1139     SubStringCharIter() {
   1140         setText(UNICODE_STRING("abc", 3));
   1141     }
   1142 };
   1143 
   1144 class SubUCharCharIter : public UCharCharacterIterator {
   1145 public:
   1146     SubUCharCharIter() {
   1147         setText(u, 3);
   1148     }
   1149 
   1150 private:
   1151     static const UChar u[3];
   1152 };
   1153 
   1154 const UChar SubUCharCharIter::u[3]={ 0x61, 0x62, 0x63 };
   1155 
   1156 void CharIterTest::TestCharIteratorSubClasses() {
   1157     SubCharIter *p;
   1158 
   1159     // coverage - call functions that are not otherwise tested
   1160     // first[32]PostInc() are default implementations that are overridden
   1161     // in ICU's own CharacterIterator subclasses
   1162     p=new SubCharIter;
   1163     if(p->firstPostInc()!=0x61) {
   1164         errln("SubCharIter.firstPosInc() failed\n");
   1165     }
   1166     delete p;
   1167 
   1168     p=new SubCharIter[2];
   1169     if(p[1].first32PostInc()!=0x61) {
   1170         errln("SubCharIter.first32PosInc() failed\n");
   1171     }
   1172     delete [] p;
   1173 
   1174     // coverage: StringCharacterIterator default constructor
   1175     SubStringCharIter sci;
   1176     if(sci.firstPostInc()!=0x61) {
   1177         errln("SubStringCharIter.firstPostInc() failed\n");
   1178     }
   1179 
   1180     // coverage: UCharCharacterIterator default constructor
   1181     SubUCharCharIter uci;
   1182     if(uci.firstPostInc()!=0x61) {
   1183         errln("SubUCharCharIter.firstPostInc() failed\n");
   1184     }
   1185 }
   1186