1 /*-
2 * Copyright (c) 2017 Enji Cooper <[email protected]>
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 <stdarg.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include <atf-c.h>
37
38 #include "sbuf_test_common.h"
39
40 static char test_string[] = "this is a test string";
41
42 #define MESSAGE_FORMAT "message: %s\n"
43 #define MESSAGE_SEPARATOR ';'
44
45 static int
sbuf_vprintf_helper(struct sbuf * sb,const char * restrict format,...)46 sbuf_vprintf_helper(struct sbuf *sb, const char * restrict format, ...)
47 {
48 va_list ap;
49 int rc;
50
51 va_start(ap, format);
52
53 rc = sbuf_vprintf(sb, format, ap);
54
55 va_end(ap);
56
57 return (rc);
58 }
59
60 ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_null_test);
ATF_TC_BODY(sbuf_printf_drain_null_test,tc)61 ATF_TC_BODY(sbuf_printf_drain_null_test, tc)
62 {
63 struct sbuf *sb;
64 char buf[2];
65 pid_t child_proc;
66
67 sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
68 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
69 strerror(errno));
70
71 child_proc = atf_utils_fork();
72 if (child_proc == 0) {
73 sbuf_set_drain(sb, sbuf_printf_drain, NULL);
74
75 ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
76 "sbuf_cat failed");
77
78 ATF_CHECK_EQ(0, sbuf_finish(sb));
79 exit(0);
80 }
81 atf_utils_wait(child_proc, 0, test_string, "");
82
83 sbuf_delete(sb);
84 }
85
86 ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_test);
ATF_TC_BODY(sbuf_printf_drain_test,tc)87 ATF_TC_BODY(sbuf_printf_drain_test, tc)
88 {
89 struct sbuf *sb;
90 char buf[2];
91 pid_t child_proc;
92 size_t cnt = 0;
93
94 sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
95 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
96 strerror(errno));
97
98 child_proc = atf_utils_fork();
99 if (child_proc == 0) {
100 sbuf_set_drain(sb, sbuf_printf_drain, &cnt);
101
102 ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
103 "sbuf_cat failed");
104
105 ATF_CHECK_EQ(0, sbuf_finish(sb));
106 ATF_CHECK_EQ(strlen(test_string), cnt);
107 exit(0);
108 }
109 atf_utils_wait(child_proc, 0, test_string, "");
110
111 sbuf_delete(sb);
112 }
113
114 ATF_TC_WITHOUT_HEAD(sbuf_printf_test);
ATF_TC_BODY(sbuf_printf_test,tc)115 ATF_TC_BODY(sbuf_printf_test, tc)
116 {
117 struct sbuf *sb;
118 char *test_string_tmp;
119
120 asprintf(&test_string_tmp, "%s%c" MESSAGE_FORMAT,
121 test_string, MESSAGE_SEPARATOR, test_string);
122 ATF_REQUIRE_MSG(test_string_tmp != NULL, "asprintf failed");
123
124 sb = sbuf_new_auto();
125 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
126 strerror(errno));
127
128 ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
129 ATF_REQUIRE_MSG(sbuf_putc(sb, MESSAGE_SEPARATOR) == 0,
130 "sbuf_putc failed");
131
132 ATF_REQUIRE_MSG(sbuf_printf(sb, MESSAGE_FORMAT, test_string) == 0,
133 "sbuf_printf failed");
134
135 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
136 strerror(errno));
137
138 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string_tmp,
139 "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
140 test_string_tmp);
141
142 sbuf_delete(sb);
143
144 free(test_string_tmp);
145 }
146
147 ATF_TC_WITHOUT_HEAD(sbuf_putbuf_test);
ATF_TC_BODY(sbuf_putbuf_test,tc)148 ATF_TC_BODY(sbuf_putbuf_test, tc)
149 {
150 struct sbuf *sb;
151 pid_t child_proc;
152
153 sb = sbuf_new_auto();
154 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
155 strerror(errno));
156
157 ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
158
159 child_proc = atf_utils_fork();
160 if (child_proc == 0) {
161 ATF_CHECK_EQ(0, sbuf_finish(sb));
162 sbuf_putbuf(sb);
163 exit(0);
164 }
165 atf_utils_wait(child_proc, 0, test_string, "");
166
167 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
168 strerror(errno));
169
170 sbuf_delete(sb);
171 }
172
173 ATF_TC_WITHOUT_HEAD(sbuf_vprintf_test);
ATF_TC_BODY(sbuf_vprintf_test,tc)174 ATF_TC_BODY(sbuf_vprintf_test, tc)
175 {
176 struct sbuf *sb;
177 char *test_string_tmp;
178 int rc;
179
180 asprintf(&test_string_tmp, "%s%c" MESSAGE_FORMAT,
181 test_string, MESSAGE_SEPARATOR, test_string);
182 ATF_REQUIRE_MSG(test_string_tmp != NULL, "asprintf failed");
183
184 sb = sbuf_new_auto();
185 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
186 strerror(errno));
187
188 ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
189 ATF_REQUIRE_MSG(sbuf_putc(sb, MESSAGE_SEPARATOR) == 0,
190 "sbuf_putc failed");
191
192 rc = sbuf_vprintf_helper(sb, MESSAGE_FORMAT, test_string);
193 ATF_REQUIRE_MSG(rc == 0, "sbuf_vprintf failed");
194
195 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
196 strerror(errno));
197
198 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string_tmp,
199 "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
200 test_string_tmp);
201
202 sbuf_delete(sb);
203 }
204
ATF_TP_ADD_TCS(tp)205 ATF_TP_ADD_TCS(tp)
206 {
207
208 ATF_TP_ADD_TC(tp, sbuf_printf_drain_null_test);
209 ATF_TP_ADD_TC(tp, sbuf_printf_drain_test);
210 ATF_TP_ADD_TC(tp, sbuf_printf_test);
211 ATF_TP_ADD_TC(tp, sbuf_putbuf_test);
212 ATF_TP_ADD_TC(tp, sbuf_vprintf_test);
213
214 return (atf_no_error());
215 }
216