1 /* $Id: buffer-t.c 10396 2020-11-12 20:19:41Z iulius $
2 *
3 * buffer test suite.
4 *
5 * The canonical version of this file is maintained in the rra-c-util package,
6 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
7 *
8 * Written by Russ Allbery <eagle@eyrie.org>
9 * Copyright 2002-2004, 2006, 2014-2015, 2020 Russ Allbery <eagle@eyrie.org>
10 * Copyright 2011-2014
11 * The Board of Trustees of the Leland Stanford Junior University
12 *
13 * Copying and distribution of this file, with or without modification, are
14 * permitted in any medium without royalty provided the copyright notice and
15 * this notice are preserved. This file is offered as-is, without any
16 * warranty.
17 *
18 * SPDX-License-Identifier: FSFAP
19 */
20
21 #define LIBTEST_NEW_FORMAT 1
22
23 #include "config.h"
24 #include "clibrary.h"
25
26 #include <fcntl.h>
27
28 #include "tap/basic.h"
29 #include "inn/buffer.h"
30 #include "inn/xwrite.h"
31
32 static const char test_string1[] = "This is a test";
33 static const char test_string2[] = " of the buffer system";
34 static const char test_string3[] = "This is a test\0 of the buffer system";
35
36
37 /*
38 * Test buffer_vsprintf. Wrapper needed to generate the va_list.
39 */
40 static void __attribute__((__format__(printf, 2, 3)))
test_vsprintf(struct buffer * buffer,const char * format,...)41 test_vsprintf(struct buffer *buffer, const char *format, ...)
42 {
43 va_list args;
44
45 va_start(args, format);
46 buffer_vsprintf(buffer, format, args);
47 va_end(args);
48 }
49
50
51 /*
52 * Likewise for buffer_append_vsprintf.
53 */
54 static void __attribute__((__format__(printf, 2, 3)))
test_append_vsprintf(struct buffer * buffer,const char * format,...)55 test_append_vsprintf(struct buffer *buffer, const char *format, ...)
56 {
57 va_list args;
58
59 va_start(args, format);
60 buffer_append_vsprintf(buffer, format, args);
61 va_end(args);
62 }
63
64
65 int
main(void)66 main(void)
67 {
68 struct buffer one = {0, 0, 0, NULL};
69 struct buffer two = {0, 0, 0, NULL};
70 struct buffer *three;
71 int fd;
72 char *data;
73 ssize_t count;
74 size_t offset;
75
76 plan(89);
77
78 /* buffer_set, buffer_append, buffer_swap */
79 buffer_set(&one, test_string1, sizeof(test_string1));
80 is_int(1024, one.size, "minimum size is 1024");
81 is_int(0, one.used, "used starts at 0");
82 is_int(sizeof(test_string1), one.left, "left is correct");
83 is_string(test_string1, one.data, "data is correct");
84 buffer_append(&one, test_string2, sizeof(test_string2));
85 is_int(1024, one.size, "appended data doesn't change size");
86 is_int(0, one.used, "or used");
87 is_int(sizeof(test_string3), one.left, "but left is the right size");
88 ok(memcmp(one.data, test_string3, sizeof(test_string3)) == 0,
89 "and the resulting data is correct");
90 one.left -= sizeof(test_string1);
91 one.used += sizeof(test_string1);
92 buffer_append(&one, test_string1, sizeof(test_string1));
93 is_int(1024, one.size, "size still isn't larger after adding data");
94 is_int(sizeof(test_string1), one.used, "and used is preserved on append");
95 is_int(sizeof(test_string3), one.left, "and left is updated properly");
96 ok(memcmp(one.data + one.used, test_string2, sizeof(test_string2)) == 0,
97 "and the middle data is unchanged");
98 ok(memcmp(one.data + one.used + sizeof(test_string2), test_string1,
99 sizeof(test_string1))
100 == 0,
101 "and the final data is correct");
102 buffer_set(&one, test_string1, sizeof(test_string1));
103 buffer_set(&two, test_string2, sizeof(test_string2));
104 buffer_swap(&one, &two);
105 is_int(1024, one.size, "swap #1 size is correct");
106 is_int(0, one.used, "swap #1 used is correct");
107 is_int(sizeof(test_string2), one.left, "swap #1 left is correct");
108 is_string(test_string2, one.data, "swap #1 data is correct");
109 is_int(1024, two.size, "swap #2 size is correct");
110 is_int(0, two.used, "swap #2 used is correct");
111 is_int(sizeof(test_string1), two.left, "swap #2 left is correct");
112 is_string(test_string1, two.data, "swap #2 data is correct");
113 free(one.data);
114 free(two.data);
115 one.data = NULL;
116 two.data = NULL;
117 one.size = 0;
118 two.size = 0;
119
120 /* buffer_resize */
121 three = buffer_new();
122 ok(three != NULL, "buffer_new works");
123 if (three == NULL)
124 bail("buffer_new returned NULL");
125 is_int(0, three->size, "initial size is 0");
126 buffer_set(three, test_string1, sizeof(test_string1));
127 is_int(1024, three->size, "size becomes 1024 when adding data");
128 buffer_resize(three, 512);
129 is_int(1024, three->size, "resizing to something smaller doesn't change");
130 buffer_resize(three, 1025);
131 is_int(2048, three->size, "resizing to something larger goes to 2048");
132 buffer_free(three);
133
134 /* buffer_read, buffer_find_string, buffer_compact */
135 fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
136 if (fd < 0)
137 sysbail("cannot create buffer-test");
138 data = bmalloc(2048);
139 memset(data, 'a', 1023);
140 data[1023] = '\r';
141 data[1024] = '\n';
142 memset(data + 1025, 'b', 1023);
143 if (xwrite(fd, data, 2048) < 2048)
144 sysbail("cannot write to buffer-test");
145 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
146 sysbail("cannot rewind buffer-test");
147 three = buffer_new();
148 ok(three != NULL, "buffer_new works");
149 if (three == NULL)
150 bail("buffer_new returned NULL");
151 is_int(0, three->size, "and initial size is 0");
152 buffer_resize(three, 1024);
153 is_int(1024, three->size, "resize to 1024 works");
154 count = buffer_read(three, fd);
155 is_int(1024, count, "reading into a buffer of size 1024 reads 1024");
156 offset = 0;
157 ok(!buffer_find_string(three, "\r\n", 0, &offset),
158 "buffer_find_string with truncated string fails");
159 is_int(0, offset, "and offset is unchanged");
160 ok(memcmp(three->data, data, three->size) == 0, "buffer data is correct");
161 buffer_resize(three, 2048);
162 is_int(2048, three->size, "resizing the buffer to 2048 works");
163 count = buffer_read(three, fd);
164 is_int(1024, count, "and now we can read the rest of the data");
165 ok(memcmp(three->data, data, 2048) == 0, "and it's all there");
166 ok(!buffer_find_string(three, "\r\n", 1024, &offset),
167 "buffer_find_string with a string starting before offset fails");
168 is_int(0, offset, "and offset is unchanged");
169 ok(buffer_find_string(three, "\r\n", 0, &offset),
170 "finding the string on the whole buffer works");
171 is_int(1023, offset, "and returns the correct location");
172 three->used += 400;
173 three->left -= 400;
174 buffer_compact(three);
175 is_int(2048, three->size, "compacting buffer doesn't change the size");
176 is_int(0, three->used, "but used is now zero");
177 is_int(1648, three->left, "and left is decreased appropriately");
178 ok(memcmp(three->data, data + 400, 1648) == 0, "and the data is correct");
179 count = buffer_read(three, fd);
180 is_int(0, count, "reading at EOF returns 0");
181 close(fd);
182 unlink("buffer-test");
183 free(data);
184 buffer_free(three);
185
186 /* buffer_sprintf and buffer_append_sprintf */
187 three = buffer_new();
188 buffer_append_sprintf(three, "testing %d testing", 6);
189 is_int(0, three->used, "buffer_append_sprintf doesn't change used");
190 is_int(17, three->left, "but sets left correctly");
191 buffer_append(three, "", 1);
192 is_int(18, three->left, "appending a nul works");
193 is_string("testing 6 testing", three->data, "and the data is correct");
194 three->left--;
195 three->used += 5;
196 three->left -= 5;
197 buffer_append_sprintf(three, " %d", 7);
198 is_int(14, three->left, "appending a digit works");
199 buffer_append(three, "", 1);
200 is_string("testing 6 testing 7", three->data, "and the data is correct");
201 buffer_sprintf(three, "%d testing", 8);
202 is_int(9, three->left, "replacing the buffer works");
203 is_string("8 testing", three->data, "and the results are correct");
204 data = bmalloc(1050);
205 memset(data, 'a', 1049);
206 data[1049] = '\0';
207 is_int(1024, three->size, "size before large sprintf is 1024");
208 buffer_sprintf(three, "%s", data);
209 is_int(2048, three->size, "size after large sprintf is 2048");
210 is_int(1049, three->left, "and left is correct");
211 buffer_append(three, "", 1);
212 is_string(data, three->data, "and data is correct");
213 free(data);
214 buffer_free(three);
215
216 /* buffer_read_all */
217 fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666);
218 if (fd < 0)
219 sysbail("cannot create buffer-test");
220 data = bmalloc(2049);
221 memset(data, 'a', 2049);
222 if (xwrite(fd, data, 2049) < 2049)
223 sysbail("cannot write to buffer-test");
224 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
225 sysbail("cannot rewind buffer-test");
226 three = buffer_new();
227 ok(buffer_read_all(three, fd), "buffer_read_all succeeds");
228 is_int(0, three->used, "and unused is zero");
229 is_int(2049, three->left, "and left is correct");
230 is_int(4096, three->size, "and size is correct");
231 ok(memcmp(data, three->data, 2049) == 0, "and data is correct");
232 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
233 sysbail("cannot rewind buffer-test");
234 ok(buffer_read_all(three, fd), "reading again succeeds");
235 is_int(0, three->used, "and used is correct");
236 is_int(4098, three->left, "and left is now larger");
237 is_int(8192, three->size, "and size doubled");
238 ok(memcmp(data, three->data + 2049, 2049) == 0, "and data is correct");
239
240 /* buffer_read_file */
241 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
242 sysbail("cannot rewind buffer-test");
243 buffer_free(three);
244 three = buffer_new();
245 ok(buffer_read_file(three, fd), "buffer_read_file succeeds");
246 is_int(0, three->used, "and leaves unused at 0");
247 is_int(2049, three->left, "and left is correct");
248 is_int(3072, three->size, "and size is a multiple of 1024");
249 ok(memcmp(data, three->data, 2049) == 0, "and the data is correct");
250
251 /* buffer_read_all and buffer_read_file errors */
252 close(fd);
253 ok(!buffer_read_all(three, fd), "buffer_read_all on closed fd fails");
254 is_int(3072, three->size, "and size is unchanged");
255 ok(!buffer_read_file(three, fd), "buffer_read_file on closed fd fails");
256 is_int(3072, three->size, "and size is unchanged");
257 is_int(2049, three->left, "and left is unchanged");
258 unlink("buffer-test");
259 free(data);
260 buffer_free(three);
261
262 /* buffer_vsprintf and buffer_append_vsprintf */
263 three = buffer_new();
264 test_append_vsprintf(three, "testing %d testing", 6);
265 is_int(0, three->used, "buffer_append_vsprintf leaves used as 0");
266 is_int(17, three->left, "and left is correct");
267 buffer_append(three, "", 1);
268 is_int(18, three->left, "and left is correct after appending a nul");
269 is_string("testing 6 testing", three->data, "and data is correct");
270 three->left--;
271 three->used += 5;
272 three->left -= 5;
273 test_append_vsprintf(three, " %d", 7);
274 is_int(14, three->left, "and appending results in the correct left");
275 buffer_append(three, "", 1);
276 is_string("testing 6 testing 7", three->data, "and the right data");
277 test_vsprintf(three, "%d testing", 8);
278 is_int(9, three->left, "replacing the buffer results in the correct size");
279 is_string("8 testing", three->data, "and the correct data");
280 data = bmalloc(1050);
281 memset(data, 'a', 1049);
282 data[1049] = '\0';
283 is_int(1024, three->size, "size is 1024 before large vsprintf");
284 test_vsprintf(three, "%s", data);
285 is_int(2048, three->size, "and 2048 afterwards");
286 is_int(1049, three->left, "and left is correct");
287 buffer_append(three, "", 1);
288 is_string(data, three->data, "and data is correct");
289 free(data);
290 buffer_free(three);
291
292 /* Test buffer_free with NULL and ensure it doesn't explode. */
293 buffer_free(NULL);
294
295 return 0;
296 }
297