Home | History | Annotate | Download | only in cintltst
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2002-2012, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *   file name:  uenumtst.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:2
     12 *
     13 *   created on: 2002jul08
     14 *   created by: Vladimir Weinstein
     15 */
     16 
     17 #include "cintltst.h"
     18 #include "uenumimp.h"
     19 #include "cmemory.h"
     20 #include "cstring.h"
     21 #include "unicode/ustring.h"
     22 
     23 static char quikBuf[256];
     24 static char* quikU2C(const UChar* str, int32_t len) {
     25     u_UCharsToChars(str, quikBuf, len);
     26     quikBuf[len] = 0;
     27     return quikBuf;
     28 }
     29 
     30 static const char* test1[] = {
     31     "first",
     32     "second",
     33     "third",
     34     "fourth"
     35 };
     36 
     37 struct chArrayContext {
     38     int32_t currIndex;
     39     int32_t maxIndex;
     40     char *currChar;
     41     UChar *currUChar;
     42     char **array;
     43 };
     44 
     45 typedef struct chArrayContext chArrayContext;
     46 
     47 #define cont ((chArrayContext *)en->context)
     48 
     49 static void U_CALLCONV
     50 chArrayClose(UEnumeration *en) {
     51     if(cont->currUChar != NULL) {
     52         free(cont->currUChar);
     53         cont->currUChar = NULL;
     54     }
     55     free(en);
     56 }
     57 
     58 static int32_t U_CALLCONV
     59 chArrayCount(UEnumeration *en, UErrorCode *status) {
     60     return cont->maxIndex;
     61 }
     62 
     63 static const UChar* U_CALLCONV
     64 chArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
     65     if(cont->currIndex >= cont->maxIndex) {
     66         return NULL;
     67     }
     68 
     69     if(cont->currUChar == NULL) {
     70         cont->currUChar = (UChar *)malloc(1024*sizeof(UChar));
     71     }
     72 
     73     cont->currChar = (cont->array)[cont->currIndex];
     74     *resultLength = (int32_t)strlen(cont->currChar);
     75     u_charsToUChars(cont->currChar, cont->currUChar, *resultLength);
     76     cont->currIndex++;
     77     return cont->currUChar;
     78 }
     79 
     80 static const char* U_CALLCONV
     81 chArrayNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
     82     if(cont->currIndex >= cont->maxIndex) {
     83         return NULL;
     84     }
     85 
     86     cont->currChar = (cont->array)[cont->currIndex];
     87     *resultLength = (int32_t)strlen(cont->currChar);
     88     cont->currIndex++;
     89     return cont->currChar;
     90 }
     91 
     92 static void U_CALLCONV
     93 chArrayReset(UEnumeration *en, UErrorCode *status) {
     94     cont->currIndex = 0;
     95 }
     96 
     97 chArrayContext myCont = {
     98     0, 0,
     99     NULL, NULL,
    100     NULL
    101 };
    102 
    103 UEnumeration chEnum = {
    104     NULL,
    105     &myCont,
    106     chArrayClose,
    107     chArrayCount,
    108     chArrayUNext,
    109     chArrayNext,
    110     chArrayReset
    111 };
    112 
    113 static const UEnumeration emptyEnumerator = {
    114     NULL,
    115     NULL,
    116     NULL,
    117     NULL,
    118     NULL,
    119     NULL,
    120     NULL,
    121 };
    122 
    123 static const UEnumeration emptyPartialEnumerator = {
    124     NULL,
    125     NULL,
    126     NULL,
    127     NULL,
    128     uenum_unextDefault,
    129     NULL,
    130     NULL,
    131 };
    132 
    133 /********************************************************************/
    134 static const UChar _first[] = {102,105,114,115,116,0};    /* "first"  */
    135 static const UChar _second[]= {115,101,99,111,110,100,0}; /* "second" */
    136 static const UChar _third[] = {116,104,105,114,100,0};    /* "third"  */
    137 static const UChar _fourth[]= {102,111,117,114,116,104,0};/* "fourth" */
    138 
    139 static const UChar* test2[] = {
    140     _first, _second, _third, _fourth
    141 };
    142 
    143 struct uchArrayContext {
    144     int32_t currIndex;
    145     int32_t maxIndex;
    146     UChar *currUChar;
    147     UChar **array;
    148 };
    149 
    150 typedef struct uchArrayContext uchArrayContext;
    151 
    152 #define ucont ((uchArrayContext *)en->context)
    153 
    154 static void U_CALLCONV
    155 uchArrayClose(UEnumeration *en) {
    156     free(en);
    157 }
    158 
    159 static int32_t U_CALLCONV
    160 uchArrayCount(UEnumeration *en, UErrorCode *status) {
    161     return ucont->maxIndex;
    162 }
    163 
    164 static const UChar* U_CALLCONV
    165 uchArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
    166     if(ucont->currIndex >= ucont->maxIndex) {
    167         return NULL;
    168     }
    169 
    170     ucont->currUChar = (ucont->array)[ucont->currIndex];
    171     *resultLength = u_strlen(ucont->currUChar);
    172     ucont->currIndex++;
    173     return ucont->currUChar;
    174 }
    175 
    176 static void U_CALLCONV
    177 uchArrayReset(UEnumeration *en, UErrorCode *status) {
    178     ucont->currIndex = 0;
    179 }
    180 
    181 uchArrayContext myUCont = {
    182     0, 0,
    183     NULL, NULL
    184 };
    185 
    186 UEnumeration uchEnum = {
    187     NULL,
    188     &myUCont,
    189     uchArrayClose,
    190     uchArrayCount,
    191     uchArrayUNext,
    192     uenum_nextDefault,
    193     uchArrayReset
    194 };
    195 
    196 /********************************************************************/
    197 
    198 static UEnumeration *getchArrayEnum(const char** source, int32_t size) {
    199     UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration));
    200     memcpy(en, &chEnum, sizeof(UEnumeration));
    201     cont->array = (char **)source;
    202     cont->maxIndex = size;
    203     return en;
    204 }
    205 
    206 static void EnumerationTest(void) {
    207     UErrorCode status = U_ZERO_ERROR;
    208     int32_t len = 0;
    209     UEnumeration *en = getchArrayEnum(test1, sizeof(test1)/sizeof(test1[0]));
    210     const char *string = NULL;
    211     const UChar *uString = NULL;
    212     while ((string = uenum_next(en, &len, &status))) {
    213         log_verbose("read \"%s\", length %i\n", string, len);
    214     }
    215     uenum_reset(en, &status);
    216     while ((uString = uenum_unext(en, &len, &status))) {
    217         log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len);
    218     }
    219 
    220     uenum_close(en);
    221 }
    222 
    223 static void EmptyEnumerationTest(void) {
    224     UErrorCode status = U_ZERO_ERROR;
    225     UEnumeration *emptyEnum = uprv_malloc(sizeof(UEnumeration));
    226 
    227     uprv_memcpy(emptyEnum, &emptyEnumerator, sizeof(UEnumeration));
    228     if (uenum_count(emptyEnum, &status) != -1 || status != U_UNSUPPORTED_ERROR) {
    229         log_err("uenum_count failed\n");
    230     }
    231     status = U_ZERO_ERROR;
    232     if (uenum_next(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
    233         log_err("uenum_next failed\n");
    234     }
    235     status = U_ZERO_ERROR;
    236     if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
    237         log_err("uenum_unext failed\n");
    238     }
    239     status = U_ZERO_ERROR;
    240     uenum_reset(emptyEnum, &status);
    241     if (status != U_UNSUPPORTED_ERROR) {
    242         log_err("uenum_reset failed\n");
    243     }
    244     uenum_close(emptyEnum);
    245 
    246     status = U_ZERO_ERROR;
    247     if (uenum_next(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) {
    248         log_err("uenum_next(NULL) failed\n");
    249     }
    250     status = U_ZERO_ERROR;
    251     if (uenum_unext(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) {
    252         log_err("uenum_unext(NULL) failed\n");
    253     }
    254     status = U_ZERO_ERROR;
    255     uenum_reset(NULL, &status);
    256     if (status != U_ZERO_ERROR) {
    257         log_err("uenum_reset(NULL) failed\n");
    258     }
    259 
    260     emptyEnum = uprv_malloc(sizeof(UEnumeration));
    261     uprv_memcpy(emptyEnum, &emptyPartialEnumerator, sizeof(UEnumeration));
    262     status = U_ZERO_ERROR;
    263     if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
    264         log_err("partial uenum_unext failed\n");
    265     }
    266     uenum_close(emptyEnum);
    267 }
    268 
    269 static UEnumeration *getuchArrayEnum(const UChar** source, int32_t size) {
    270     UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration));
    271     memcpy(en, &uchEnum, sizeof(UEnumeration));
    272     ucont->array = (UChar **)source;
    273     ucont->maxIndex = size;
    274     return en;
    275 }
    276 
    277 static void DefaultNextTest(void) {
    278     UErrorCode status = U_ZERO_ERROR;
    279     int32_t len = 0;
    280     UEnumeration *en = getuchArrayEnum(test2, sizeof(test2)/sizeof(test2[0]));
    281     const char *string = NULL;
    282     const UChar *uString = NULL;
    283     while ((uString = uenum_unext(en, &len, &status))) {
    284         log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len);
    285     }
    286     if (U_FAILURE(status)) {
    287         log_err("FAIL: uenum_unext => %s\n", u_errorName(status));
    288     }
    289     uenum_reset(en, &status);
    290     while ((string = uenum_next(en, &len, &status))) {
    291         log_verbose("read \"%s\", length %i\n", string, len);
    292     }
    293     if (U_FAILURE(status)) {
    294         log_err("FAIL: uenum_next => %s\n", u_errorName(status));
    295     }
    296 
    297     uenum_close(en);
    298 }
    299 
    300 static void verifyEnumeration(int line, UEnumeration *u, const char * const * compareToChar, const UChar * const * compareToUChar, int32_t expect_count) {
    301   UErrorCode status = U_ZERO_ERROR;
    302   int32_t got_count,i,len;
    303   const char *c;
    304   UChar buf[1024];
    305 
    306   log_verbose("%s:%d: verifying enumeration..\n", __FILE__, line);
    307 
    308   uenum_reset(u, &status);
    309   if(U_FAILURE(status)) {
    310     log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
    311     return;
    312   }
    313 
    314   got_count = uenum_count(u, &status);
    315   if(U_FAILURE(status)) {
    316     log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
    317     return;
    318   }
    319 
    320   if(got_count!=expect_count) {
    321     log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__, line, expect_count, got_count);
    322   } else {
    323     log_verbose("%s:%d: OK: got count %d\n", __FILE__, line, got_count);
    324   }
    325 
    326   if(compareToChar!=NULL) { /* else, not invariant */
    327     for(i=0;i<got_count;i++) {
    328       c = uenum_next(u,&len, &status);
    329       if(U_FAILURE(status)) {
    330         log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE__, line, i, u_errorName(status));
    331         return;
    332       }
    333       if(c==NULL) {
    334         log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__, line, i, u_errorName(status));
    335         return;
    336       }
    337 
    338       if(strcmp(c,compareToChar[i])) {
    339         log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], c);
    340       } else {
    341         log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__, line, i, c);
    342       }
    343 
    344       if(len!=strlen(compareToChar[i])) {
    345         log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
    346       } else {
    347         log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__, line, i, len);
    348       }
    349     }
    350   }
    351 
    352   /* now try U */
    353   uenum_reset(u, &status);
    354   if(U_FAILURE(status)) {
    355     log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
    356     return;
    357   }
    358 
    359   for(i=0;i<got_count;i++) {
    360     const UChar *ustr = uenum_unext(u,&len, &status);
    361     if(U_FAILURE(status)) {
    362       log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
    363       return;
    364     }
    365     if(ustr==NULL) {
    366       log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
    367       return;
    368     }
    369     if(compareToChar!=NULL) {
    370       u_charsToUChars(compareToChar[i], buf, strlen(compareToChar[i])+1);
    371       if(u_strncmp(ustr,buf,len)) {
    372         int j;
    373         log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], austrdup(ustr));
    374         for(j=0;ustr[j]&&buf[j];j++) {
    375           log_verbose("  @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],buf[j]);
    376         }
    377       } else {
    378         log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, compareToChar[i]);
    379       }
    380 
    381       if(len!=strlen(compareToChar[i])) {
    382         log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
    383       } else {
    384         log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
    385       }
    386     }
    387 
    388     if(compareToUChar!=NULL) {
    389       if(u_strcmp(ustr,compareToUChar[i])) {
    390         int j;
    391         log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i]), austrdup(ustr));
    392         for(j=0;ustr[j]&&compareToUChar[j];j++) {
    393           log_verbose("  @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],compareToUChar[j]);
    394         }
    395       } else {
    396         log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i]));
    397       }
    398 
    399       if(len!=u_strlen(compareToUChar[i])) {
    400         log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, u_strlen(compareToUChar[i]), len);
    401       } else {
    402         log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
    403       }
    404     }
    405   }
    406 }
    407 
    408 
    409 
    410 
    411 
    412 static void TestCharStringsEnumeration(void)  {
    413   UErrorCode status = U_ZERO_ERROR;
    414 
    415   /* //! [uenum_openCharStringsEnumeration] */
    416   const char* strings[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" };
    417   UEnumeration *u = uenum_openCharStringsEnumeration(strings, 4, &status);
    418   /* //! [uenum_openCharStringsEnumeration] */
    419   if(U_FAILURE(status)) {
    420     log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(status));
    421     return;
    422   }
    423 
    424   verifyEnumeration(__LINE__, u, strings, NULL, 4);
    425 
    426   uenum_close(u);
    427 }
    428 
    429 static void TestUCharStringsEnumeration(void)  {
    430   UErrorCode status = U_ZERO_ERROR;
    431   /* //! [uenum_openUCharStringsEnumeration] */
    432   static const UChar nko_1[] = {0x07c1,0}, nko_2[] = {0x07c2}, nko_3[] = {0x07c3,0}, nko_4[] = {0x07c4,0};
    433   static const UChar* ustrings[] = {  nko_1, nko_2, nko_3, nko_4  };
    434   UEnumeration *u = uenum_openUCharStringsEnumeration(ustrings, 4, &status);
    435   /* //! [uenum_openUCharStringsEnumeration] */
    436   if(U_FAILURE(status)) {
    437     log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(status));
    438     return;
    439   }
    440 
    441   verifyEnumeration(__LINE__, u, NULL, ustrings, 4);
    442   uenum_close(u);
    443 
    444 
    445   u =  uenum_openUCharStringsEnumeration(test2, 4, &status);
    446   if(U_FAILURE(status)) {
    447     log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorName(status));
    448     return;
    449   }
    450   verifyEnumeration(__LINE__, u, test1, NULL, 4); /* same string */
    451   uenum_close(u);
    452 
    453 }
    454 
    455 void addEnumerationTest(TestNode** root);
    456 
    457 void addEnumerationTest(TestNode** root)
    458 {
    459     addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest");
    460     addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest");
    461     addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest");
    462     addTest(root, &TestCharStringsEnumeration, "tsutil/uenumtst/TestCharStringsEnumeration");
    463     addTest(root, &TestUCharStringsEnumeration, "tsutil/uenumtst/TestUCharStringsEnumeration");
    464 }
    465