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/param.h>
27 #include <sys/sbuf.h>
28
29 #include <atf-c.h>
30 #include <errno.h>
31 #include <libutil.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "sbuf_test_common.h"
37
38 static char test_string[] = "this is a test string";
39 static char test_whitespace_string[] = " \f\n\r\t\v ";
40 static int test_buffer[] = {
41 0,
42 1,
43 2,
44 3,
45 4,
46 5,
47 };
48
49 static void
check_buffers_equal(const void * sb_buf,const void * test_buf,size_t len)50 check_buffers_equal(const void *sb_buf, const void *test_buf, size_t len)
51 {
52 if (memcmp(sb_buf, test_buf, len) != 0) {
53 printf("sbuf:\n");
54 hexdump(sb_buf, len, NULL, 0), printf("test_buf:\n");
55 hexdump(test_buf, len, NULL, 0);
56 atf_tc_fail("contents of sbuf didn't match test_buf contents");
57 }
58 }
59
60 ATF_TC_WITHOUT_HEAD(sbuf_bcat_test);
ATF_TC_BODY(sbuf_bcat_test,tc)61 ATF_TC_BODY(sbuf_bcat_test, tc)
62 {
63 struct sbuf *sb;
64 int *test_buffer_tmp;
65 ssize_t test_sbuf_len;
66
67 test_buffer_tmp = malloc(sizeof(test_buffer) * 2);
68 ATF_REQUIRE_MSG(test_buffer_tmp != NULL, "malloc failed");
69
70 memcpy(test_buffer_tmp, test_buffer, sizeof(test_buffer));
71 memcpy(&test_buffer_tmp[nitems(test_buffer)], test_buffer,
72 sizeof(test_buffer));
73
74 sb = sbuf_new_auto();
75 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
76 strerror(errno));
77
78 ATF_CHECK_MSG(sbuf_bcat(sb, test_buffer, sizeof(test_buffer)) == 0,
79 "sbuf_bcat failed");
80
81 test_sbuf_len = sbuf_len(sb);
82 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
83 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
84 sizeof(test_buffer));
85
86 ATF_CHECK_MSG(sbuf_bcat(sb, test_buffer, sizeof(test_buffer)) == 0,
87 "sbuf_bcat failed");
88
89 test_sbuf_len = sbuf_len(sb);
90 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)(2 * sizeof(test_buffer)),
91 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
92 2 * sizeof(test_buffer));
93
94 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
95 strerror(errno));
96
97 check_buffers_equal(sbuf_data(sb), test_buffer_tmp,
98 (size_t)test_sbuf_len);
99
100 sbuf_delete(sb);
101
102 free(test_buffer_tmp);
103 }
104
105 ATF_TC_WITHOUT_HEAD(sbuf_bcpy_test);
ATF_TC_BODY(sbuf_bcpy_test,tc)106 ATF_TC_BODY(sbuf_bcpy_test, tc)
107 {
108 struct sbuf *sb;
109 ssize_t test_sbuf_len;
110
111 sb = sbuf_new_auto();
112 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
113 strerror(errno));
114
115 ATF_CHECK_MSG(sbuf_bcpy(sb, test_buffer, sizeof(test_buffer)) == 0,
116 "sbuf_bcpy failed");
117
118 test_sbuf_len = sbuf_len(sb);
119 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
120 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
121 sizeof(test_buffer));
122
123 ATF_CHECK_MSG(sbuf_bcpy(sb, test_buffer, sizeof(test_buffer)) == 0,
124 "sbuf_bcpy failed");
125
126 test_sbuf_len = sbuf_len(sb);
127 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)sizeof(test_buffer),
128 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
129 sizeof(test_buffer));
130
131 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
132 strerror(errno));
133
134 check_buffers_equal(sbuf_data(sb), test_buffer, (size_t)test_sbuf_len);
135
136 sbuf_delete(sb);
137 }
138
139 ATF_TC_WITHOUT_HEAD(sbuf_cat_test);
ATF_TC_BODY(sbuf_cat_test,tc)140 ATF_TC_BODY(sbuf_cat_test, tc)
141 {
142 struct sbuf *sb;
143 char *test_string_tmp;
144 ssize_t test_sbuf_len;
145
146 asprintf(&test_string_tmp, "%s%s", test_string, test_string);
147 ATF_REQUIRE_MSG(test_string_tmp != NULL, "asprintf failed");
148
149 sb = sbuf_new_auto();
150 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
151 strerror(errno));
152
153 ATF_CHECK_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
154
155 test_sbuf_len = sbuf_len(sb);
156 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
157 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
158 sizeof(test_string));
159
160 ATF_CHECK_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed");
161
162 test_sbuf_len = sbuf_len(sb);
163 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string_tmp),
164 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
165 strlen(test_string_tmp));
166
167 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
168 strerror(errno));
169
170 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string_tmp,
171 "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
172 test_string_tmp);
173
174 sbuf_delete(sb);
175
176 free(test_string_tmp);
177 }
178
179 ATF_TC_WITHOUT_HEAD(sbuf_cpy_test);
ATF_TC_BODY(sbuf_cpy_test,tc)180 ATF_TC_BODY(sbuf_cpy_test, tc)
181 {
182 struct sbuf *sb;
183 ssize_t test_sbuf_len;
184
185 sb = sbuf_new_auto();
186 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
187 strerror(errno));
188
189 ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
190
191 test_sbuf_len = sbuf_len(sb);
192 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
193 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
194 strlen(test_string));
195
196 ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
197
198 test_sbuf_len = sbuf_len(sb);
199 ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(test_string),
200 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
201 strlen(test_string));
202
203 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
204 strerror(errno));
205
206 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
207 "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
208 test_string);
209
210 sbuf_delete(sb);
211 }
212
213 ATF_TC_WITHOUT_HEAD(sbuf_putc_test);
ATF_TC_BODY(sbuf_putc_test,tc)214 ATF_TC_BODY(sbuf_putc_test, tc)
215 {
216 struct sbuf *sb;
217 ssize_t test_sbuf_len;
218 size_t i;
219
220 sb = sbuf_new_auto();
221 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
222 strerror(errno));
223
224 for (i = 0; i <= strlen(test_string); i++) { /* Include the NUL */
225 ATF_REQUIRE_MSG(sbuf_putc(sb, test_string[i]) == 0,
226 "sbuf_putc failed");
227
228 /* The best we can do until sbuf_finish(3) is called. */
229 test_sbuf_len = sbuf_len(sb);
230 ATF_REQUIRE_MSG((ssize_t)(i + 1) == test_sbuf_len,
231 "sbuf_len(..) => %zd (actual) != %zu (expected)",
232 test_sbuf_len, i + 1);
233 }
234
235 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
236 strerror(errno));
237
238 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
239 "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
240 test_string);
241
242 sbuf_delete(sb);
243 }
244
245 ATF_TC_WITHOUT_HEAD(sbuf_trim_test);
ATF_TC_BODY(sbuf_trim_test,tc)246 ATF_TC_BODY(sbuf_trim_test, tc)
247 {
248 struct sbuf *sb;
249 ssize_t exp_sbuf_len, test_sbuf_len;
250
251 sb = sbuf_new_auto();
252 ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
253 strerror(errno));
254
255 ATF_CHECK_MSG(sbuf_cpy(sb, test_string) == 0, "sbuf_cpy failed");
256 ATF_CHECK_MSG(sbuf_cat(sb, test_whitespace_string) == 0,
257 "sbuf_cat failed");
258
259 /* The best we can do until sbuf_finish(3) is called. */
260 exp_sbuf_len = (ssize_t)(strlen(test_string) +
261 strlen(test_whitespace_string));
262 test_sbuf_len = sbuf_len(sb);
263 ATF_REQUIRE_MSG(exp_sbuf_len == test_sbuf_len,
264 "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
265 exp_sbuf_len);
266
267 ATF_REQUIRE_MSG(sbuf_trim(sb) == 0, "sbuf_trim failed");
268
269 ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
270 strerror(errno));
271
272 ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), test_string,
273 "sbuf (\"%s\") != test string (\"%s\") (trimmed)", sbuf_data(sb),
274 test_string);
275
276 sbuf_delete(sb);
277 }
278
ATF_TP_ADD_TCS(tp)279 ATF_TP_ADD_TCS(tp)
280 {
281 ATF_TP_ADD_TC(tp, sbuf_bcat_test);
282 ATF_TP_ADD_TC(tp, sbuf_bcpy_test);
283 ATF_TP_ADD_TC(tp, sbuf_cat_test);
284 ATF_TP_ADD_TC(tp, sbuf_cpy_test);
285 ATF_TP_ADD_TC(tp, sbuf_putc_test);
286 ATF_TP_ADD_TC(tp, sbuf_trim_test);
287
288 return (atf_no_error());
289 }
290