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