xref: /freebsd/lib/libc/tests/string/memrchr_test.c (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2023 Robert Clausecker
5  */
6 
7 #include <sys/cdefs.h>
8 
9 #include <dlfcn.h>
10 #include <limits.h>
11 #include <string.h>
12 
13 #include <atf-c.h>
14 
15 static void *(*memrchr_fn)(const void *, int, size_t);
16 
17 ATF_TC_WITHOUT_HEAD(null);
18 ATF_TC_BODY(null, tc)
19 {
20 	ATF_CHECK_EQ(memrchr_fn(NULL, 42, 0), NULL);
21 }
22 
23 ATF_TC_WITHOUT_HEAD(not_found);
24 ATF_TC_BODY(not_found, tc)
25 {
26 	size_t i, j;
27 	char buf[1+15+64+1]; /* offset [0..15] + 64 buffer bytes + sentinels */
28 
29 	buf[0] = 'X';
30 	memset(buf + 1, '-', sizeof(buf) - 1);
31 
32 	for (i = 0; i < 16; i++)
33 		for (j = 0; j < 64; j++) {
34 			buf[i + j + 1] = 'X';
35 			ATF_CHECK_EQ(memrchr_fn(buf + i + 1, 'X', j), NULL);
36 			buf[i + j + 1] = '-';
37 		}
38 }
39 
40 static void
41 do_found_test(char buf[], size_t len, size_t first, size_t second)
42 {
43 	/* invariant: first <= second */
44 
45 	buf[first] = 'X';
46 	buf[second] = 'X';
47 	ATF_CHECK_EQ(memrchr_fn(buf, 'X', len), buf + second);
48 	buf[first] = '-';
49 	buf[second] = '-';
50 }
51 
52 ATF_TC_WITHOUT_HEAD(found);
53 ATF_TC_BODY(found, tc)
54 {
55 	size_t i, j, k, l;
56 	char buf[1+15+64+1];
57 
58 	buf[0] = 'X';
59 	memset(buf + 1, '-', sizeof(buf) - 1);
60 
61 	for (i = 0; i < 16; i++)
62 		for (j = 0; j < 64; j++)
63 			for (k = 0; k < j; k++)
64 				for (l = 0; l <= k; l++) {
65 					buf[i + j + 1] = 'X';
66 					do_found_test(buf + i + 1, j, l, k);
67 					buf[i + j + 1] = '-';
68 				}
69 }
70 
71 /* check that the right character is found */
72 static void
73 do_values_test(unsigned char buf[], size_t len, size_t i, int c)
74 {
75 	/* sentinels */
76 	buf[-1] = c;
77 	buf[len] = c;
78 	memset(buf, c + 1, len);
79 
80 	if (i < len) {
81 		buf[i] = c;
82 		ATF_CHECK_EQ(memrchr_fn(buf, c, len), buf + i);
83 	} else
84 		ATF_CHECK_EQ(memrchr_fn(buf, c, len), NULL);
85 }
86 
87 ATF_TC_WITHOUT_HEAD(values);
88 ATF_TC_BODY(values, tc)
89 {
90 	size_t i, j, k;
91 	int c;
92 	unsigned char buf[1+15+64+1];
93 
94 	for (i = 0; i < 16; i++)
95 		for (j = 0; j < 64; j++)
96 			for (k = 0; k <= j; k++)
97 				for (c = 0; c <= UCHAR_MAX; c++)
98 					do_values_test(buf + i + 1, j, k, c);
99 }
100 
101 ATF_TP_ADD_TCS(tp)
102 {
103 	void *dl_handle;
104 
105 	dl_handle = dlopen(NULL, RTLD_LAZY);
106 	memrchr_fn = dlsym(dl_handle, "test_memrchr");
107 	if (memrchr_fn == NULL)
108 		memrchr_fn = memrchr;
109 
110 	ATF_TP_ADD_TC(tp, null);
111 	ATF_TP_ADD_TC(tp, not_found);
112 	ATF_TP_ADD_TC(tp, found);
113 	ATF_TP_ADD_TC(tp, values);
114 
115 	return (atf_no_error());
116 }
117