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