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