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