xref: /freebsd/lib/libc/tests/stdlib/bsearch_s_test.c (revision d59c7ea2701fe7b73b32eef49a7c712ef38de5a0)
1*d59c7ea2SFaraz Vahedi /*
2*d59c7ea2SFaraz Vahedi  * Copyright (c) 2026 Faraz Vahedi <kfv@FreeBSD.org>
3*d59c7ea2SFaraz Vahedi  *
4*d59c7ea2SFaraz Vahedi  * SPDX-License-Identifier: BSD-2-Clause
5*d59c7ea2SFaraz Vahedi  */
6*d59c7ea2SFaraz Vahedi 
7*d59c7ea2SFaraz Vahedi /*
8*d59c7ea2SFaraz Vahedi  * Test for bsearch_s() routine.
9*d59c7ea2SFaraz Vahedi  */
10*d59c7ea2SFaraz Vahedi 
11*d59c7ea2SFaraz Vahedi #include <stdint.h>
12*d59c7ea2SFaraz Vahedi #include <stdlib.h>
13*d59c7ea2SFaraz Vahedi 
14*d59c7ea2SFaraz Vahedi #define	THUNK 42
15*d59c7ea2SFaraz Vahedi 
16*d59c7ea2SFaraz Vahedi #include "test-search.h"
17*d59c7ea2SFaraz Vahedi 
18*d59c7ea2SFaraz Vahedi static errno_t error_code;
19*d59c7ea2SFaraz Vahedi static int compar_calls;
20*d59c7ea2SFaraz Vahedi 
21*d59c7ea2SFaraz Vahedi static int
searchhelp_s(const void * a,const void * b,void * thunk)22*d59c7ea2SFaraz Vahedi searchhelp_s(const void *a, const void *b, void *thunk)
23*d59c7ea2SFaraz Vahedi {
24*d59c7ea2SFaraz Vahedi 	compar_calls++;
25*d59c7ea2SFaraz Vahedi 	if (thunk != NULL)
26*d59c7ea2SFaraz Vahedi 		ATF_REQUIRE_EQ(*(int *)thunk, THUNK);
27*d59c7ea2SFaraz Vahedi 	return (searchhelp(a, b));
28*d59c7ea2SFaraz Vahedi }
29*d59c7ea2SFaraz Vahedi 
30*d59c7ea2SFaraz Vahedi static void
constraint_handler(const char * restrict msg __unused,void * restrict ptr __unused,errno_t error)31*d59c7ea2SFaraz Vahedi constraint_handler(const char * restrict msg __unused,
32*d59c7ea2SFaraz Vahedi     void * restrict ptr __unused, errno_t error)
33*d59c7ea2SFaraz Vahedi {
34*d59c7ea2SFaraz Vahedi 	error_code = error;
35*d59c7ea2SFaraz Vahedi }
36*d59c7ea2SFaraz Vahedi 
37*d59c7ea2SFaraz Vahedi static void
expect_viol(const void * key,const void * base,rsize_t nmemb,rsize_t size,int (* compar)(const void *,const void *,void *),void * thunk)38*d59c7ea2SFaraz Vahedi expect_viol(const void *key, const void *base, rsize_t nmemb, rsize_t size,
39*d59c7ea2SFaraz Vahedi     int (*compar)(const void *, const void *, void *), void *thunk)
40*d59c7ea2SFaraz Vahedi {
41*d59c7ea2SFaraz Vahedi 	error_code = 0;
42*d59c7ea2SFaraz Vahedi 	compar_calls = 0;
43*d59c7ea2SFaraz Vahedi 	ATF_CHECK(bsearch_s(key, base, nmemb, size, compar, thunk) == NULL);
44*d59c7ea2SFaraz Vahedi 	ATF_CHECK(error_code > 0);
45*d59c7ea2SFaraz Vahedi 	ATF_CHECK_EQ(compar_calls, 0);
46*d59c7ea2SFaraz Vahedi }
47*d59c7ea2SFaraz Vahedi 
48*d59c7ea2SFaraz Vahedi static void *
do_bsearch_s(const int * key,const int * base,size_t n,void * ctx)49*d59c7ea2SFaraz Vahedi do_bsearch_s(const int *key, const int *base, size_t n, void *ctx)
50*d59c7ea2SFaraz Vahedi {
51*d59c7ea2SFaraz Vahedi 	return (bsearch_s(key, base, n, sizeof(int), searchhelp_s, ctx));
52*d59c7ea2SFaraz Vahedi }
53*d59c7ea2SFaraz Vahedi 
54*d59c7ea2SFaraz Vahedi ATF_TC_WITHOUT_HEAD(bsearch_s_constraints);
ATF_TC_BODY(bsearch_s_constraints,tc)55*d59c7ea2SFaraz Vahedi ATF_TC_BODY(bsearch_s_constraints, tc)
56*d59c7ea2SFaraz Vahedi {
57*d59c7ea2SFaraz Vahedi 	int thunk = THUNK;
58*d59c7ea2SFaraz Vahedi 	int key = 4;
59*d59c7ea2SFaraz Vahedi 	int b[] = { 4, 7, 81 };
60*d59c7ea2SFaraz Vahedi 
61*d59c7ea2SFaraz Vahedi 	set_constraint_handler_s(constraint_handler);
62*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, -1, sizeof(int), searchhelp_s, &thunk);
63*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, RSIZE_MAX + 1, sizeof(int), searchhelp_s, &thunk);
64*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, nitems(b), -1, searchhelp_s, &thunk);
65*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, nitems(b), RSIZE_MAX + 1, searchhelp_s, &thunk);
66*d59c7ea2SFaraz Vahedi 	expect_viol(NULL, b, nitems(b), sizeof(int), searchhelp_s, &thunk);
67*d59c7ea2SFaraz Vahedi 	expect_viol(&key, NULL, 1, sizeof(int), searchhelp_s, &thunk);
68*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, nitems(b), sizeof(int), NULL, &thunk);
69*d59c7ea2SFaraz Vahedi 	/* size > RSIZE_MAX is a violation even when nmemb is zero. */
70*d59c7ea2SFaraz Vahedi 	expect_viol(&key, b, 0, RSIZE_MAX + 1, searchhelp_s, &thunk);
71*d59c7ea2SFaraz Vahedi }
72*d59c7ea2SFaraz Vahedi 
73*d59c7ea2SFaraz Vahedi ATF_TC_WITHOUT_HEAD(bsearch_s_nmemb_zero);
ATF_TC_BODY(bsearch_s_nmemb_zero,tc)74*d59c7ea2SFaraz Vahedi ATF_TC_BODY(bsearch_s_nmemb_zero, tc)
75*d59c7ea2SFaraz Vahedi {
76*d59c7ea2SFaraz Vahedi 	int thunk = THUNK;
77*d59c7ea2SFaraz Vahedi 	int key = 4;
78*d59c7ea2SFaraz Vahedi 	int b[] = { 4, 7, 81 };
79*d59c7ea2SFaraz Vahedi 
80*d59c7ea2SFaraz Vahedi 	error_code = 0;
81*d59c7ea2SFaraz Vahedi 	compar_calls = 0;
82*d59c7ea2SFaraz Vahedi 	set_constraint_handler_s(constraint_handler);
83*d59c7ea2SFaraz Vahedi 	ATF_CHECK(bsearch_s(&key, b, 0, sizeof(int), searchhelp_s,
84*d59c7ea2SFaraz Vahedi 	    &thunk) == NULL);
85*d59c7ea2SFaraz Vahedi 	ATF_CHECK(error_code == 0);
86*d59c7ea2SFaraz Vahedi 	ATF_CHECK_EQ(compar_calls, 0);
87*d59c7ea2SFaraz Vahedi 	ATF_CHECK(bsearch_s(NULL, NULL, 0, 0, NULL, NULL) == NULL);
88*d59c7ea2SFaraz Vahedi 	ATF_CHECK(error_code == 0);
89*d59c7ea2SFaraz Vahedi }
90*d59c7ea2SFaraz Vahedi 
91*d59c7ea2SFaraz Vahedi ATF_TC_WITHOUT_HEAD(bsearch_s_h);
ATF_TC_BODY(bsearch_s_h,tc)92*d59c7ea2SFaraz Vahedi ATF_TC_BODY(bsearch_s_h, tc)
93*d59c7ea2SFaraz Vahedi {
94*d59c7ea2SFaraz Vahedi 	int thunk = THUNK;
95*d59c7ea2SFaraz Vahedi 	int b[] = { 4, 7, 81 };
96*d59c7ea2SFaraz Vahedi 	int key = 7;
97*d59c7ea2SFaraz Vahedi 	int *found;
98*d59c7ea2SFaraz Vahedi 
99*d59c7ea2SFaraz Vahedi 	error_code = 0;
100*d59c7ea2SFaraz Vahedi 	compar_calls = 0;
101*d59c7ea2SFaraz Vahedi 	set_constraint_handler_s(constraint_handler);
102*d59c7ea2SFaraz Vahedi 	found = bsearch_s(&key, b, nitems(b), sizeof(int), searchhelp_s,
103*d59c7ea2SFaraz Vahedi 	    &thunk);
104*d59c7ea2SFaraz Vahedi 	ATF_CHECK(error_code == 0);
105*d59c7ea2SFaraz Vahedi 	ATF_CHECK(compar_calls > 0);
106*d59c7ea2SFaraz Vahedi 	ATF_CHECK(found == &b[1]);
107*d59c7ea2SFaraz Vahedi 
108*d59c7ea2SFaraz Vahedi 	compar_calls = 0;
109*d59c7ea2SFaraz Vahedi 	found = bsearch_s(&key, b, nitems(b), sizeof(int), searchhelp_s, NULL);
110*d59c7ea2SFaraz Vahedi 	ATF_CHECK(found == &b[1]);
111*d59c7ea2SFaraz Vahedi 	ATF_CHECK(compar_calls > 0);
112*d59c7ea2SFaraz Vahedi }
113*d59c7ea2SFaraz Vahedi 
114*d59c7ea2SFaraz Vahedi ATF_TC_WITHOUT_HEAD(bsearch_s_test);
ATF_TC_BODY(bsearch_s_test,tc)115*d59c7ea2SFaraz Vahedi ATF_TC_BODY(bsearch_s_test, tc)
116*d59c7ea2SFaraz Vahedi {
117*d59c7ea2SFaraz Vahedi 	int testvector[SVEC_LEN];
118*d59c7ea2SFaraz Vahedi 	int thunk = THUNK;
119*d59c7ea2SFaraz Vahedi 	int j;
120*d59c7ea2SFaraz Vahedi 
121*d59c7ea2SFaraz Vahedi 	for (j = 1; j <= SVEC_LEN; j++)
122*d59c7ea2SFaraz Vahedi 		check_sorted_search(do_bsearch_s, &thunk, testvector,
123*d59c7ea2SFaraz Vahedi 		    (size_t)j);
124*d59c7ea2SFaraz Vahedi }
125*d59c7ea2SFaraz Vahedi 
ATF_TP_ADD_TCS(tp)126*d59c7ea2SFaraz Vahedi ATF_TP_ADD_TCS(tp)
127*d59c7ea2SFaraz Vahedi {
128*d59c7ea2SFaraz Vahedi 	ATF_TP_ADD_TC(tp, bsearch_s_constraints);
129*d59c7ea2SFaraz Vahedi 	ATF_TP_ADD_TC(tp, bsearch_s_nmemb_zero);
130*d59c7ea2SFaraz Vahedi 	ATF_TP_ADD_TC(tp, bsearch_s_h);
131*d59c7ea2SFaraz Vahedi 	ATF_TP_ADD_TC(tp, bsearch_s_test);
132*d59c7ea2SFaraz Vahedi 
133*d59c7ea2SFaraz Vahedi 	return (atf_no_error());
134*d59c7ea2SFaraz Vahedi }
135