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