unit1603.c (7217B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 #include "unitcheck.h" 25 26 #include "hash.h" 27 28 #include "memdebug.h" /* LAST include file */ 29 30 static const size_t slots = 3; 31 32 static void t1603_mydtor(void *p) 33 { 34 /* Data are statically allocated */ 35 (void)p; /* unused */ 36 } 37 38 static size_t elem_dtor_calls; 39 40 static void my_elem_dtor(void *key, size_t key_len, void *p) 41 { 42 (void)p; /* unused */ 43 (void)key; /* unused */ 44 (void)key_len; /* unused */ 45 ++elem_dtor_calls; 46 } 47 48 static CURLcode t1603_setup(struct Curl_hash *hash_static) 49 { 50 Curl_hash_init(hash_static, slots, Curl_hash_str, 51 curlx_str_key_compare, t1603_mydtor); 52 return CURLE_OK; 53 } 54 55 static void t1603_stop(struct Curl_hash *hash_static) 56 { 57 Curl_hash_destroy(hash_static); 58 } 59 60 static CURLcode test_unit1603(char *arg) 61 { 62 struct Curl_hash hash_static; 63 64 UNITTEST_BEGIN(t1603_setup(&hash_static)) 65 66 char key1[] = "key1"; 67 char key2[] = "key2b"; 68 char key3[] = "key3"; 69 char key4[] = "key4"; 70 char notakey[] = "notakey"; 71 char *nodep; 72 int rc; 73 74 /* Ensure the key hashes are as expected in order to test both hash 75 collisions and a full table. Unfortunately, the hashes can vary 76 between architectures. */ 77 if(Curl_hash_str(key1, strlen(key1), slots) != 1 || 78 Curl_hash_str(key2, strlen(key2), slots) != 0 || 79 Curl_hash_str(key3, strlen(key3), slots) != 2 || 80 Curl_hash_str(key4, strlen(key4), slots) != 1) 81 curl_mfprintf(stderr, 82 "Warning: hashes are not computed as expected on this " 83 "architecture; test coverage will be less comprehensive\n"); 84 85 nodep = Curl_hash_add(&hash_static, &key1, strlen(key1), &key1); 86 fail_unless(nodep, "insertion into hash failed"); 87 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 88 fail_unless(nodep == key1, "hash retrieval failed"); 89 90 nodep = Curl_hash_add(&hash_static, &key2, strlen(key2), &key2); 91 fail_unless(nodep, "insertion into hash failed"); 92 nodep = Curl_hash_pick(&hash_static, &key2, strlen(key2)); 93 fail_unless(nodep == key2, "hash retrieval failed"); 94 95 nodep = Curl_hash_add(&hash_static, &key3, strlen(key3), &key3); 96 fail_unless(nodep, "insertion into hash failed"); 97 nodep = Curl_hash_pick(&hash_static, &key3, strlen(key3)); 98 fail_unless(nodep == key3, "hash retrieval failed"); 99 100 /* The fourth element exceeds the number of slots & collides */ 101 nodep = Curl_hash_add(&hash_static, &key4, strlen(key4), &key4); 102 fail_unless(nodep, "insertion into hash failed"); 103 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 104 fail_unless(nodep == key4, "hash retrieval failed"); 105 106 /* Make sure all elements are still accessible */ 107 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 108 fail_unless(nodep == key1, "hash retrieval failed"); 109 nodep = Curl_hash_pick(&hash_static, &key2, strlen(key2)); 110 fail_unless(nodep == key2, "hash retrieval failed"); 111 nodep = Curl_hash_pick(&hash_static, &key3, strlen(key3)); 112 fail_unless(nodep == key3, "hash retrieval failed"); 113 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 114 fail_unless(nodep == key4, "hash retrieval failed"); 115 116 /* Delete the second of two entries in a bucket */ 117 rc = Curl_hash_delete(&hash_static, &key4, strlen(key4)); 118 fail_unless(rc == 0, "hash delete failed"); 119 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 120 fail_unless(nodep == key1, "hash retrieval failed"); 121 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 122 fail_unless(!nodep, "hash retrieval should have failed"); 123 124 /* Insert that deleted node again */ 125 nodep = Curl_hash_add(&hash_static, &key4, strlen(key4), &key4); 126 fail_unless(nodep, "insertion into hash failed"); 127 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 128 fail_unless(nodep == key4, "hash retrieval failed"); 129 130 /* Delete the first of two entries in a bucket */ 131 rc = Curl_hash_delete(&hash_static, &key1, strlen(key1)); 132 fail_unless(rc == 0, "hash delete failed"); 133 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 134 fail_unless(!nodep, "hash retrieval should have failed"); 135 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 136 fail_unless(nodep == key4, "hash retrieval failed"); 137 138 /* Delete the remaining one of two entries in a bucket */ 139 rc = Curl_hash_delete(&hash_static, &key4, strlen(key4)); 140 fail_unless(rc == 0, "hash delete failed"); 141 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 142 fail_unless(!nodep, "hash retrieval should have failed"); 143 nodep = Curl_hash_pick(&hash_static, &key4, strlen(key4)); 144 fail_unless(!nodep, "hash retrieval should have failed"); 145 146 /* Delete an already deleted node */ 147 rc = Curl_hash_delete(&hash_static, &key4, strlen(key4)); 148 fail_unless(rc, "hash delete should have failed"); 149 150 /* Replace an existing node */ 151 nodep = Curl_hash_add(&hash_static, &key1, strlen(key1), ¬akey); 152 fail_unless(nodep, "insertion into hash failed"); 153 nodep = Curl_hash_pick(&hash_static, &key1, strlen(key1)); 154 fail_unless(nodep == notakey, "hash retrieval failed"); 155 156 /* Make sure all remaining elements are still accessible */ 157 nodep = Curl_hash_pick(&hash_static, &key2, strlen(key2)); 158 fail_unless(nodep == key2, "hash retrieval failed"); 159 nodep = Curl_hash_pick(&hash_static, &key3, strlen(key3)); 160 fail_unless(nodep == key3, "hash retrieval failed"); 161 162 /* Add element with own destructor */ 163 nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1, 164 my_elem_dtor); 165 fail_unless(nodep, "add2 insertion into hash failed"); 166 fail_unless(elem_dtor_calls == 0, "element destructor count should be 0"); 167 /* Add it again, should invoke destructor on first */ 168 nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1, 169 my_elem_dtor); 170 fail_unless(nodep, "add2 again, insertion into hash failed"); 171 fail_unless(elem_dtor_calls == 1, "element destructor count should be 1"); 172 /* remove, should invoke destructor */ 173 rc = Curl_hash_delete(&hash_static, &key1, strlen(key1)); 174 fail_unless(rc == 0, "hash delete failed"); 175 fail_unless(elem_dtor_calls == 2, "element destructor count should be 1"); 176 177 /* Clean up */ 178 Curl_hash_clean(&hash_static); 179 180 UNITTEST_END(t1603_stop(&hash_static)) 181 }