xref: /freebsd/lib/libsbuf/tests/sbuf_core_test.c (revision 991bd461625a2c521d5be4fd6938deed57f60972)
1b824378bSEnji Cooper /*-
2148a8da8SEnji Cooper  * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org>
3b824378bSEnji Cooper  *
4b824378bSEnji Cooper  * Redistribution and use in source and binary forms, with or without
5b824378bSEnji Cooper  * modification, are permitted provided that the following conditions
6b824378bSEnji Cooper  * are met:
7b824378bSEnji Cooper  * 1. Redistributions of source code must retain the above copyright
8b824378bSEnji Cooper  *    notice, this list of conditions and the following disclaimer.
9b824378bSEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
10b824378bSEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
11b824378bSEnji Cooper  *    documentation and/or other materials provided with the distribution.
12b824378bSEnji Cooper  *
13b824378bSEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14b824378bSEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15b824378bSEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16b824378bSEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17b824378bSEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18b824378bSEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19b824378bSEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20b824378bSEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21b824378bSEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22b824378bSEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23b824378bSEnji Cooper  * SUCH DAMAGE.
24b824378bSEnji Cooper  */
25b824378bSEnji Cooper 
26b824378bSEnji Cooper #include <sys/param.h>
27b824378bSEnji Cooper #include <sys/sbuf.h>
28*991bd461SEnji Cooper 
29*991bd461SEnji Cooper #include <atf-c.h>
30b824378bSEnji Cooper #include <errno.h>
31b824378bSEnji Cooper #include <stdarg.h>
32b824378bSEnji Cooper #include <stdio.h>
33b824378bSEnji Cooper #include <stdlib.h>
34b824378bSEnji Cooper #include <string.h>
35b824378bSEnji Cooper #include <unistd.h>
36b824378bSEnji Cooper 
37b824378bSEnji Cooper #include "sbuf_test_common.h"
38b824378bSEnji Cooper 
39b824378bSEnji Cooper static char test_string[] = "this is a test string";
40b824378bSEnji Cooper #define TEST_STRING_CHOP_COUNT 5
41b824378bSEnji Cooper _Static_assert(nitems(test_string) > TEST_STRING_CHOP_COUNT,
42b824378bSEnji Cooper     "test_string is too short");
43b824378bSEnji Cooper 
44b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_clear_test);
ATF_TC_BODY(sbuf_clear_test,tc)45b824378bSEnji Cooper ATF_TC_BODY(sbuf_clear_test, tc)
46b824378bSEnji Cooper {
47b824378bSEnji Cooper 	struct sbuf *sb;
48b824378bSEnji Cooper 	ssize_t buf_len;
49b824378bSEnji Cooper 	pid_t child_proc;
50b824378bSEnji Cooper 
51b824378bSEnji Cooper 	sb = sbuf_new_auto();
52b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
53b824378bSEnji Cooper 	    strerror(errno));
54b824378bSEnji Cooper 
55b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
56b824378bSEnji Cooper 
57b824378bSEnji Cooper 	/*
58b824378bSEnji Cooper 	 * Cheat so we can get the contents of the buffer before calling
59b824378bSEnji Cooper 	 * sbuf_finish(3) below, making additional sbuf changes impossible.
60b824378bSEnji Cooper 	 */
61b824378bSEnji Cooper 	child_proc = atf_utils_fork();
62b824378bSEnji Cooper 	if (child_proc == 0) {
637d7db529SConrad Meyer 		ATF_REQUIRE_EQ_MSG(0, sbuf_finish(sb), "sbuf_finish failed: %s",
647d7db529SConrad Meyer 		    strerror(errno));
657d7db529SConrad Meyer 
66b824378bSEnji Cooper 		sbuf_putbuf(sb);
67b824378bSEnji Cooper 		exit(0);
68b824378bSEnji Cooper 	}
69b824378bSEnji Cooper 	atf_utils_wait(child_proc, 0, test_string, "");
70b824378bSEnji Cooper 
71b824378bSEnji Cooper 	sbuf_clear(sb);
72b824378bSEnji Cooper 
73b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
74b824378bSEnji Cooper 	    strerror(errno));
75b824378bSEnji Cooper 
76b824378bSEnji Cooper 	buf_len = sbuf_len(sb);
77b824378bSEnji Cooper 	ATF_REQUIRE_MSG(buf_len == 0, "sbuf_len (%zd) != 0", buf_len);
78*991bd461SEnji Cooper 	ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), "", "sbuf (\"%s\") was not empty",
79*991bd461SEnji Cooper 	    sbuf_data(sb));
80b824378bSEnji Cooper 
81b824378bSEnji Cooper 	sbuf_delete(sb);
82b824378bSEnji Cooper }
83b824378bSEnji Cooper 
84b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_done_and_sbuf_finish_test);
ATF_TC_BODY(sbuf_done_and_sbuf_finish_test,tc)85b824378bSEnji Cooper ATF_TC_BODY(sbuf_done_and_sbuf_finish_test, tc)
86b824378bSEnji Cooper {
87b824378bSEnji Cooper 	struct sbuf *sb;
88b824378bSEnji Cooper 
89b824378bSEnji Cooper 	sb = sbuf_new_auto();
90b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
91b824378bSEnji Cooper 	    strerror(errno));
92b824378bSEnji Cooper 
93b824378bSEnji Cooper 	ATF_CHECK(sbuf_done(sb) == 0);
94b824378bSEnji Cooper 
95b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
96b824378bSEnji Cooper 	    strerror(errno));
97b824378bSEnji Cooper 
98b824378bSEnji Cooper 	ATF_CHECK(sbuf_done(sb) != 0);
99b824378bSEnji Cooper 
100b824378bSEnji Cooper 	sbuf_delete(sb);
101b824378bSEnji Cooper }
102b824378bSEnji Cooper 
1037d7db529SConrad Meyer static int
drain_ret0(void * arg,const char * data,int len)1047d7db529SConrad Meyer drain_ret0(void *arg, const char *data, int len)
1057d7db529SConrad Meyer {
1067d7db529SConrad Meyer 	(void)arg;
1077d7db529SConrad Meyer 	(void)data;
1087d7db529SConrad Meyer 	(void)len;
1097d7db529SConrad Meyer 
1107d7db529SConrad Meyer 	return (0);
1117d7db529SConrad Meyer }
1127d7db529SConrad Meyer 
1137d7db529SConrad Meyer ATF_TC_WITHOUT_HEAD(sbuf_drain_ret0_test);
ATF_TC_BODY(sbuf_drain_ret0_test,tc)1147d7db529SConrad Meyer ATF_TC_BODY(sbuf_drain_ret0_test, tc)
1157d7db529SConrad Meyer {
1167d7db529SConrad Meyer 	struct sbuf *sb;
1177d7db529SConrad Meyer 
1187d7db529SConrad Meyer 	sb = sbuf_new_auto();
1197d7db529SConrad Meyer 
1207d7db529SConrad Meyer 	sbuf_set_drain(sb, drain_ret0, NULL);
1217d7db529SConrad Meyer 
1227d7db529SConrad Meyer 	sbuf_cat(sb, test_string);
1237d7db529SConrad Meyer 
1247d7db529SConrad Meyer 	ATF_CHECK_EQ_MSG(-1, sbuf_finish(sb),
1257d7db529SConrad Meyer 	    "required to return error when drain func returns 0");
1267d7db529SConrad Meyer 	ATF_CHECK_EQ_MSG(EDEADLK, errno,
1277d7db529SConrad Meyer 	    "errno required to be EDEADLK when drain func returns 0");
1287d7db529SConrad Meyer }
1297d7db529SConrad Meyer 
130b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_len_test);
ATF_TC_BODY(sbuf_len_test,tc)131b824378bSEnji Cooper ATF_TC_BODY(sbuf_len_test, tc)
132b824378bSEnji Cooper {
133b824378bSEnji Cooper 	struct sbuf *sb;
134b824378bSEnji Cooper 	ssize_t buf_len, test_string_len;
135b824378bSEnji Cooper 	int i;
136b824378bSEnji Cooper 
137b824378bSEnji Cooper 	sb = sbuf_new_auto();
138b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
139b824378bSEnji Cooper 	    strerror(errno));
140b824378bSEnji Cooper 
141b824378bSEnji Cooper 	test_string_len = strlen(test_string);
142b824378bSEnji Cooper 	for (i = 0; i < 20; i++) {
143b824378bSEnji Cooper 		buf_len = sbuf_len(sb);
144b824378bSEnji Cooper 		ATF_REQUIRE_MSG(buf_len == (ssize_t)(i * test_string_len),
145b824378bSEnji Cooper 		    "sbuf_len (%zd) != %zu", buf_len, i * test_string_len);
146*991bd461SEnji Cooper 		ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0,
147*991bd461SEnji Cooper 		    "sbuf_cat failed");
148b824378bSEnji Cooper 	}
149b824378bSEnji Cooper 
150b824378bSEnji Cooper #ifdef HAVE_SBUF_SET_FLAGS
151b824378bSEnji Cooper 	sbuf_set_flags(sb, SBUF_INCLUDENUL);
152b824378bSEnji Cooper 	ATF_REQUIRE_MSG((ssize_t)(i * test_string_len + 1) == sbuf_len(sb),
153b824378bSEnji Cooper 	    "sbuf_len(..) didn't report the NUL char");
154b824378bSEnji Cooper #endif
155b824378bSEnji Cooper 
156b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
157b824378bSEnji Cooper 	    strerror(errno));
158b824378bSEnji Cooper 
159b824378bSEnji Cooper 	sbuf_delete(sb);
160b824378bSEnji Cooper }
161b824378bSEnji Cooper 
1627d7db529SConrad Meyer ATF_TC_WITHOUT_HEAD(sbuf_new_fixedlen);
ATF_TC_BODY(sbuf_new_fixedlen,tc)1637d7db529SConrad Meyer ATF_TC_BODY(sbuf_new_fixedlen, tc)
1647d7db529SConrad Meyer {
1657d7db529SConrad Meyer 	char buf[strlen(test_string) + 1];
1667d7db529SConrad Meyer 	struct sbuf sb;
1677d7db529SConrad Meyer 	pid_t child_proc;
1687d7db529SConrad Meyer 
1697d7db529SConrad Meyer 	sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
1707d7db529SConrad Meyer 
1717d7db529SConrad Meyer 	sbuf_cat(&sb, test_string);
1727d7db529SConrad Meyer 
1737d7db529SConrad Meyer 	child_proc = atf_utils_fork();
1747d7db529SConrad Meyer 	if (child_proc == 0) {
175*991bd461SEnji Cooper 		ATF_REQUIRE_EQ_MSG(0, sbuf_finish(&sb),
176*991bd461SEnji Cooper 		    "sbuf_finish failed: %s", strerror(errno));
1777d7db529SConrad Meyer 
1787d7db529SConrad Meyer 		sbuf_putbuf(&sb);
1797d7db529SConrad Meyer 		exit(0);
1807d7db529SConrad Meyer 	}
1817d7db529SConrad Meyer 	atf_utils_wait(child_proc, 0, test_string, "");
1827d7db529SConrad Meyer 
1837d7db529SConrad Meyer 	sbuf_putc(&sb, ' ');
1847d7db529SConrad Meyer 
185*991bd461SEnji Cooper 	ATF_CHECK_EQ_MSG(-1, sbuf_finish(&sb),
186*991bd461SEnji Cooper 	    "failed to return error on overflow");
1877d7db529SConrad Meyer 
1887d7db529SConrad Meyer 	sbuf_delete(&sb);
1897d7db529SConrad Meyer }
1907d7db529SConrad Meyer 
191b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_setpos_test);
ATF_TC_BODY(sbuf_setpos_test,tc)192b824378bSEnji Cooper ATF_TC_BODY(sbuf_setpos_test, tc)
193b824378bSEnji Cooper {
194b824378bSEnji Cooper 	struct sbuf *sb;
195b824378bSEnji Cooper 	size_t test_string_chopped_len, test_string_len;
196b824378bSEnji Cooper 	ssize_t buf_len;
197b824378bSEnji Cooper 
198b824378bSEnji Cooper 	sb = sbuf_new_auto();
199b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
200b824378bSEnji Cooper 	    strerror(errno));
201b824378bSEnji Cooper 
202b824378bSEnji Cooper 	/*
203b824378bSEnji Cooper 	 * An obvious sanity check -- if sbuf_len(..) lies, these invariants
204b824378bSEnji Cooper 	 * are impossible to test.
205b824378bSEnji Cooper 	 */
206b824378bSEnji Cooper 	ATF_REQUIRE(sbuf_len(sb) == 0);
207b824378bSEnji Cooper 
208b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, -1) == -1);
209b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, 0) == 0);
210b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, 1) == -1);
211b824378bSEnji Cooper 
212b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
213b824378bSEnji Cooper 
214b824378bSEnji Cooper 	buf_len = sbuf_len(sb);
215b824378bSEnji Cooper 	test_string_len = strlen(test_string);
216b824378bSEnji Cooper 	test_string_chopped_len = test_string_len - TEST_STRING_CHOP_COUNT;
217b824378bSEnji Cooper 	ATF_REQUIRE_MSG(buf_len == (ssize_t)test_string_len,
218b824378bSEnji Cooper 	    "sbuf length (%zd) != test_string length (%zu)", buf_len,
219b824378bSEnji Cooper 	    test_string_len);
220b824378bSEnji Cooper 
221b824378bSEnji Cooper 	/* Out of bounds (under length) */
222b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, -1) == -1);
223b824378bSEnji Cooper 	/*
224b824378bSEnji Cooper 	 * Out of bounds (over length)
225b824378bSEnji Cooper 	 *
226b824378bSEnji Cooper 	 * Note: SBUF_INCLUDENUL not set, so take '\0' into account.
227b824378bSEnji Cooper 	 */
228b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, test_string_len + 2) == -1);
229b824378bSEnji Cooper 	/* Within bounds */
230b824378bSEnji Cooper 	ATF_CHECK(sbuf_setpos(sb, test_string_chopped_len) == 0);
231b824378bSEnji Cooper 
232b824378bSEnji Cooper 	ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
233b824378bSEnji Cooper 	    strerror(errno));
234b824378bSEnji Cooper 
235b824378bSEnji Cooper 	buf_len = sbuf_len(sb);
236b824378bSEnji Cooper 	ATF_REQUIRE_MSG(buf_len == (ssize_t)test_string_chopped_len,
237b824378bSEnji Cooper 	    "sbuf_setpos didn't truncate string as expected");
238b824378bSEnji Cooper 	ATF_REQUIRE_MSG(strncmp(sbuf_data(sb), test_string, buf_len) == 0,
239b824378bSEnji Cooper 	    "sbuf (\"%s\") != test string (\"%s\") for [0,%zd]", sbuf_data(sb),
240b824378bSEnji Cooper 	    test_string, buf_len);
241b824378bSEnji Cooper 
242b824378bSEnji Cooper 	sbuf_delete(sb);
243b824378bSEnji Cooper }
244b824378bSEnji Cooper 
ATF_TP_ADD_TCS(tp)245b824378bSEnji Cooper ATF_TP_ADD_TCS(tp)
246b824378bSEnji Cooper {
247b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_clear_test);
248b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_done_and_sbuf_finish_test);
2497d7db529SConrad Meyer 	ATF_TP_ADD_TC(tp, sbuf_drain_ret0_test);
250b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_len_test);
2517d7db529SConrad Meyer 	ATF_TP_ADD_TC(tp, sbuf_new_fixedlen);
252b824378bSEnji Cooper #if 0
253b824378bSEnji Cooper 	/* TODO */
254b824378bSEnji Cooper #ifdef HAVE_SBUF_CLEAR_FLAGS
255b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_clear_flags_test);
256b824378bSEnji Cooper #endif
257b824378bSEnji Cooper #ifdef HAVE_SBUF_GET_FLAGS
258b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_get_flags_test);
259b824378bSEnji Cooper #endif
260b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_new_positive_test);
261b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_new_negative_test);
262b824378bSEnji Cooper #ifdef HAVE_SBUF_SET_FLAGS
263b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_set_flags_test);
264b824378bSEnji Cooper #endif
265b824378bSEnji Cooper #endif
266b824378bSEnji Cooper 	ATF_TP_ADD_TC(tp, sbuf_setpos_test);
267b824378bSEnji Cooper 
268b824378bSEnji Cooper 	return (atf_no_error());
269b824378bSEnji Cooper }
270