1272343Sngie/* $NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $ */
2272343Sngie
3272343Sngie/*-
4272343Sngie * Copyright (c) 2008 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * Redistribution and use in source and binary forms, with or without
8272343Sngie * modification, are permitted provided that the following conditions
9272343Sngie * are met:
10272343Sngie * 1. Redistributions of source code must retain the above copyright
11272343Sngie *    notice, this list of conditions and the following disclaimer.
12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
13272343Sngie *    notice, this list of conditions and the following disclaimer in the
14272343Sngie *    documentation and/or other materials provided with the distribution.
15272343Sngie *
16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26272343Sngie * POSSIBILITY OF SUCH DAMAGE.
27272343Sngie */
28272343Sngie
29272343Sngie/*
30272343Sngie * Copyright (c) 2001 Christopher G. Demetriou
31272343Sngie * All rights reserved.
32272343Sngie *
33272343Sngie * Redistribution and use in source and binary forms, with or without
34272343Sngie * modification, are permitted provided that the following conditions
35272343Sngie * are met:
36272343Sngie * 1. Redistributions of source code must retain the above copyright
37272343Sngie *    notice, this list of conditions and the following disclaimer.
38272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
39272343Sngie *    notice, this list of conditions and the following disclaimer in the
40272343Sngie *    documentation and/or other materials provided with the distribution.
41272343Sngie * 3. All advertising materials mentioning features or use of this software
42272343Sngie *    must display the following acknowledgement:
43272343Sngie *          This product includes software developed for the
44272343Sngie *          NetBSD Project.  See http://www.NetBSD.org/ for
45272343Sngie *          information about NetBSD.
46272343Sngie * 4. The name of the author may not be used to endorse or promote products
47272343Sngie *    derived from this software without specific prior written permission.
48272343Sngie *
49272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
50272343Sngie * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51272343Sngie * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52272343Sngie * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
53272343Sngie * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54272343Sngie * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55272343Sngie * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56272343Sngie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57272343Sngie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58272343Sngie * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59272343Sngie *
60272343Sngie * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
61272343Sngie */
62272343Sngie
63272343Sngie#include <sys/cdefs.h>
64272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\
65272343Sngie The NetBSD Foundation, inc. All rights reserved.");
66272343Sngie__RCSID("$NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $");
67272343Sngie
68272343Sngie#include <errno.h>
69272343Sngie#include <search.h>
70272343Sngie#include <string.h>
71272343Sngie#include <stdio.h>
72272343Sngie#include <stdlib.h>
73272343Sngie
74272343Sngie#include <atf-c.h>
75272343Sngie
76272343Sngie#define REQUIRE_ERRNO(x) ATF_REQUIRE_MSG(x, "%s", strerror(errno))
77272343Sngie
78272343SngieATF_TC(hsearch_basic);
79272343SngieATF_TC_HEAD(hsearch_basic, tc)
80272343Sngie{
81272343Sngie
82272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching");
83272343Sngie}
84272343Sngie
85272343SngieATF_TC_BODY(hsearch_basic, tc)
86272343Sngie{
87272343Sngie	ENTRY e, *ep;
88272343Sngie	char ch[2];
89272343Sngie	int i;
90272343Sngie
91272343Sngie	REQUIRE_ERRNO(hcreate(16) != 0);
92272343Sngie
93272343Sngie	/* ch[1] should be constant from here on down. */
94272343Sngie	ch[1] = '\0';
95272343Sngie
96272343Sngie	/* Basic insertions.  Check enough that there'll be collisions. */
97272343Sngie	for (i = 0; i < 26; i++) {
98272343Sngie		ch[0] = 'a' + i;
99272343Sngie		e.key = strdup(ch);	/* ptr to provided key is kept! */
100272343Sngie		ATF_REQUIRE(e.key != NULL);
101272343Sngie		e.data = (void *)(intptr_t)i;
102272343Sngie
103272343Sngie		ep = hsearch(e, ENTER);
104272343Sngie
105272343Sngie		ATF_REQUIRE(ep != NULL);
106272343Sngie		ATF_REQUIRE_STREQ(ep->key, ch);
107272343Sngie		ATF_REQUIRE_EQ((intptr_t)ep->data, i);
108272343Sngie	}
109272343Sngie
110272343Sngie	/* e.key should be constant from here on down. */
111272343Sngie	e.key = ch;
112272343Sngie
113272343Sngie	/* Basic lookups. */
114272343Sngie	for (i = 0; i < 26; i++) {
115272343Sngie		ch[0] = 'a' + i;
116272343Sngie
117272343Sngie		ep = hsearch(e, FIND);
118272343Sngie
119272343Sngie		ATF_REQUIRE(ep != NULL);
120272343Sngie		ATF_REQUIRE_STREQ(ep->key, ch);
121272343Sngie		ATF_REQUIRE_EQ((intptr_t)ep->data, i);
122272343Sngie	}
123272343Sngie
124314818Sngie#ifdef __NetBSD__
125272343Sngie	hdestroy1(free, NULL);
126314818Sngie#else
127314818Sngie	hdestroy();
128314818Sngie#endif
129272343Sngie}
130272343Sngie
131272343SngieATF_TC(hsearch_duplicate);
132272343SngieATF_TC_HEAD(hsearch_duplicate, tc)
133272343Sngie{
134272343Sngie
135272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate "
136272343Sngie	    "doesn't overwrite existing data");
137272343Sngie}
138272343Sngie
139272343SngieATF_TC_BODY(hsearch_duplicate, tc)
140272343Sngie{
141272343Sngie	ENTRY e, *ep;
142272343Sngie
143272343Sngie	REQUIRE_ERRNO(hcreate(16));
144272343Sngie
145272343Sngie	e.key = __UNCONST("a");
146272343Sngie	e.data = (void *)(intptr_t) 0;
147272343Sngie
148272343Sngie	ep = hsearch(e, ENTER);
149272343Sngie
150272343Sngie	ATF_REQUIRE(ep != NULL);
151272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
152272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
153272343Sngie
154272343Sngie	e.data = (void *)(intptr_t)12345;
155272343Sngie
156272343Sngie	ep = hsearch(e, ENTER);
157272343Sngie	ep = hsearch(e, FIND);
158272343Sngie
159272343Sngie	ATF_REQUIRE(ep != NULL);
160272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
161272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
162272343Sngie
163272343Sngie	hdestroy();
164272343Sngie}
165272343Sngie
166272343SngieATF_TC(hsearch_nonexistent);
167272343SngieATF_TC_HEAD(hsearch_nonexistent, tc)
168272343Sngie{
169272343Sngie
170272343Sngie	atf_tc_set_md_var(tc, "descr",
171272343Sngie	    "Checks searching for non-existent entry");
172272343Sngie}
173272343Sngie
174272343SngieATF_TC_BODY(hsearch_nonexistent, tc)
175272343Sngie{
176272343Sngie	ENTRY e, *ep;
177272343Sngie
178272343Sngie	REQUIRE_ERRNO(hcreate(16));
179272343Sngie
180272343Sngie	e.key = __UNCONST("A");
181272343Sngie	ep = hsearch(e, FIND);
182272343Sngie	ATF_REQUIRE_EQ(ep, NULL);
183272343Sngie
184272343Sngie	hdestroy();
185272343Sngie}
186272343Sngie
187272343SngieATF_TC(hsearch_two);
188272343SngieATF_TC_HEAD(hsearch_two, tc)
189272343Sngie{
190272343Sngie
191272343Sngie	atf_tc_set_md_var(tc, "descr",
192272343Sngie	    "Checks that searching doesn't overwrite previous search results");
193272343Sngie}
194272343Sngie
195272343SngieATF_TC_BODY(hsearch_two, tc)
196272343Sngie{
197272343Sngie	ENTRY e, *ep, *ep2;
198272343Sngie
199272343Sngie	REQUIRE_ERRNO(hcreate(16));
200272343Sngie
201272343Sngie	e.key = __UNCONST("a");
202272343Sngie	e.data = (void*)(intptr_t)0;
203272343Sngie
204272343Sngie	ep = hsearch(e, ENTER);
205272343Sngie
206272343Sngie	ATF_REQUIRE(ep != NULL);
207272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
208272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
209272343Sngie
210272343Sngie	e.key = __UNCONST("b");
211272343Sngie	e.data = (void*)(intptr_t)1;
212272343Sngie
213272343Sngie	ep = hsearch(e, ENTER);
214272343Sngie
215272343Sngie	ATF_REQUIRE(ep != NULL);
216272343Sngie	ATF_REQUIRE_STREQ(ep->key, "b");
217272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 1);
218272343Sngie
219272343Sngie	e.key = __UNCONST("a");
220272343Sngie	ep = hsearch(e, FIND);
221272343Sngie
222272343Sngie	e.key = __UNCONST("b");
223272343Sngie	ep2 = hsearch(e, FIND);
224272343Sngie
225272343Sngie	ATF_REQUIRE(ep != NULL);
226272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
227272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
228272343Sngie
229272343Sngie	ATF_REQUIRE(ep2 != NULL);
230272343Sngie	ATF_REQUIRE_STREQ(ep2->key, "b");
231272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep2->data, 1);
232272343Sngie
233272343Sngie	hdestroy();
234272343Sngie}
235272343Sngie
236276046Sngie#if defined(__FreeBSD__) && 1100027 <= __FreeBSD_version
237272343SngieATF_TC(hsearch_r_basic);
238272343SngieATF_TC_HEAD(hsearch_r_basic, tc)
239272343Sngie{
240272343Sngie
241272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching");
242272343Sngie}
243272343Sngie
244272343SngieATF_TC_BODY(hsearch_r_basic, tc)
245272343Sngie{
246272343Sngie	ENTRY e, *ep;
247272343Sngie	char ch[2];
248272343Sngie	int i;
249272343Sngie	struct hsearch_data t;
250272343Sngie
251272343Sngie	REQUIRE_ERRNO(hcreate_r(16, &t) != 0);
252272343Sngie
253272343Sngie	/* ch[1] should be constant from here on down. */
254272343Sngie	ch[1] = '\0';
255272343Sngie
256272343Sngie	/* Basic insertions.  Check enough that there'll be collisions. */
257272343Sngie	for (i = 0; i < 26; i++) {
258272343Sngie		ch[0] = 'a' + i;
259272343Sngie		e.key = strdup(ch);	/* ptr to provided key is kept! */
260272343Sngie		ATF_REQUIRE(e.key != NULL);
261272343Sngie		e.data = (void *)(intptr_t)i;
262272343Sngie
263272343Sngie		ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1);
264272343Sngie		ATF_REQUIRE(ep != NULL);
265272343Sngie		ATF_REQUIRE_STREQ(ep->key, ch);
266272343Sngie		ATF_REQUIRE_EQ((intptr_t)ep->data, i);
267272343Sngie	}
268272343Sngie
269272343Sngie	/* e.key should be constant from here on down. */
270272343Sngie	e.key = ch;
271272343Sngie
272272343Sngie	/* Basic lookups. */
273272343Sngie	for (i = 0; i < 26; i++) {
274272343Sngie		ch[0] = 'a' + i;
275272343Sngie
276272343Sngie		ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1);
277272343Sngie		ATF_REQUIRE(ep != NULL);
278272343Sngie		ATF_REQUIRE_STREQ(ep->key, ch);
279272343Sngie		ATF_REQUIRE_EQ((intptr_t)ep->data, i);
280272343Sngie	}
281272343Sngie
282314818Sngie#ifdef __NetBSD__
283272343Sngie	hdestroy1_r(&t, free, NULL);
284314818Sngie#else
285314818Sngie	hdestroy_r(&t);
286314818Sngie#endif
287272343Sngie}
288272890Sngie#endif
289272343Sngie
290314818Sngie#if defined(__FreeBSD__) && 1100027 <= __FreeBSD_version
291272343SngieATF_TC(hsearch_r_duplicate);
292272343SngieATF_TC_HEAD(hsearch_r_duplicate, tc)
293272343Sngie{
294272343Sngie
295272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate "
296272343Sngie	    "doesn't overwrite existing data");
297272343Sngie}
298272343Sngie
299272343SngieATF_TC_BODY(hsearch_r_duplicate, tc)
300272343Sngie{
301272343Sngie	ENTRY e, *ep;
302272343Sngie	struct hsearch_data t;
303272343Sngie
304272343Sngie	REQUIRE_ERRNO(hcreate_r(16, &t));
305272343Sngie
306272343Sngie	e.key = __UNCONST("a");
307272343Sngie	e.data = (void *)(intptr_t) 0;
308272343Sngie
309272343Sngie	ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1);
310272343Sngie	ATF_REQUIRE(ep != NULL);
311272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
312272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
313272343Sngie
314272343Sngie	e.data = (void *)(intptr_t)12345;
315272343Sngie
316272343Sngie	ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1);
317272343Sngie	ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1);
318272343Sngie
319272343Sngie	ATF_REQUIRE(ep != NULL);
320272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
321272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
322272343Sngie
323272343Sngie	hdestroy_r(&t);
324272343Sngie}
325272343Sngie
326272343SngieATF_TC(hsearch_r_nonexistent);
327272343SngieATF_TC_HEAD(hsearch_r_nonexistent, tc)
328272343Sngie{
329272343Sngie
330272343Sngie	atf_tc_set_md_var(tc, "descr",
331272343Sngie	    "Checks searching for non-existent entry");
332272343Sngie}
333272343Sngie
334272343SngieATF_TC_BODY(hsearch_r_nonexistent, tc)
335272343Sngie{
336272343Sngie	ENTRY e, *ep;
337272343Sngie	struct hsearch_data t;
338272343Sngie
339272343Sngie	REQUIRE_ERRNO(hcreate_r(16, &t));
340272343Sngie
341314818Sngie#ifdef __FreeBSD__
342314818Sngie	atf_tc_expect_fail("behavior doesn't match docs; see bug # 216872");
343314818Sngie#endif
344272343Sngie	e.key = __UNCONST("A");
345272343Sngie	ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1);
346272343Sngie	ATF_REQUIRE_EQ(ep, NULL);
347272343Sngie
348272343Sngie	hdestroy_r(&t);
349272343Sngie}
350272343Sngie
351272343SngieATF_TC(hsearch_r_two);
352272343SngieATF_TC_HEAD(hsearch_r_two, tc)
353272343Sngie{
354272343Sngie
355272343Sngie	atf_tc_set_md_var(tc, "descr",
356272343Sngie	    "Checks that searching doesn't overwrite previous search results");
357272343Sngie}
358272343Sngie
359272343SngieATF_TC_BODY(hsearch_r_two, tc)
360272343Sngie{
361272343Sngie	ENTRY e, *ep, *ep2;
362272343Sngie	struct hsearch_data t;
363272343Sngie
364272343Sngie	REQUIRE_ERRNO(hcreate_r(16, &t));
365272343Sngie
366272343Sngie	e.key = __UNCONST("a");
367272343Sngie	e.data = (void*)(intptr_t)0;
368272343Sngie
369272343Sngie	ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1);
370272343Sngie	ATF_REQUIRE(ep != NULL);
371272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
372272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
373272343Sngie
374272343Sngie	e.key = __UNCONST("b");
375272343Sngie	e.data = (void*)(intptr_t)1;
376272343Sngie
377272343Sngie	ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1);
378272343Sngie	ATF_REQUIRE(ep != NULL);
379272343Sngie	ATF_REQUIRE_STREQ(ep->key, "b");
380272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 1);
381272343Sngie
382272343Sngie	e.key = __UNCONST("a");
383272343Sngie	ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1);
384272343Sngie
385272343Sngie	e.key = __UNCONST("b");
386272343Sngie	ATF_REQUIRE(hsearch_r(e, FIND, &ep2, &t) == 1);
387272343Sngie
388272343Sngie	ATF_REQUIRE(ep != NULL);
389272343Sngie	ATF_REQUIRE_STREQ(ep->key, "a");
390272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep->data, 0);
391272343Sngie
392272343Sngie	ATF_REQUIRE(ep2 != NULL);
393272343Sngie	ATF_REQUIRE_STREQ(ep2->key, "b");
394272343Sngie	ATF_REQUIRE_EQ((intptr_t)ep2->data, 1);
395272343Sngie
396272343Sngie	hdestroy_r(&t);
397272343Sngie}
398276046Sngie#endif
399272343Sngie
400272343SngieATF_TP_ADD_TCS(tp)
401272343Sngie{
402272343Sngie
403272343Sngie	ATF_TP_ADD_TC(tp, hsearch_basic);
404272343Sngie	ATF_TP_ADD_TC(tp, hsearch_duplicate);
405272343Sngie	ATF_TP_ADD_TC(tp, hsearch_nonexistent);
406272343Sngie	ATF_TP_ADD_TC(tp, hsearch_two);
407314818Sngie
408276046Sngie#if defined(__FreeBSD__) && 1100027 <= __FreeBSD_version
409272343Sngie	ATF_TP_ADD_TC(tp, hsearch_r_basic);
410272343Sngie	ATF_TP_ADD_TC(tp, hsearch_r_duplicate);
411272343Sngie	ATF_TP_ADD_TC(tp, hsearch_r_nonexistent);
412272343Sngie	ATF_TP_ADD_TC(tp, hsearch_r_two);
413276046Sngie#endif
414272343Sngie
415272343Sngie	return atf_no_error();
416272343Sngie}
417