1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 2000-2009, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * Date Name Description
9 * 03/22/00 aliu Creation.
10 * 07/13/00 Madhu Added more tests
11 *******************************************************************************
16 #include "unicode/ctest.h"
17 #include "unicode/ustring.h"
20 /**********************************************************************
22 *********************************************************************/
24 static void TestBasic(void);
25 static void TestOtherAPI(void);
26 static void hashIChars(void);
28 static int32_t U_EXPORT2 U_CALLCONV
hashChars(const UHashTok key
);
30 static UBool U_EXPORT2 U_CALLCONV
isEqualChars(const UHashTok key1
, const UHashTok key2
);
32 static void _put(UHashtable
* hash
,
35 int32_t expectedOldValue
);
37 static void _get(UHashtable
* hash
,
39 int32_t expectedValue
);
41 static void _remove(UHashtable
* hash
,
43 int32_t expectedValue
);
45 void addHashtableTest(TestNode
** root
);
47 /**********************************************************************
48 * UHashTok wrapper functions
49 *********************************************************************/
52 _compareChars(const void* a
, const void* b
) {
54 s
.pointer
= (void *)a
;
55 t
.pointer
= (void *)b
;
56 return uhash_compareChars(s
, t
);
60 _compareIChars(const void* a
, const void* b
) {
62 s
.pointer
= (void *)a
;
63 t
.pointer
= (void *)b
;
64 return uhash_compareIChars(s
, t
);
68 _compareUChars(const void* a
, const void* b
) {
70 s
.pointer
= (void *)a
;
71 t
.pointer
= (void *)b
;
72 return uhash_compareUChars(s
, t
);
76 _compareLong(int32_t a
, int32_t b
) {
80 return uhash_compareLong(s
, t
);
83 /**********************************************************************
85 *********************************************************************/
87 void addHashtableTest(TestNode
** root
) {
89 addTest(root
, &TestBasic
, "tsutil/chashtst/TestBasic");
90 addTest(root
, &TestOtherAPI
, "tsutil/chashtst/TestOtherAPI");
91 addTest(root
, &hashIChars
, "tsutil/chashtst/hashIChars");
95 /**********************************************************************
97 *********************************************************************/
99 static void TestBasic(void) {
100 static const char one
[4] = {0x6F, 0x6E, 0x65, 0}; /* "one" */
101 static const char one2
[4] = {0x6F, 0x6E, 0x65, 0}; /* Get around compiler optimizations */
102 static const char two
[4] = {0x74, 0x77, 0x6F, 0}; /* "two" */
103 static const char three
[6] = {0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* "three" */
104 static const char omega
[6] = {0x6F, 0x6D, 0x65, 0x67, 0x61, 0}; /* "omega" */
105 UErrorCode status
= U_ZERO_ERROR
;
108 hash
= uhash_open(hashChars
, isEqualChars
, NULL
, &status
);
109 if (U_FAILURE(status
)) {
110 log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
111 u_errorName(status
), hash
);
115 log_err("FAIL: uhash_open returned NULL\n");
118 log_verbose("Ok: uhash_open returned 0x%08X\n", hash
);
120 _put(hash
, one
, 1, 0);
121 _put(hash
, omega
, 24, 0);
122 _put(hash
, two
, 2, 0);
123 _put(hash
, three
, 3, 0);
124 _put(hash
, one
, -1, 1);
125 _put(hash
, two
, -2, 2);
126 _put(hash
, omega
, 48, 24);
127 _put(hash
, one
, 100, -1);
128 _get(hash
, three
, 3);
129 _remove(hash
, two
, -2);
131 _get(hash
, one
, 100);
132 _put(hash
, two
, 200, 0);
133 _get(hash
, omega
, 48);
134 _get(hash
, two
, 200);
136 if(_compareChars((void*)one
, (void*)three
) == TRUE
||
137 _compareChars((void*)one
, (void*)one2
) != TRUE
||
138 _compareChars((void*)one
, (void*)one
) != TRUE
||
139 _compareChars((void*)one
, NULL
) == TRUE
) {
140 log_err("FAIL: compareChars failed\n");
142 if(_compareIChars((void*)one
, (void*)three
) == TRUE
||
143 _compareIChars((void*)one
, (void*)one
) != TRUE
||
144 _compareIChars((void*)one
, (void*)one2
) != TRUE
||
145 _compareIChars((void*)one
, NULL
) == TRUE
) {
146 log_err("FAIL: compareIChars failed\n");
153 static void TestOtherAPI(void){
155 UErrorCode status
= U_ZERO_ERROR
;
158 /* Use the correct type when cast to void * */
159 static const UChar one
[4] = {0x006F, 0x006E, 0x0065, 0}; /* L"one" */
160 static const UChar one2
[4] = {0x006F, 0x006E, 0x0065, 0}; /* Get around compiler optimizations */
161 static const UChar two
[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
162 static const UChar two2
[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
163 static const UChar three
[6] = {0x0074, 0x0068, 0x0072, 0x0065, 0x0065, 0}; /* L"three" */
164 static const UChar four
[6] = {0x0066, 0x006F, 0x0075, 0x0072, 0}; /* L"four" */
165 static const UChar five
[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
166 static const UChar five2
[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
168 hash
= uhash_open(uhash_hashUChars
, uhash_compareUChars
, NULL
, &status
);
169 if (U_FAILURE(status
)) {
170 log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
171 u_errorName(status
), hash
);
175 log_err("FAIL: uhash_open returned NULL\n");
178 log_verbose("Ok: uhash_open returned 0x%08X\n", hash
);
180 uhash_puti(hash
, (void*)one
, 1, &status
);
181 if(uhash_count(hash
) != 1){
182 log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash
));
184 if(uhash_find(hash
, (void*)two
) != NULL
){
185 log_err("FAIL: uhash_find failed\n");
187 uhash_puti(hash
, (void*)two
, 2, &status
);
188 uhash_puti(hash
, (void*)three
, 3, &status
);
189 uhash_puti(hash
, (void*)four
, 4, &status
);
190 uhash_puti(hash
, (void*)five
, 5, &status
);
192 if(uhash_count(hash
) != 5){
193 log_err("FAIL: uhas_count() failed. Expected: 5, Got: %d\n", uhash_count(hash
));
196 if(uhash_geti(hash
, (void*)two2
) != 2){
197 log_err("FAIL: uhash_geti failed\n");
200 if(uhash_find(hash
, (void*)two2
) == NULL
){
201 log_err("FAIL: uhash_find of \"two\" failed\n");
204 if(uhash_removei(hash
, (void*)five2
) != 5){
205 log_err("FAIL: uhash_remove() failed\n");
207 if(uhash_count(hash
) != 4){
208 log_err("FAIL: uhas_count() failed. Expected: 4, Got: %d\n", uhash_count(hash
));
211 uhash_put(hash
, (void*)one
, NULL
, &status
);
212 if(uhash_count(hash
) != 3){
213 log_err("FAIL: uhash_put() with value=NULL didn't remove the key value pair\n");
215 status
=U_ILLEGAL_ARGUMENT_ERROR
;
216 uhash_puti(hash
, (void*)one
, 1, &status
);
217 if(uhash_count(hash
) != 3){
218 log_err("FAIL: uhash_put() with value!=NULL should fail when status != U_ZERO_ERROR \n");
222 uhash_puti(hash
, (void*)one
, 1, &status
);
223 if(uhash_count(hash
) != 4){
224 log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n");
227 if(_compareUChars((void*)one
, (void*)two
) == TRUE
||
228 _compareUChars((void*)one
, (void*)one
) != TRUE
||
229 _compareUChars((void*)one
, (void*)one2
) != TRUE
||
230 _compareUChars((void*)one
, NULL
) == TRUE
) {
231 log_err("FAIL: compareUChars failed\n");
234 uhash_removeAll(hash
);
235 if(uhash_count(hash
) != 0){
236 log_err("FAIL: uhas_count() failed. Expected: 0, Got: %d\n", uhash_count(hash
));
239 uhash_setKeyComparator(hash
, uhash_compareLong
);
240 uhash_setKeyHasher(hash
, uhash_hashLong
);
241 uhash_iputi(hash
, 1001, 1, &status
);
242 uhash_iputi(hash
, 1002, 2, &status
);
243 uhash_iputi(hash
, 1003, 3, &status
);
244 if(_compareLong(1001, 1002) == TRUE
||
245 _compareLong(1001, 1001) != TRUE
||
246 _compareLong(1001, 0) == TRUE
) {
247 log_err("FAIL: compareLong failed\n");
249 /*set the resize policy to just GROW and SHRINK*/
250 /*how to test this??*/
251 uhash_setResizePolicy(hash
, U_GROW_AND_SHRINK
);
252 uhash_iputi(hash
, 1004, 4, &status
);
253 uhash_iputi(hash
, 1005, 5, &status
);
254 uhash_iputi(hash
, 1006, 6, &status
);
255 if(uhash_count(hash
) != 6){
256 log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash
));
258 if(uhash_iremovei(hash
, 1004) != 4){
259 log_err("FAIL: uhash_remove failed\n");
261 if(uhash_iremovei(hash
, 1004) != 0){
262 log_err("FAIL: uhash_remove failed\n");
265 uhash_removeAll(hash
);
266 uhash_iput(hash
, 2004, (void*)one
, &status
);
267 uhash_iput(hash
, 2005, (void*)two
, &status
);
268 if(uhash_count(hash
) != 2){
269 log_err("FAIL: uhash_count() failed. Expected: 2, Got: %d\n", uhash_count(hash
));
271 if(uhash_iremove(hash
, 2004) != (void*)one
){
272 log_err("FAIL: uhash_remove failed\n");
274 if(uhash_iremove(hash
, 2004) != NULL
){
275 log_err("FAIL: uhash_remove failed\n");
277 if(uhash_count(hash
) != 1){
278 log_err("FAIL: uhash_count() failed. Expected: 1, Got: %d\n", uhash_count(hash
));
285 static void hashIChars(void) {
286 static const char which
[] = "which";
287 static const char WHICH2
[] = "WHICH";
288 static const char where
[] = "where";
289 UErrorCode status
= U_ZERO_ERROR
;
292 hash
= uhash_open(uhash_hashIChars
, uhash_compareIChars
, NULL
, &status
);
293 if (U_FAILURE(status
)) {
294 log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
295 u_errorName(status
), hash
);
299 log_err("FAIL: uhash_open returned NULL\n");
302 log_verbose("Ok: uhash_open returned 0x%08X\n", hash
);
304 _put(hash
, which
, 1, 0);
305 _put(hash
, WHICH2
, 2, 1);
306 _put(hash
, where
, 3, 0);
307 if(uhash_count(hash
) != 2){
308 log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash
));
310 _remove(hash
, which
, 2);
316 /**********************************************************************
318 *********************************************************************/
321 * This hash function is designed to collide a lot to test key equality
322 * resolution. It only uses the first char.
324 static int32_t U_EXPORT2 U_CALLCONV
hashChars(const UHashTok key
) {
325 return *(const char*) key
.pointer
;
328 static UBool U_EXPORT2 U_CALLCONV
isEqualChars(const UHashTok key1
, const UHashTok key2
) {
329 return (UBool
)((key1
.pointer
!= NULL
) &&
330 (key2
.pointer
!= NULL
) &&
331 (uprv_strcmp((const char*)key1
.pointer
, (const char*)key2
.pointer
) == 0));
334 /**********************************************************************
336 *********************************************************************/
338 static void _put(UHashtable
* hash
,
341 int32_t expectedOldValue
) {
342 UErrorCode status
= U_ZERO_ERROR
;
344 uhash_puti(hash
, (void*) key
, value
, &status
);
345 if (U_FAILURE(status
)) {
346 log_err("FAIL: uhash_put(%s) failed with %s and returned %ld\n",
347 key
, u_errorName(status
), oldValue
);
348 } else if (oldValue
!= expectedOldValue
) {
349 log_err("FAIL: uhash_put(%s) returned old value %ld; expected %ld\n",
350 key
, oldValue
, expectedOldValue
);
352 log_verbose("Ok: uhash_put(%s, %d) returned old value %ld\n",
353 key
, value
, oldValue
);
357 static void _get(UHashtable
* hash
,
359 int32_t expectedValue
) {
360 UErrorCode status
= U_ZERO_ERROR
;
361 int32_t value
= uhash_geti(hash
, key
);
362 if (U_FAILURE(status
)) {
363 log_err("FAIL: uhash_get(%s) failed with %s and returned %ld\n",
364 key
, u_errorName(status
), value
);
365 } else if (value
!= expectedValue
) {
366 log_err("FAIL: uhash_get(%s) returned %ld; expected %ld\n",
367 key
, value
, expectedValue
);
369 log_verbose("Ok: uhash_get(%s) returned value %ld\n",
374 static void _remove(UHashtable
* hash
,
376 int32_t expectedValue
) {
377 int32_t value
= uhash_removei(hash
, key
);
378 if (value
!= expectedValue
) {
379 log_err("FAIL: uhash_remove(%s) returned %ld; expected %ld\n",
380 key
, value
, expectedValue
);
382 log_verbose("Ok: uhash_remove(%s) returned old value %ld\n",