1 1.4 christos /* $NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $ */ 2 1.1 pgoyette 3 1.1 pgoyette /*- 4 1.1 pgoyette * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.1 pgoyette * All rights reserved. 6 1.1 pgoyette * 7 1.1 pgoyette * Redistribution and use in source and binary forms, with or without 8 1.1 pgoyette * modification, are permitted provided that the following conditions 9 1.1 pgoyette * are met: 10 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright 11 1.1 pgoyette * notice, this list of conditions and the following disclaimer. 12 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the 14 1.1 pgoyette * documentation and/or other materials provided with the distribution. 15 1.1 pgoyette * 16 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 pgoyette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 pgoyette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 pgoyette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 pgoyette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 pgoyette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 pgoyette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 pgoyette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 pgoyette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 pgoyette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 pgoyette * POSSIBILITY OF SUCH DAMAGE. 27 1.1 pgoyette */ 28 1.1 pgoyette 29 1.1 pgoyette /* 30 1.1 pgoyette * Copyright (c) 2001 Christopher G. Demetriou 31 1.1 pgoyette * All rights reserved. 32 1.2 jruoho * 33 1.1 pgoyette * Redistribution and use in source and binary forms, with or without 34 1.1 pgoyette * modification, are permitted provided that the following conditions 35 1.1 pgoyette * are met: 36 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright 37 1.1 pgoyette * notice, this list of conditions and the following disclaimer. 38 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright 39 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the 40 1.1 pgoyette * documentation and/or other materials provided with the distribution. 41 1.1 pgoyette * 3. All advertising materials mentioning features or use of this software 42 1.1 pgoyette * must display the following acknowledgement: 43 1.1 pgoyette * This product includes software developed for the 44 1.1 pgoyette * NetBSD Project. See http://www.NetBSD.org/ for 45 1.1 pgoyette * information about NetBSD. 46 1.1 pgoyette * 4. The name of the author may not be used to endorse or promote products 47 1.1 pgoyette * derived from this software without specific prior written permission. 48 1.2 jruoho * 49 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 50 1.1 pgoyette * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 51 1.1 pgoyette * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 52 1.1 pgoyette * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 53 1.1 pgoyette * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 54 1.1 pgoyette * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 1.1 pgoyette * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 1.1 pgoyette * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 1.1 pgoyette * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 58 1.1 pgoyette * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 1.2 jruoho * 60 1.1 pgoyette * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> 61 1.1 pgoyette */ 62 1.1 pgoyette 63 1.1 pgoyette #include <sys/cdefs.h> 64 1.1 pgoyette __COPYRIGHT("@(#) Copyright (c) 2008\ 65 1.1 pgoyette The NetBSD Foundation, inc. All rights reserved."); 66 1.4 christos __RCSID("$NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $"); 67 1.1 pgoyette 68 1.1 pgoyette #include <errno.h> 69 1.1 pgoyette #include <search.h> 70 1.1 pgoyette #include <string.h> 71 1.1 pgoyette #include <stdio.h> 72 1.4 christos #include <stdlib.h> 73 1.1 pgoyette 74 1.1 pgoyette #include <atf-c.h> 75 1.1 pgoyette 76 1.1 pgoyette #define REQUIRE_ERRNO(x) ATF_REQUIRE_MSG(x, "%s", strerror(errno)) 77 1.1 pgoyette 78 1.2 jruoho ATF_TC(hsearch_basic); 79 1.2 jruoho ATF_TC_HEAD(hsearch_basic, tc) 80 1.1 pgoyette { 81 1.1 pgoyette 82 1.1 pgoyette atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching"); 83 1.1 pgoyette } 84 1.1 pgoyette 85 1.2 jruoho ATF_TC_BODY(hsearch_basic, tc) 86 1.1 pgoyette { 87 1.1 pgoyette ENTRY e, *ep; 88 1.1 pgoyette char ch[2]; 89 1.1 pgoyette int i; 90 1.1 pgoyette 91 1.1 pgoyette REQUIRE_ERRNO(hcreate(16) != 0); 92 1.1 pgoyette 93 1.1 pgoyette /* ch[1] should be constant from here on down. */ 94 1.1 pgoyette ch[1] = '\0'; 95 1.1 pgoyette 96 1.1 pgoyette /* Basic insertions. Check enough that there'll be collisions. */ 97 1.1 pgoyette for (i = 0; i < 26; i++) { 98 1.1 pgoyette ch[0] = 'a' + i; 99 1.1 pgoyette e.key = strdup(ch); /* ptr to provided key is kept! */ 100 1.1 pgoyette ATF_REQUIRE(e.key != NULL); 101 1.4 christos e.data = (void *)(intptr_t)i; 102 1.1 pgoyette 103 1.1 pgoyette ep = hsearch(e, ENTER); 104 1.1 pgoyette 105 1.1 pgoyette ATF_REQUIRE(ep != NULL); 106 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, ch); 107 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, i); 108 1.1 pgoyette } 109 1.1 pgoyette 110 1.1 pgoyette /* e.key should be constant from here on down. */ 111 1.1 pgoyette e.key = ch; 112 1.1 pgoyette 113 1.1 pgoyette /* Basic lookups. */ 114 1.1 pgoyette for (i = 0; i < 26; i++) { 115 1.1 pgoyette ch[0] = 'a' + i; 116 1.1 pgoyette 117 1.1 pgoyette ep = hsearch(e, FIND); 118 1.1 pgoyette 119 1.1 pgoyette ATF_REQUIRE(ep != NULL); 120 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, ch); 121 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, i); 122 1.1 pgoyette } 123 1.1 pgoyette 124 1.4 christos hdestroy1(free, NULL); 125 1.1 pgoyette } 126 1.1 pgoyette 127 1.2 jruoho ATF_TC(hsearch_duplicate); 128 1.2 jruoho ATF_TC_HEAD(hsearch_duplicate, tc) 129 1.1 pgoyette { 130 1.1 pgoyette 131 1.1 pgoyette atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate " 132 1.1 pgoyette "doesn't overwrite existing data"); 133 1.1 pgoyette } 134 1.1 pgoyette 135 1.2 jruoho ATF_TC_BODY(hsearch_duplicate, tc) 136 1.1 pgoyette { 137 1.1 pgoyette ENTRY e, *ep; 138 1.1 pgoyette 139 1.1 pgoyette REQUIRE_ERRNO(hcreate(16)); 140 1.1 pgoyette 141 1.4 christos e.key = __UNCONST("a"); 142 1.4 christos e.data = (void *)(intptr_t) 0; 143 1.1 pgoyette 144 1.1 pgoyette ep = hsearch(e, ENTER); 145 1.1 pgoyette 146 1.1 pgoyette ATF_REQUIRE(ep != NULL); 147 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, "a"); 148 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 149 1.1 pgoyette 150 1.4 christos e.data = (void *)(intptr_t)12345; 151 1.1 pgoyette 152 1.1 pgoyette ep = hsearch(e, ENTER); 153 1.1 pgoyette ep = hsearch(e, FIND); 154 1.1 pgoyette 155 1.1 pgoyette ATF_REQUIRE(ep != NULL); 156 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, "a"); 157 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 158 1.1 pgoyette 159 1.1 pgoyette hdestroy(); 160 1.1 pgoyette } 161 1.1 pgoyette 162 1.2 jruoho ATF_TC(hsearch_nonexistent); 163 1.2 jruoho ATF_TC_HEAD(hsearch_nonexistent, tc) 164 1.1 pgoyette { 165 1.1 pgoyette 166 1.1 pgoyette atf_tc_set_md_var(tc, "descr", 167 1.1 pgoyette "Checks searching for non-existent entry"); 168 1.1 pgoyette } 169 1.1 pgoyette 170 1.2 jruoho ATF_TC_BODY(hsearch_nonexistent, tc) 171 1.1 pgoyette { 172 1.1 pgoyette ENTRY e, *ep; 173 1.1 pgoyette 174 1.1 pgoyette REQUIRE_ERRNO(hcreate(16)); 175 1.1 pgoyette 176 1.4 christos e.key = __UNCONST("A"); 177 1.1 pgoyette ep = hsearch(e, FIND); 178 1.1 pgoyette ATF_REQUIRE_EQ(ep, NULL); 179 1.1 pgoyette 180 1.1 pgoyette hdestroy(); 181 1.1 pgoyette } 182 1.1 pgoyette 183 1.2 jruoho ATF_TC(hsearch_two); 184 1.2 jruoho ATF_TC_HEAD(hsearch_two, tc) 185 1.1 pgoyette { 186 1.1 pgoyette 187 1.1 pgoyette atf_tc_set_md_var(tc, "descr", 188 1.1 pgoyette "Checks that searching doesn't overwrite previous search results"); 189 1.1 pgoyette } 190 1.1 pgoyette 191 1.2 jruoho ATF_TC_BODY(hsearch_two, tc) 192 1.1 pgoyette { 193 1.1 pgoyette ENTRY e, *ep, *ep2; 194 1.1 pgoyette 195 1.1 pgoyette REQUIRE_ERRNO(hcreate(16)); 196 1.1 pgoyette 197 1.4 christos e.key = __UNCONST("a"); 198 1.4 christos e.data = (void*)(intptr_t)0; 199 1.1 pgoyette 200 1.1 pgoyette ep = hsearch(e, ENTER); 201 1.1 pgoyette 202 1.1 pgoyette ATF_REQUIRE(ep != NULL); 203 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, "a"); 204 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 205 1.1 pgoyette 206 1.4 christos e.key = __UNCONST("b"); 207 1.4 christos e.data = (void*)(intptr_t)1; 208 1.1 pgoyette 209 1.1 pgoyette ep = hsearch(e, ENTER); 210 1.2 jruoho 211 1.1 pgoyette ATF_REQUIRE(ep != NULL); 212 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, "b"); 213 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 1); 214 1.1 pgoyette 215 1.4 christos e.key = __UNCONST("a"); 216 1.1 pgoyette ep = hsearch(e, FIND); 217 1.1 pgoyette 218 1.4 christos e.key = __UNCONST("b"); 219 1.1 pgoyette ep2 = hsearch(e, FIND); 220 1.1 pgoyette 221 1.1 pgoyette ATF_REQUIRE(ep != NULL); 222 1.1 pgoyette ATF_REQUIRE_STREQ(ep->key, "a"); 223 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 224 1.1 pgoyette 225 1.1 pgoyette ATF_REQUIRE(ep2 != NULL); 226 1.1 pgoyette ATF_REQUIRE_STREQ(ep2->key, "b"); 227 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep2->data, 1); 228 1.2 jruoho 229 1.1 pgoyette hdestroy(); 230 1.1 pgoyette } 231 1.1 pgoyette 232 1.3 christos ATF_TC(hsearch_r_basic); 233 1.3 christos ATF_TC_HEAD(hsearch_r_basic, tc) 234 1.3 christos { 235 1.3 christos 236 1.3 christos atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching"); 237 1.3 christos } 238 1.3 christos 239 1.3 christos ATF_TC_BODY(hsearch_r_basic, tc) 240 1.3 christos { 241 1.3 christos ENTRY e, *ep; 242 1.3 christos char ch[2]; 243 1.3 christos int i; 244 1.3 christos struct hsearch_data t; 245 1.3 christos 246 1.3 christos REQUIRE_ERRNO(hcreate_r(16, &t) != 0); 247 1.3 christos 248 1.3 christos /* ch[1] should be constant from here on down. */ 249 1.3 christos ch[1] = '\0'; 250 1.3 christos 251 1.3 christos /* Basic insertions. Check enough that there'll be collisions. */ 252 1.3 christos for (i = 0; i < 26; i++) { 253 1.3 christos ch[0] = 'a' + i; 254 1.3 christos e.key = strdup(ch); /* ptr to provided key is kept! */ 255 1.3 christos ATF_REQUIRE(e.key != NULL); 256 1.4 christos e.data = (void *)(intptr_t)i; 257 1.3 christos 258 1.3 christos ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); 259 1.3 christos ATF_REQUIRE(ep != NULL); 260 1.3 christos ATF_REQUIRE_STREQ(ep->key, ch); 261 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, i); 262 1.3 christos } 263 1.3 christos 264 1.3 christos /* e.key should be constant from here on down. */ 265 1.3 christos e.key = ch; 266 1.3 christos 267 1.3 christos /* Basic lookups. */ 268 1.3 christos for (i = 0; i < 26; i++) { 269 1.3 christos ch[0] = 'a' + i; 270 1.3 christos 271 1.3 christos ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); 272 1.3 christos ATF_REQUIRE(ep != NULL); 273 1.3 christos ATF_REQUIRE_STREQ(ep->key, ch); 274 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, i); 275 1.3 christos } 276 1.3 christos 277 1.4 christos hdestroy1_r(&t, free, NULL); 278 1.3 christos } 279 1.3 christos 280 1.3 christos ATF_TC(hsearch_r_duplicate); 281 1.3 christos ATF_TC_HEAD(hsearch_r_duplicate, tc) 282 1.3 christos { 283 1.3 christos 284 1.3 christos atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate " 285 1.3 christos "doesn't overwrite existing data"); 286 1.3 christos } 287 1.3 christos 288 1.3 christos ATF_TC_BODY(hsearch_r_duplicate, tc) 289 1.3 christos { 290 1.3 christos ENTRY e, *ep; 291 1.3 christos struct hsearch_data t; 292 1.3 christos 293 1.3 christos REQUIRE_ERRNO(hcreate_r(16, &t)); 294 1.3 christos 295 1.4 christos e.key = __UNCONST("a"); 296 1.4 christos e.data = (void *)(intptr_t) 0; 297 1.3 christos 298 1.3 christos ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); 299 1.3 christos ATF_REQUIRE(ep != NULL); 300 1.3 christos ATF_REQUIRE_STREQ(ep->key, "a"); 301 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 302 1.3 christos 303 1.4 christos e.data = (void *)(intptr_t)12345; 304 1.3 christos 305 1.3 christos ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); 306 1.3 christos ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); 307 1.3 christos 308 1.3 christos ATF_REQUIRE(ep != NULL); 309 1.3 christos ATF_REQUIRE_STREQ(ep->key, "a"); 310 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 311 1.3 christos 312 1.3 christos hdestroy_r(&t); 313 1.3 christos } 314 1.3 christos 315 1.3 christos ATF_TC(hsearch_r_nonexistent); 316 1.3 christos ATF_TC_HEAD(hsearch_r_nonexistent, tc) 317 1.3 christos { 318 1.3 christos 319 1.3 christos atf_tc_set_md_var(tc, "descr", 320 1.3 christos "Checks searching for non-existent entry"); 321 1.3 christos } 322 1.3 christos 323 1.3 christos ATF_TC_BODY(hsearch_r_nonexistent, tc) 324 1.3 christos { 325 1.3 christos ENTRY e, *ep; 326 1.3 christos struct hsearch_data t; 327 1.3 christos 328 1.3 christos REQUIRE_ERRNO(hcreate_r(16, &t)); 329 1.3 christos 330 1.4 christos e.key = __UNCONST("A"); 331 1.3 christos ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); 332 1.3 christos ATF_REQUIRE_EQ(ep, NULL); 333 1.3 christos 334 1.3 christos hdestroy_r(&t); 335 1.3 christos } 336 1.3 christos 337 1.3 christos ATF_TC(hsearch_r_two); 338 1.3 christos ATF_TC_HEAD(hsearch_r_two, tc) 339 1.3 christos { 340 1.3 christos 341 1.3 christos atf_tc_set_md_var(tc, "descr", 342 1.3 christos "Checks that searching doesn't overwrite previous search results"); 343 1.3 christos } 344 1.3 christos 345 1.3 christos ATF_TC_BODY(hsearch_r_two, tc) 346 1.3 christos { 347 1.3 christos ENTRY e, *ep, *ep2; 348 1.3 christos struct hsearch_data t; 349 1.3 christos 350 1.3 christos REQUIRE_ERRNO(hcreate_r(16, &t)); 351 1.3 christos 352 1.4 christos e.key = __UNCONST("a"); 353 1.4 christos e.data = (void*)(intptr_t)0; 354 1.3 christos 355 1.3 christos ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); 356 1.3 christos ATF_REQUIRE(ep != NULL); 357 1.3 christos ATF_REQUIRE_STREQ(ep->key, "a"); 358 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 359 1.3 christos 360 1.4 christos e.key = __UNCONST("b"); 361 1.4 christos e.data = (void*)(intptr_t)1; 362 1.3 christos 363 1.3 christos ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); 364 1.3 christos ATF_REQUIRE(ep != NULL); 365 1.3 christos ATF_REQUIRE_STREQ(ep->key, "b"); 366 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 1); 367 1.3 christos 368 1.4 christos e.key = __UNCONST("a"); 369 1.3 christos ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); 370 1.3 christos 371 1.4 christos e.key = __UNCONST("b"); 372 1.3 christos ATF_REQUIRE(hsearch_r(e, FIND, &ep2, &t) == 1); 373 1.3 christos 374 1.3 christos ATF_REQUIRE(ep != NULL); 375 1.3 christos ATF_REQUIRE_STREQ(ep->key, "a"); 376 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep->data, 0); 377 1.3 christos 378 1.3 christos ATF_REQUIRE(ep2 != NULL); 379 1.3 christos ATF_REQUIRE_STREQ(ep2->key, "b"); 380 1.4 christos ATF_REQUIRE_EQ((intptr_t)ep2->data, 1); 381 1.3 christos 382 1.3 christos hdestroy_r(&t); 383 1.3 christos } 384 1.3 christos 385 1.1 pgoyette ATF_TP_ADD_TCS(tp) 386 1.1 pgoyette { 387 1.1 pgoyette 388 1.2 jruoho ATF_TP_ADD_TC(tp, hsearch_basic); 389 1.2 jruoho ATF_TP_ADD_TC(tp, hsearch_duplicate); 390 1.2 jruoho ATF_TP_ADD_TC(tp, hsearch_nonexistent); 391 1.2 jruoho ATF_TP_ADD_TC(tp, hsearch_two); 392 1.1 pgoyette 393 1.3 christos ATF_TP_ADD_TC(tp, hsearch_r_basic); 394 1.3 christos ATF_TP_ADD_TC(tp, hsearch_r_duplicate); 395 1.3 christos ATF_TP_ADD_TC(tp, hsearch_r_nonexistent); 396 1.3 christos ATF_TP_ADD_TC(tp, hsearch_r_two); 397 1.3 christos 398 1.1 pgoyette return atf_no_error(); 399 1.1 pgoyette } 400