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