Home | History | Annotate | Download | only in cintltst
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 2000-2009, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 *******************************************************************************
      6 *   Date        Name        Description
      7 *   03/22/00    aliu        Creation.
      8 *   07/13/00    Madhu       Added more tests
      9 *******************************************************************************
     10 */
     11 
     12 #include "cintltst.h"
     13 #include "uhash.h"
     14 #include "unicode/ctest.h"
     15 #include "unicode/ustring.h"
     16 #include "cstring.h"
     17 
     18 /**********************************************************************
     19  * Prototypes
     20  *********************************************************************/
     21 
     22 static void TestBasic(void);
     23 static void TestOtherAPI(void);
     24 static void hashIChars(void);
     25 
     26 static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key);
     27 
     28 static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2);
     29 
     30 static void _put(UHashtable* hash,
     31                  const char* key,
     32                  int32_t value,
     33                  int32_t expectedOldValue);
     34 
     35 static void _get(UHashtable* hash,
     36           const char* key,
     37           int32_t expectedValue);
     38 
     39 static void _remove(UHashtable* hash,
     40              const char* key,
     41              int32_t expectedValue);
     42 
     43 void addHashtableTest(TestNode** root);
     44 
     45 /**********************************************************************
     46  * UHashTok wrapper functions
     47  *********************************************************************/
     48 
     49 static UBool
     50 _compareChars(const void* a, const void* b) {
     51     UHashTok s, t;
     52     s.pointer = (void *)a;
     53     t.pointer = (void *)b;
     54     return uhash_compareChars(s, t);
     55 }
     56 
     57 static UBool
     58 _compareIChars(const void* a, const void* b) {
     59     UHashTok s, t;
     60     s.pointer = (void *)a;
     61     t.pointer = (void *)b;
     62     return uhash_compareIChars(s, t);
     63 }
     64 
     65 static UBool
     66 _compareUChars(const void* a, const void* b) {
     67     UHashTok s, t;
     68     s.pointer = (void *)a;
     69     t.pointer = (void *)b;
     70     return uhash_compareUChars(s, t);
     71 }
     72 
     73 static UBool
     74 _compareLong(int32_t a, int32_t b) {
     75     UHashTok s, t;
     76     s.integer = a;
     77     t.integer = b;
     78     return uhash_compareLong(s, t);
     79 }
     80 
     81 /**********************************************************************
     82  * FW Registration
     83  *********************************************************************/
     84 
     85 void addHashtableTest(TestNode** root) {
     86 
     87     addTest(root, &TestBasic,   "tsutil/chashtst/TestBasic");
     88     addTest(root, &TestOtherAPI, "tsutil/chashtst/TestOtherAPI");
     89     addTest(root, &hashIChars, "tsutil/chashtst/hashIChars");
     90 
     91 }
     92 
     93 /**********************************************************************
     94  * Test Functions
     95  *********************************************************************/
     96 
     97 static void TestBasic(void) {
     98     static const char one[4] =   {0x6F, 0x6E, 0x65, 0}; /* "one" */
     99     static const char one2[4] =  {0x6F, 0x6E, 0x65, 0}; /* Get around compiler optimizations */
    100     static const char two[4] =   {0x74, 0x77, 0x6F, 0}; /* "two" */
    101     static const char three[6] = {0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* "three" */
    102     static const char omega[6] = {0x6F, 0x6D, 0x65, 0x67, 0x61, 0}; /* "omega" */
    103     UErrorCode status = U_ZERO_ERROR;
    104     UHashtable *hash;
    105 
    106     hash = uhash_open(hashChars, isEqualChars, NULL,  &status);
    107     if (U_FAILURE(status)) {
    108         log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
    109                 u_errorName(status), hash);
    110         return;
    111     }
    112     if (hash == NULL) {
    113         log_err("FAIL: uhash_open returned NULL\n");
    114         return;
    115     }
    116     log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
    117 
    118     _put(hash, one, 1, 0);
    119     _put(hash, omega, 24, 0);
    120     _put(hash, two, 2, 0);
    121     _put(hash, three, 3, 0);
    122     _put(hash, one, -1, 1);
    123     _put(hash, two, -2, 2);
    124     _put(hash, omega, 48, 24);
    125     _put(hash, one, 100, -1);
    126     _get(hash, three, 3);
    127     _remove(hash, two, -2);
    128     _get(hash, two, 0);
    129     _get(hash, one, 100);
    130     _put(hash, two, 200, 0);
    131     _get(hash, omega, 48);
    132     _get(hash, two, 200);
    133 
    134     if(_compareChars((void*)one, (void*)three) == TRUE ||
    135         _compareChars((void*)one, (void*)one2) != TRUE ||
    136         _compareChars((void*)one, (void*)one) != TRUE ||
    137         _compareChars((void*)one, NULL) == TRUE  )  {
    138         log_err("FAIL: compareChars failed\n");
    139     }
    140     if(_compareIChars((void*)one, (void*)three) == TRUE ||
    141         _compareIChars((void*)one, (void*)one) != TRUE ||
    142         _compareIChars((void*)one, (void*)one2) != TRUE ||
    143         _compareIChars((void*)one, NULL) == TRUE  )  {
    144         log_err("FAIL: compareIChars failed\n");
    145     }
    146 
    147     uhash_close(hash);
    148 
    149 }
    150 
    151 static void TestOtherAPI(void){
    152 
    153     UErrorCode status = U_ZERO_ERROR;
    154     UHashtable *hash;
    155 
    156     /* Use the correct type when cast to void * */
    157     static const UChar one[4]   = {0x006F, 0x006E, 0x0065, 0}; /* L"one" */
    158     static const UChar one2[4]  = {0x006F, 0x006E, 0x0065, 0}; /* Get around compiler optimizations */
    159     static const UChar two[4]   = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
    160     static const UChar two2[4]  = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
    161     static const UChar three[6] = {0x0074, 0x0068, 0x0072, 0x0065, 0x0065, 0}; /* L"three" */
    162     static const UChar four[6]  = {0x0066, 0x006F, 0x0075, 0x0072, 0}; /* L"four" */
    163     static const UChar five[6]  = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
    164     static const UChar five2[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
    165 
    166     hash = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL,  &status);
    167     if (U_FAILURE(status)) {
    168         log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
    169                 u_errorName(status), hash);
    170         return;
    171     }
    172     if (hash == NULL) {
    173         log_err("FAIL: uhash_open returned NULL\n");
    174         return;
    175     }
    176     log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
    177 
    178     uhash_puti(hash, (void*)one, 1, &status);
    179     if(uhash_count(hash) != 1){
    180          log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
    181     }
    182     if(uhash_find(hash, (void*)two) != NULL){
    183         log_err("FAIL: uhash_find failed\n");
    184     }
    185     uhash_puti(hash, (void*)two, 2, &status);
    186     uhash_puti(hash, (void*)three, 3, &status);
    187     uhash_puti(hash, (void*)four, 4, &status);
    188     uhash_puti(hash, (void*)five, 5, &status);
    189 
    190     if(uhash_count(hash) != 5){
    191         log_err("FAIL: uhas_count() failed. Expected: 5, Got: %d\n", uhash_count(hash));
    192     }
    193 
    194     if(uhash_geti(hash, (void*)two2) != 2){
    195         log_err("FAIL: uhash_geti failed\n");
    196     }
    197 
    198     if(uhash_find(hash, (void*)two2) == NULL){
    199         log_err("FAIL: uhash_find of \"two\" failed\n");
    200     }
    201 
    202     if(uhash_removei(hash, (void*)five2) != 5){
    203         log_err("FAIL: uhash_remove() failed\n");
    204     }
    205     if(uhash_count(hash) != 4){
    206         log_err("FAIL: uhas_count() failed. Expected: 4, Got: %d\n", uhash_count(hash));
    207     }
    208 
    209     uhash_put(hash, (void*)one, NULL, &status);
    210     if(uhash_count(hash) != 3){
    211         log_err("FAIL: uhash_put() with value=NULL didn't remove the key value pair\n");
    212     }
    213     status=U_ILLEGAL_ARGUMENT_ERROR;
    214     uhash_puti(hash, (void*)one, 1, &status);
    215     if(uhash_count(hash) != 3){
    216         log_err("FAIL: uhash_put() with value!=NULL should fail when status != U_ZERO_ERROR \n");
    217     }
    218 
    219     status=U_ZERO_ERROR;
    220     uhash_puti(hash, (void*)one, 1, &status);
    221     if(uhash_count(hash) != 4){
    222         log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n");
    223     }
    224 
    225     if(_compareUChars((void*)one, (void*)two) == TRUE ||
    226         _compareUChars((void*)one, (void*)one) != TRUE ||
    227         _compareUChars((void*)one, (void*)one2) != TRUE ||
    228         _compareUChars((void*)one, NULL) == TRUE  )  {
    229         log_err("FAIL: compareUChars failed\n");
    230     }
    231 
    232     uhash_removeAll(hash);
    233     if(uhash_count(hash) != 0){
    234         log_err("FAIL: uhas_count() failed. Expected: 0, Got: %d\n", uhash_count(hash));
    235     }
    236 
    237     uhash_setKeyComparator(hash, uhash_compareLong);
    238     uhash_setKeyHasher(hash, uhash_hashLong);
    239     uhash_iputi(hash, 1001, 1, &status);
    240     uhash_iputi(hash, 1002, 2, &status);
    241     uhash_iputi(hash, 1003, 3, &status);
    242     if(_compareLong(1001, 1002) == TRUE ||
    243         _compareLong(1001, 1001) != TRUE ||
    244         _compareLong(1001, 0) == TRUE  )  {
    245         log_err("FAIL: compareLong failed\n");
    246     }
    247     /*set the resize policy to just GROW and SHRINK*/
    248          /*how to test this??*/
    249     uhash_setResizePolicy(hash, U_GROW_AND_SHRINK);
    250     uhash_iputi(hash, 1004, 4, &status);
    251     uhash_iputi(hash, 1005, 5, &status);
    252     uhash_iputi(hash, 1006, 6, &status);
    253     if(uhash_count(hash) != 6){
    254         log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash));
    255     }
    256     if(uhash_iremovei(hash, 1004) != 4){
    257         log_err("FAIL: uhash_remove failed\n");
    258     }
    259     if(uhash_iremovei(hash, 1004) != 0){
    260         log_err("FAIL: uhash_remove failed\n");
    261     }
    262 
    263     uhash_removeAll(hash);
    264     uhash_iput(hash, 2004, (void*)one, &status);
    265     uhash_iput(hash, 2005, (void*)two, &status);
    266     if(uhash_count(hash) != 2){
    267         log_err("FAIL: uhash_count() failed. Expected: 2, Got: %d\n", uhash_count(hash));
    268     }
    269     if(uhash_iremove(hash, 2004) != (void*)one){
    270         log_err("FAIL: uhash_remove failed\n");
    271     }
    272     if(uhash_iremove(hash, 2004) != NULL){
    273         log_err("FAIL: uhash_remove failed\n");
    274     }
    275     if(uhash_count(hash) != 1){
    276         log_err("FAIL: uhash_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
    277     }
    278 
    279     uhash_close(hash);
    280 
    281 }
    282 
    283 static void hashIChars(void) {
    284     static const char which[] = "which";
    285     static const char WHICH2[] = "WHICH";
    286     static const char where[] = "where";
    287     UErrorCode status = U_ZERO_ERROR;
    288     UHashtable *hash;
    289 
    290     hash = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &status);
    291     if (U_FAILURE(status)) {
    292         log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
    293                 u_errorName(status), hash);
    294         return;
    295     }
    296     if (hash == NULL) {
    297         log_err("FAIL: uhash_open returned NULL\n");
    298         return;
    299     }
    300     log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
    301 
    302     _put(hash, which, 1, 0);
    303     _put(hash, WHICH2, 2, 1);
    304     _put(hash, where, 3, 0);
    305     if(uhash_count(hash) != 2){
    306          log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
    307     }
    308     _remove(hash, which, 2);
    309 
    310     uhash_close(hash);
    311 }
    312 
    313 
    314 /**********************************************************************
    315  * uhash Callbacks
    316  *********************************************************************/
    317 
    318 /**
    319  * This hash function is designed to collide a lot to test key equality
    320  * resolution.  It only uses the first char.
    321  */
    322 static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key) {
    323     return *(const char*) key.pointer;
    324 }
    325 
    326 static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2) {
    327     return (UBool)((key1.pointer != NULL) &&
    328         (key2.pointer != NULL) &&
    329         (uprv_strcmp((const char*)key1.pointer, (const char*)key2.pointer) == 0));
    330 }
    331 
    332 /**********************************************************************
    333  * Wrapper Functions
    334  *********************************************************************/
    335 
    336 static void _put(UHashtable* hash,
    337           const char* key,
    338           int32_t value,
    339           int32_t expectedOldValue) {
    340     UErrorCode status = U_ZERO_ERROR;
    341     int32_t oldValue =
    342         uhash_puti(hash, (void*) key, value, &status);
    343     if (U_FAILURE(status)) {
    344         log_err("FAIL: uhash_put(%s) failed with %s and returned %ld\n",
    345                 key, u_errorName(status), oldValue);
    346     } else if (oldValue != expectedOldValue) {
    347         log_err("FAIL: uhash_put(%s) returned old value %ld; expected %ld\n",
    348                 key, oldValue, expectedOldValue);
    349     } else {
    350         log_verbose("Ok: uhash_put(%s, %d) returned old value %ld\n",
    351                     key, value, oldValue);
    352     }
    353 }
    354 
    355 static void _get(UHashtable* hash,
    356           const char* key,
    357           int32_t expectedValue) {
    358     UErrorCode status = U_ZERO_ERROR;
    359     int32_t value = uhash_geti(hash, key);
    360     if (U_FAILURE(status)) {
    361         log_err("FAIL: uhash_get(%s) failed with %s and returned %ld\n",
    362                 key, u_errorName(status), value);
    363     } else if (value != expectedValue) {
    364         log_err("FAIL: uhash_get(%s) returned %ld; expected %ld\n",
    365                 key, value, expectedValue);
    366     } else {
    367         log_verbose("Ok: uhash_get(%s) returned value %ld\n",
    368                     key, value);
    369     }
    370 }
    371 
    372 static void _remove(UHashtable* hash,
    373              const char* key,
    374              int32_t expectedValue) {
    375     int32_t value = uhash_removei(hash, key);
    376     if (value != expectedValue) {
    377         log_err("FAIL: uhash_remove(%s) returned %ld; expected %ld\n",
    378                 key, value, expectedValue);
    379     } else {
    380         log_verbose("Ok: uhash_remove(%s) returned old value %ld\n",
    381                     key, value);
    382     }
    383 }
    384 
    385