xref: /freebsd/lib/libsbuf/tests/sbuf_string_test.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 #include <sys/param.h>
28 #include <sys/sbuf.h>
29 #include <errno.h>
30 #include <libutil.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <atf-c.h>
36 
37 #include "sbuf_test_common.h"
38 
39 static char	test_string[] = "this is a test string";
40 static char	test_whitespace_string[] = " \f\n\r\t\v ";
41 static int	test_buffer[] = { 0, 1, 2, 3, 4, 5, };
42 
43 static void
44 check_buffers_equal(const void *sb_buf, const void *test_buf, size_t len)
45 {
46 
47 	if (memcmp(sb_buf, test_buf, len) != 0) {
48 		printf("sbuf:\n");
49 		hexdump(sb_buf, len, NULL, 0),
50 		printf("test_buf:\n");
51 		hexdump(test_buf, len, NULL, 0);
52 		atf_tc_fail("contents of sbuf didn't match test_buf contents");
53 	}
54 }
55 
56 ATF_TC_WITHOUT_HEAD(sbuf_bcat_test);
57 ATF_TC_BODY(sbuf_bcat_test, tc)
58 {
59 	struct sbuf *sb;
60 	int *test_buffer_tmp;
61 	ssize_t test_sbuf_len;
62 
63 	test_buffer_tmp = malloc(sizeof(test_buffer) * 2);
64 	ATF_REQUIRE_MSG(test_buffer_tmp != NULL, "malloc failed");
65 
66 	memcpy(test_buffer_tmp, test_buffer, sizeof(test_buffer));
67 	memcpy(&test_buffer_tmp[nitems(test_buffer)], test_buffer,
68 	    sizeof(test_buffer));
69 
70 	sb = sbuf_new_auto();
71 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
72 	    strerror(errno));
73 
74 	ATF_CHECK_MSG(sbuf_bcat(sb, test_buffer, sizeof(test_buffer)) == 0,
75 	    "sbuf_bcat failed");
76 
77 	test_sbuf_len = sbuf_len(sb);
78 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
79 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
80 	    test_sbuf_len, sizeof(test_buffer));
81 
82 	ATF_CHECK_MSG(sbuf_bcat(sb, test_buffer, sizeof(test_buffer)) == 0,
83 	    "sbuf_bcat failed");
84 
85 	test_sbuf_len = sbuf_len(sb);
86 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)(2 * sizeof(test_buffer)),
87 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
88 	    test_sbuf_len, 2 * sizeof(test_buffer));
89 
90 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
91 	    strerror(errno));
92 
93 	check_buffers_equal(sbuf_data(sb), test_buffer_tmp,
94 	    (size_t)test_sbuf_len);
95 
96 	sbuf_delete(sb);
97 
98 	free(test_buffer_tmp);
99 }
100 
101 ATF_TC_WITHOUT_HEAD(sbuf_bcpy_test);
102 ATF_TC_BODY(sbuf_bcpy_test, tc)
103 {
104 	struct sbuf *sb;
105 	ssize_t test_sbuf_len;
106 
107 	sb = sbuf_new_auto();
108 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
109 	    strerror(errno));
110 
111 	ATF_CHECK_MSG(sbuf_bcpy(sb, test_buffer, sizeof(test_buffer)) == 0,
112 	    "sbuf_bcpy failed");
113 
114 	test_sbuf_len = sbuf_len(sb);
115 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
116 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
117 	    test_sbuf_len, sizeof(test_buffer));
118 
119 	ATF_CHECK_MSG(sbuf_bcpy(sb, test_buffer, sizeof(test_buffer)) == 0,
120 	    "sbuf_bcpy failed");
121 
122 	test_sbuf_len = sbuf_len(sb);
123 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
124 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
125 	    test_sbuf_len, sizeof(test_buffer));
126 
127 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
128 	    strerror(errno));
129 
130 	check_buffers_equal(sbuf_data(sb), test_buffer, (size_t)test_sbuf_len);
131 
132 	sbuf_delete(sb);
133 }
134 
135 ATF_TC_WITHOUT_HEAD(sbuf_cat_test);
136 ATF_TC_BODY(sbuf_cat_test, tc)
137 {
138 	struct sbuf *sb;
139 	char *test_string_tmp;
140 	ssize_t test_sbuf_len;
141 
142 	asprintf(&test_string_tmp, "%s%s", test_string, test_string);
143 	ATF_REQUIRE_MSG(test_string_tmp != NULL, "asprintf failed");
144 
145 	sb = sbuf_new_auto();
146 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
147 	    strerror(errno));
148 
149 	ATF_CHECK_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
150 
151 	test_sbuf_len = sbuf_len(sb);
152 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
153 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
154 	    test_sbuf_len, sizeof(test_string));
155 
156 	ATF_CHECK_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
157 
158 	test_sbuf_len = sbuf_len(sb);
159 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string_tmp),
160 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
161 	    test_sbuf_len, strlen(test_string_tmp));
162 
163 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
164 	    strerror(errno));
165 
166 	ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string_tmp,
167 	    "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
168 	    test_string_tmp);
169 
170 	sbuf_delete(sb);
171 
172 	free(test_string_tmp);
173 }
174 
175 ATF_TC_WITHOUT_HEAD(sbuf_cpy_test);
176 ATF_TC_BODY(sbuf_cpy_test, tc)
177 {
178 	struct sbuf *sb;
179 	ssize_t test_sbuf_len;
180 
181 	sb = sbuf_new_auto();
182 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
183 	    strerror(errno));
184 
185 	ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
186 
187 	test_sbuf_len = sbuf_len(sb);
188 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
189 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
190 	    test_sbuf_len, strlen(test_string));
191 
192 	ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
193 
194 	test_sbuf_len = sbuf_len(sb);
195 	ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
196 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
197 	    test_sbuf_len, strlen(test_string));
198 
199 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
200 	    strerror(errno));
201 
202 	ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
203 	    "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
204 	    test_string);
205 
206 	sbuf_delete(sb);
207 }
208 
209 ATF_TC_WITHOUT_HEAD(sbuf_putc_test);
210 ATF_TC_BODY(sbuf_putc_test, tc)
211 {
212 	struct sbuf *sb;
213 	ssize_t test_sbuf_len;
214 	size_t i;
215 
216 	sb = sbuf_new_auto();
217 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
218 	    strerror(errno));
219 
220 	for (i = 0; i <= strlen(test_string); i++) {	/* Include the NUL */
221 		ATF_REQUIRE_MSG(sbuf_putc(sb, test_string[i]) == 0,
222 		    "sbuf_putc failed");
223 
224 		/* The best we can do until sbuf_finish(3) is called. */
225 		test_sbuf_len = sbuf_len(sb);
226 		ATF_REQUIRE_MSG((ssize_t)(i + 1) == test_sbuf_len,
227 		    "sbuf_len(..) => %zd (actual) != %zu (expected)",
228 		    test_sbuf_len, i + 1);
229 	}
230 
231 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
232 	    strerror(errno));
233 
234 	ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
235 	    "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
236 	    test_string);
237 
238 	sbuf_delete(sb);
239 }
240 
241 ATF_TC_WITHOUT_HEAD(sbuf_trim_test);
242 ATF_TC_BODY(sbuf_trim_test, tc)
243 {
244 	struct sbuf *sb;
245 	ssize_t exp_sbuf_len, test_sbuf_len;
246 
247 	sb = sbuf_new_auto();
248 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
249 	    strerror(errno));
250 
251 	ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
252 	ATF_CHECK_MSG(sbuf_cat(sb, test_whitespace_string) == 0,
253 	    "sbuf_cat failed");
254 
255 	/* The best we can do until sbuf_finish(3) is called. */
256 	exp_sbuf_len = (ssize_t)(strlen(test_string) +
257 	    strlen(test_whitespace_string));
258 	test_sbuf_len = sbuf_len(sb);
259 	ATF_REQUIRE_MSG(exp_sbuf_len == test_sbuf_len,
260 	    "sbuf_len(..) => %zd (actual) != %zu (expected)",
261 	    test_sbuf_len, exp_sbuf_len);
262 
263 	ATF_REQUIRE_MSG(sbuf_trim(sb) == 0, "sbuf_trim failed");
264 
265 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
266 	    strerror(errno));
267 
268 	ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
269 	    "sbuf (\"%s\") != test string (\"%s\") (trimmed)", sbuf_data(sb),
270 	    test_string);
271 
272 	sbuf_delete(sb);
273 }
274 
275 ATF_TP_ADD_TCS(tp)
276 {
277 
278 	ATF_TP_ADD_TC(tp, sbuf_bcat_test);
279 	ATF_TP_ADD_TC(tp, sbuf_bcpy_test);
280 	ATF_TP_ADD_TC(tp, sbuf_cat_test);
281 	ATF_TP_ADD_TC(tp, sbuf_cpy_test);
282 	ATF_TP_ADD_TC(tp, sbuf_putc_test);
283 	ATF_TP_ADD_TC(tp, sbuf_trim_test);
284 
285 	return (atf_no_error());
286 }
287