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 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 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 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 * 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); 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); 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); 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); 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 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