Thu, 25 Jan 2024 22:01:12 +0100
add cx_array_add() + fix type of cx_array_default_reallocator
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include "cx/test.h"
30 #include "util_allocator.h"
32 #include "cx/buffer.h"
34 static CX_TEST_SUBROUTINE(expect_default_flush_config, CxBuffer *buf) {
35 CX_TEST_ASSERT(buf->flush_blkmax == 0);
36 CX_TEST_ASSERT(buf->flush_blksize == 4096);
37 CX_TEST_ASSERT(buf->flush_threshold == SIZE_MAX);
38 CX_TEST_ASSERT(buf->flush_func == NULL);
39 CX_TEST_ASSERT(buf->flush_target == NULL);
40 }
42 CX_TEST(test_buffer_init_wrap_space) {
43 CxTestingAllocator talloc;
44 cx_testing_allocator_init(&talloc);
45 CxAllocator *alloc = &talloc.base;
46 CX_TEST_DO {
47 CxBuffer buf;
48 void *space = cxMalloc(alloc, 16);
49 cxBufferInit(&buf, space, 16, alloc, CX_BUFFER_DEFAULT);
50 CX_TEST_CALL_SUBROUTINE(expect_default_flush_config, &buf);
51 CX_TEST_ASSERT(buf.space == space);
52 CX_TEST_ASSERT((buf.flags & CX_BUFFER_AUTO_EXTEND) == 0);
53 CX_TEST_ASSERT((buf.flags & CX_BUFFER_FREE_CONTENTS) == 0);
54 CX_TEST_ASSERT(buf.pos == 0);
55 CX_TEST_ASSERT(buf.size == 0);
56 CX_TEST_ASSERT(buf.capacity == 16);
57 CX_TEST_ASSERT(buf.allocator == alloc);
58 cxBufferDestroy(&buf);
59 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
60 cxFree(alloc, space);
61 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
62 }
63 cx_testing_allocator_destroy(&talloc);
64 }
66 CX_TEST(test_buffer_init_wrap_space_auto_extend) {
67 CxTestingAllocator talloc;
68 cx_testing_allocator_init(&talloc);
69 CxAllocator *alloc = &talloc.base;
70 CX_TEST_DO {
71 CxBuffer buf;
72 void *space = cxMalloc(alloc, 16);
73 cxBufferInit(&buf, space, 16, alloc, CX_BUFFER_AUTO_EXTEND);
74 CX_TEST_CALL_SUBROUTINE(expect_default_flush_config, &buf);
75 CX_TEST_ASSERT(buf.space == space);
76 CX_TEST_ASSERT((buf.flags & CX_BUFFER_AUTO_EXTEND) == CX_BUFFER_AUTO_EXTEND);
77 CX_TEST_ASSERT((buf.flags & CX_BUFFER_FREE_CONTENTS) == 0);
78 CX_TEST_ASSERT(buf.pos == 0);
79 CX_TEST_ASSERT(buf.size == 0);
80 CX_TEST_ASSERT(buf.capacity == 16);
81 CX_TEST_ASSERT(buf.allocator == alloc);
82 cxBufferDestroy(&buf);
83 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
84 cxFree(alloc, space);
85 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
86 }
87 cx_testing_allocator_destroy(&talloc);
88 }
90 CX_TEST(test_buffer_init_wrap_space_auto_free) {
91 CxTestingAllocator talloc;
92 cx_testing_allocator_init(&talloc);
93 CxAllocator *alloc = &talloc.base;
94 CX_TEST_DO {
95 CxBuffer buf;
96 void *space = cxMalloc(alloc, 16);
97 cxBufferInit(&buf, space, 16, alloc, CX_BUFFER_FREE_CONTENTS);
98 CX_TEST_CALL_SUBROUTINE(expect_default_flush_config, &buf);
99 CX_TEST_ASSERT(buf.space == space);
100 CX_TEST_ASSERT((buf.flags & CX_BUFFER_AUTO_EXTEND) == 0);
101 CX_TEST_ASSERT((buf.flags & CX_BUFFER_FREE_CONTENTS) == CX_BUFFER_FREE_CONTENTS);
102 CX_TEST_ASSERT(buf.pos == 0);
103 CX_TEST_ASSERT(buf.size == 0);
104 CX_TEST_ASSERT(buf.capacity == 16);
105 CX_TEST_ASSERT(buf.allocator == alloc);
106 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
107 cxBufferDestroy(&buf);
108 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
109 }
110 cx_testing_allocator_destroy(&talloc);
111 }
113 CX_TEST(test_buffer_init_fresh_space) {
114 CxTestingAllocator talloc;
115 cx_testing_allocator_init(&talloc);
116 CxAllocator *alloc = &talloc.base;
117 CX_TEST_DO {
118 CxBuffer buf;
119 cxBufferInit(&buf, NULL, 8, alloc, CX_BUFFER_DEFAULT);
120 CX_TEST_CALL_SUBROUTINE(expect_default_flush_config, &buf);
121 CX_TEST_ASSERT(buf.space != NULL);
122 CX_TEST_ASSERT((buf.flags & CX_BUFFER_AUTO_EXTEND) == 0);
123 CX_TEST_ASSERT((buf.flags & CX_BUFFER_FREE_CONTENTS) == CX_BUFFER_FREE_CONTENTS);
124 CX_TEST_ASSERT(buf.pos == 0);
125 CX_TEST_ASSERT(buf.size == 0);
126 CX_TEST_ASSERT(buf.capacity == 8);
127 CX_TEST_ASSERT(buf.allocator == alloc);
128 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); // space is still allocated
129 cxBufferDestroy(&buf);
130 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
131 }
132 cx_testing_allocator_destroy(&talloc);
133 }
135 CX_TEST(test_buffer_init_on_heap) {
136 CxTestingAllocator talloc;
137 cx_testing_allocator_init(&talloc);
138 CxAllocator *alloc = &talloc.base;
139 CX_TEST_DO {
140 CxBuffer *buf;
141 void *space = cxMalloc(alloc, 16);
142 buf = cxBufferCreate(space, 16, alloc, CX_BUFFER_FREE_CONTENTS);
143 CX_TEST_ASSERT(buf != NULL);
144 CX_TEST_CALL_SUBROUTINE(expect_default_flush_config, buf);
145 CX_TEST_ASSERT(buf->space == space);
146 CX_TEST_ASSERT((buf->flags & CX_BUFFER_AUTO_EXTEND) == 0);
147 CX_TEST_ASSERT((buf->flags & CX_BUFFER_FREE_CONTENTS) == CX_BUFFER_FREE_CONTENTS);
148 CX_TEST_ASSERT(buf->pos == 0);
149 CX_TEST_ASSERT(buf->size == 0);
150 CX_TEST_ASSERT(buf->capacity == 16);
151 CX_TEST_ASSERT(buf->allocator == alloc);
152 cxBufferFree(buf);
153 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
154 }
155 cx_testing_allocator_destroy(&talloc);
156 }
158 CX_TEST(test_buffer_minimum_capacity_sufficient) {
159 CxTestingAllocator talloc;
160 cx_testing_allocator_init(&talloc);
161 CxAllocator *alloc = &talloc.base;
162 CX_TEST_DO {
163 void *space = cxMalloc(alloc, 8);
164 CxBuffer buf;
165 cxBufferInit(&buf, space, 8, alloc, CX_BUFFER_FREE_CONTENTS);
166 memcpy(space, "Testing", 8);
167 buf.size = 8;
168 cxBufferMinimumCapacity(&buf, 6);
169 CX_TEST_ASSERT(buf.capacity == 8);
170 CX_TEST_ASSERT(buf.size == 8);
171 CX_TEST_ASSERT(memcmp(buf.space, "Testing", 8) == 0);
172 cxBufferDestroy(&buf);
173 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
174 }
175 cx_testing_allocator_destroy(&talloc);
176 }
178 CX_TEST(test_buffer_minimum_capacity_extend) {
179 CxTestingAllocator talloc;
180 cx_testing_allocator_init(&talloc);
181 CxAllocator *alloc = &talloc.base;
182 CX_TEST_DO {
183 void *space = cxMalloc(alloc, 8);
184 CxBuffer buf;
185 cxBufferInit(&buf, space, 8, alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend!
186 memcpy(space, "Testing", 8);
187 buf.size = 8;
188 cxBufferMinimumCapacity(&buf, 16);
189 CX_TEST_ASSERT(buf.capacity == 16);
190 CX_TEST_ASSERT(buf.size == 8);
191 CX_TEST_ASSERT(memcmp(buf.space, "Testing", 8) == 0);
192 cxBufferDestroy(&buf);
193 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
194 }
195 cx_testing_allocator_destroy(&talloc);
196 }
198 CX_TEST(test_buffer_clear) {
199 char space[16];
200 strcpy(space, "clear test");
201 CxBuffer buf;
202 cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
203 CX_TEST_DO {
204 CX_TEST_ASSERT(buf.size == 0);
205 // only clear the used part of the buffer
206 cxBufferClear(&buf);
207 CX_TEST_ASSERT(0 == memcmp(space, "clear test", 10));
208 buf.size = 5;
209 buf.pos = 3;
210 cxBufferClear(&buf);
211 CX_TEST_ASSERT(0 == memcmp(space, "\0\0\0\0\0 test", 10));
212 CX_TEST_ASSERT(buf.size == 0);
213 CX_TEST_ASSERT(buf.pos == 0);
214 }
215 cxBufferDestroy(&buf);
216 }
218 CX_TEST(test_buffer_reset) {
219 char space[16];
220 strcpy(space, "reset test");
221 CxBuffer buf;
222 cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
223 CX_TEST_DO {
224 buf.size = 5;
225 buf.pos = 3;
226 cxBufferReset(&buf);
227 CX_TEST_ASSERT(0 == memcmp(space, "reset test", 10));
228 CX_TEST_ASSERT(buf.size == 0);
229 CX_TEST_ASSERT(buf.pos == 0);
230 }
231 cxBufferDestroy(&buf);
232 }
234 CX_TEST(test_buffer_seek_set_zero) {
235 CxBuffer buf;
236 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
237 buf.size = 6;
238 buf.pos = 3;
239 CX_TEST_DO {
240 int result = cxBufferSeek(&buf, 0, SEEK_SET);
241 CX_TEST_ASSERT(result == 0);
242 CX_TEST_ASSERT(buf.pos == 0);
243 }
244 cxBufferDestroy(&buf);
245 }
247 CX_TEST(test_buffer_seek_set_valid) {
248 CxBuffer buf;
249 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
250 buf.size = 6;
251 buf.pos = 3;
252 CX_TEST_DO {
253 int result = cxBufferSeek(&buf, 5, SEEK_SET);
254 CX_TEST_ASSERT(result == 0);
255 CX_TEST_ASSERT(buf.pos == 5);
256 }
257 cxBufferDestroy(&buf);
258 }
260 CX_TEST(test_buffer_seek_set_invalid) {
261 CxBuffer buf;
262 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
263 buf.size = 6;
264 buf.pos = 3;
265 CX_TEST_DO {
266 int result = cxBufferSeek(&buf, 6, SEEK_SET);
267 CX_TEST_ASSERT(result != 0);
268 CX_TEST_ASSERT(buf.pos == 3);
269 }
270 cxBufferDestroy(&buf);
271 }
273 CX_TEST(test_buffer_seek_cur_zero) {
274 CxBuffer buf;
275 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
276 buf.size = 6;
277 buf.pos = 3;
278 CX_TEST_DO {
279 int result = cxBufferSeek(&buf, 0, SEEK_CUR);
280 CX_TEST_ASSERT(result == 0);
281 CX_TEST_ASSERT(buf.pos == 3);
282 }
283 cxBufferDestroy(&buf);
284 }
286 CX_TEST(test_buffer_seek_cur_valid_positive) {
287 CxBuffer buf;
288 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
289 buf.size = 6;
290 buf.pos = 3;
291 CX_TEST_DO {
292 int result = cxBufferSeek(&buf, 2, SEEK_CUR);
293 CX_TEST_ASSERT(result == 0);
294 CX_TEST_ASSERT(buf.pos == 5);
295 }
296 cxBufferDestroy(&buf);
297 }
299 CX_TEST(test_buffer_seek_cur_valid_negative) {
300 CxBuffer buf;
301 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
302 buf.size = 6;
303 buf.pos = 3;
304 CX_TEST_DO {
305 int result = cxBufferSeek(&buf, -3, SEEK_CUR);
306 CX_TEST_ASSERT(result == 0);
307 CX_TEST_ASSERT(buf.pos == 0);
308 }
309 cxBufferDestroy(&buf);
310 }
312 CX_TEST(test_buffer_seek_cur_invalid_positive) {
313 CxBuffer buf;
314 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
315 buf.size = 6;
316 buf.pos = 3;
317 CX_TEST_DO {
318 int result = cxBufferSeek(&buf, 3, SEEK_CUR);
319 CX_TEST_ASSERT(result != 0);
320 CX_TEST_ASSERT(buf.pos == 3);
321 }
322 cxBufferDestroy(&buf);
323 }
325 CX_TEST(test_buffer_seek_cur_invalid_negative) {
326 CxBuffer buf;
327 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
328 buf.size = 6;
329 buf.pos = 3;
330 CX_TEST_DO {
331 int result = cxBufferSeek(&buf, -4, SEEK_CUR);
332 CX_TEST_ASSERT(result != 0);
333 CX_TEST_ASSERT(buf.pos == 3);
334 }
335 cxBufferDestroy(&buf);
336 }
338 CX_TEST(test_buffer_seek_end_zero) {
339 CxBuffer buf;
340 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
341 buf.size = 6;
342 buf.pos = 3;
343 CX_TEST_DO {
344 int result = cxBufferSeek(&buf, 0, SEEK_END);
345 // the (past-the-)end position is always invalid
346 CX_TEST_ASSERT(result != 0);
347 CX_TEST_ASSERT(buf.pos == 3);
348 }
349 cxBufferDestroy(&buf);
350 }
352 CX_TEST(test_buffer_seek_end_valid) {
353 CxBuffer buf;
354 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
355 buf.size = 6;
356 buf.pos = 3;
357 CX_TEST_DO {
358 int result = cxBufferSeek(&buf, -6, SEEK_END);
359 CX_TEST_ASSERT(result == 0);
360 CX_TEST_ASSERT(buf.pos == 0);
361 }
362 cxBufferDestroy(&buf);
363 }
365 CX_TEST(test_buffer_seek_end_invalid) {
366 CxBuffer buf;
367 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
368 buf.size = 6;
369 buf.pos = 3;
370 CX_TEST_DO {
371 int result = cxBufferSeek(&buf, 1, SEEK_END);
372 CX_TEST_ASSERT(result != 0);
373 CX_TEST_ASSERT(buf.pos == 3);
374 }
375 cxBufferDestroy(&buf);
376 }
378 CX_TEST(test_buffer_seek_whence_invalid) {
379 CxBuffer buf;
380 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
381 buf.size = 6;
382 buf.pos = 3;
383 CX_TEST_DO {
384 int result = cxBufferSeek(&buf, 2, 9000);
385 CX_TEST_ASSERT(result != 0);
386 CX_TEST_ASSERT(buf.size == 6);
387 CX_TEST_ASSERT(buf.pos == 3);
388 }
389 cxBufferDestroy(&buf);
390 }
392 CX_TEST(test_buffer_eof_reached) {
393 CxBuffer buf;
394 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
395 buf.size = buf.pos = 3;
396 CX_TEST_DO {
397 CX_TEST_ASSERT(cxBufferEof(&buf));
398 buf.pos = buf.size - 1;
399 CX_TEST_ASSERT(!cxBufferEof(&buf));
400 cxBufferPut(&buf, 'a');
401 CX_TEST_ASSERT(cxBufferEof(&buf));
402 }
403 cxBufferDestroy(&buf);
404 }
406 CX_TEST(test_buffer_eof_not_reached) {
407 CxBuffer buf;
408 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
409 buf.size = 6;
410 CX_TEST_DO {
411 buf.pos = buf.size - 1;
412 CX_TEST_ASSERT(!cxBufferEof(&buf));
413 buf.pos = 0;
414 cxBufferWrite("test", 1, 5, &buf);
415 CX_TEST_ASSERT(!cxBufferEof(&buf));
416 }
417 cxBufferDestroy(&buf);
418 }
420 #define TEST_BUFFER_SHIFT_SETUP(buf) \
421 CxTestingAllocator talloc; \
422 cx_testing_allocator_init(&talloc); \
423 CxAllocator *alloc = &talloc.base; \
424 CxBuffer buf; \
425 cxBufferInit(&buf, NULL, 16, alloc, CX_BUFFER_DEFAULT); \
426 memcpy(buf.space, "test____XXXXXXXX", 16); \
427 buf.capacity = 8; \
428 buf.pos = 4; \
429 buf.size = 4
430 #define TEST_BUFFER_SHIFT_TEARDOWN(buf) \
431 cxBufferDestroy(&buf); \
432 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); \
433 cx_testing_allocator_destroy(&talloc)
436 CX_TEST(test_buffer_shift_left_zero) {
437 TEST_BUFFER_SHIFT_SETUP(buf);
438 CX_TEST_DO {
439 int ret = cxBufferShiftLeft(&buf, 0);
440 CX_TEST_ASSERT(ret == 0);
441 CX_TEST_ASSERT(buf.pos == 4);
442 CX_TEST_ASSERT(buf.size == 4);
443 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
444 TEST_BUFFER_SHIFT_TEARDOWN(buf);
445 }
446 }
448 CX_TEST(test_buffer_shift_left_zero_offset_interface) {
449 TEST_BUFFER_SHIFT_SETUP(buf);
450 CX_TEST_DO {
451 int ret = cxBufferShift(&buf, -0);
452 CX_TEST_ASSERT(ret == 0);
453 CX_TEST_ASSERT(buf.pos == 4);
454 CX_TEST_ASSERT(buf.size == 4);
455 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
456 TEST_BUFFER_SHIFT_TEARDOWN(buf);
457 }
458 }
460 CX_TEST(test_buffer_shift_left_standard) {
461 TEST_BUFFER_SHIFT_SETUP(buf);
462 CX_TEST_DO {
463 int ret = cxBufferShiftLeft(&buf, 2);
464 CX_TEST_ASSERT(ret == 0);
465 CX_TEST_ASSERT(buf.pos == 2);
466 CX_TEST_ASSERT(buf.size == 2);
467 CX_TEST_ASSERT(memcmp(buf.space, "stst____XXXXXXXX", 16) == 0);
468 TEST_BUFFER_SHIFT_TEARDOWN(buf);
469 }
470 }
472 CX_TEST(test_buffer_shift_left_overshift) {
473 TEST_BUFFER_SHIFT_SETUP(buf);
474 CX_TEST_DO {
475 int ret = cxBufferShiftLeft(&buf, 6);
476 CX_TEST_ASSERT(ret == 0);
477 CX_TEST_ASSERT(buf.pos == 0);
478 CX_TEST_ASSERT(buf.size == 0);
479 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
480 TEST_BUFFER_SHIFT_TEARDOWN(buf);
481 }
482 }
484 CX_TEST(test_buffer_shift_left_overshift_pos_only) {
485 TEST_BUFFER_SHIFT_SETUP(buf);
486 buf.pos = 2;
487 CX_TEST_DO {
488 int ret = cxBufferShiftLeft(&buf, 3);
489 CX_TEST_ASSERT(ret == 0);
490 CX_TEST_ASSERT(buf.pos == 0);
491 CX_TEST_ASSERT(buf.size == 1);
492 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
493 TEST_BUFFER_SHIFT_TEARDOWN(buf);
494 }
495 }
497 CX_TEST(test_buffer_shift_left_offset_interface) {
498 TEST_BUFFER_SHIFT_SETUP(buf);
499 buf.pos = 3;
500 CX_TEST_DO {
501 int ret = cxBufferShift(&buf, -2);
502 CX_TEST_ASSERT(ret == 0);
503 CX_TEST_ASSERT(buf.pos == 1);
504 CX_TEST_ASSERT(buf.size == 2);
505 CX_TEST_ASSERT(memcmp(buf.space, "stst____XXXXXXXX", 16) == 0);
506 TEST_BUFFER_SHIFT_TEARDOWN(buf);
507 }
508 }
510 CX_TEST(test_buffer_shift_right_zero) {
511 TEST_BUFFER_SHIFT_SETUP(buf);
512 CX_TEST_DO {
513 int ret = cxBufferShiftRight(&buf, 0);
514 CX_TEST_ASSERT(ret == 0);
515 CX_TEST_ASSERT(buf.pos == 4);
516 CX_TEST_ASSERT(buf.size == 4);
517 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
518 TEST_BUFFER_SHIFT_TEARDOWN(buf);
519 }
520 }
522 CX_TEST(test_buffer_shift_right_zero_offset_interface) {
523 TEST_BUFFER_SHIFT_SETUP(buf);
524 CX_TEST_DO {
525 int ret = cxBufferShift(&buf, +0);
526 CX_TEST_ASSERT(ret == 0);
527 CX_TEST_ASSERT(buf.pos == 4);
528 CX_TEST_ASSERT(buf.size == 4);
529 CX_TEST_ASSERT(memcmp(buf.space, "test____XXXXXXXX", 16) == 0);
530 TEST_BUFFER_SHIFT_TEARDOWN(buf);
531 }
532 }
534 CX_TEST(test_buffer_shift_right_standard) {
535 TEST_BUFFER_SHIFT_SETUP(buf);
536 CX_TEST_DO {
537 int ret = cxBufferShiftRight(&buf, 3);
538 CX_TEST_ASSERT(ret == 0);
539 CX_TEST_ASSERT(buf.pos == 7);
540 CX_TEST_ASSERT(buf.size == 7);
541 CX_TEST_ASSERT(memcmp(buf.space, "testest_XXXXXXXX", 16) == 0);
542 TEST_BUFFER_SHIFT_TEARDOWN(buf);
543 }
544 }
546 CX_TEST(test_buffer_shift_right_overshift_discard) {
547 TEST_BUFFER_SHIFT_SETUP(buf);
548 CX_TEST_DO {
549 int ret = cxBufferShiftRight(&buf, 6);
550 CX_TEST_ASSERT(ret == 0);
551 CX_TEST_ASSERT(buf.pos == 8);
552 CX_TEST_ASSERT(buf.size == 8);
553 CX_TEST_ASSERT(buf.capacity == 8);
554 CX_TEST_ASSERT(memcmp(buf.space, "test__teXXXXXXXX", 16) == 0);
555 TEST_BUFFER_SHIFT_TEARDOWN(buf);
556 }
557 }
559 CX_TEST(test_buffer_shift_right_overshift_extend) {
560 TEST_BUFFER_SHIFT_SETUP(buf);
561 buf.flags |= CX_BUFFER_AUTO_EXTEND;
562 CX_TEST_DO {
563 int ret = cxBufferShiftRight(&buf, 6);
564 CX_TEST_ASSERT(ret == 0);
565 CX_TEST_ASSERT(buf.pos == 10);
566 CX_TEST_ASSERT(buf.size == 10);
567 CX_TEST_ASSERT(buf.capacity >= 10);
568 // cannot assert more than 10 bytes because
569 // the buffer was required to reallocate the space
570 CX_TEST_ASSERT(memcmp(buf.space, "test__test", 10) == 0);
571 TEST_BUFFER_SHIFT_TEARDOWN(buf);
572 }
573 }
575 CX_TEST(test_buffer_shift_right_offset_interface) {
576 TEST_BUFFER_SHIFT_SETUP(buf);
577 buf.pos = 3;
578 CX_TEST_DO {
579 int ret = cxBufferShift(&buf, 2);
580 CX_TEST_ASSERT(ret == 0);
581 CX_TEST_ASSERT(buf.pos == 5);
582 CX_TEST_ASSERT(buf.size == 6);
583 CX_TEST_ASSERT(memcmp(buf.space, "tetest__XXXXXXXX", 16) == 0);
584 TEST_BUFFER_SHIFT_TEARDOWN(buf);
585 }
586 }
588 static size_t mock_write_limited_rate(
589 void const *ptr,
590 size_t size,
591 __attribute__((unused)) size_t nitems,
592 CxBuffer *buffer
593 ) {
594 // simulate limited target drain capacity
595 static bool full = false;
596 if (full) {
597 full = false;
598 return 0;
599 } else {
600 full = true;
601 return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer);
602 }
603 }
605 CX_TEST(test_buffer_write_size_one_fit) {
606 CxBuffer buf, target;
607 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
608 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
609 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
610 buf.capacity = 8;
611 buf.size = buf.pos = 4;
612 const char *data = "test";
613 CX_TEST_DO {
614 size_t written = cxBufferWrite(data, 1, 4, &buf);
615 CX_TEST_ASSERT(written == 4);
616 CX_TEST_ASSERT(buf.size == 8);
617 CX_TEST_ASSERT(buf.pos == 8);
618 CX_TEST_ASSERT(buf.capacity == 8);
619 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptest", 8));
620 }
622 cxBufferDestroy(&buf);
623 cxBufferDestroy(&target);
624 }
626 CX_TEST(test_buffer_write_size_one_discard) {
627 CxBuffer buf, target;
628 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
629 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
630 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
631 buf.capacity = 8;
632 buf.size = buf.pos = 4;
633 const char *data = "testing";
634 CX_TEST_DO {
635 size_t written = cxBufferWrite(data, 1, 7, &buf);
636 CX_TEST_ASSERT(written == 4);
637 CX_TEST_ASSERT(buf.size == 8);
638 CX_TEST_ASSERT(buf.pos == 8);
639 CX_TEST_ASSERT(buf.capacity == 8);
640 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptest\0", 9));
641 }
642 cxBufferDestroy(&buf);
643 cxBufferDestroy(&target);
644 }
646 CX_TEST(test_buffer_write_size_one_extend) {
647 CxBuffer buf, target;
648 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
649 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
650 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
651 buf.capacity = 8;
652 buf.size = buf.pos = 4;
653 buf.flags |= CX_BUFFER_AUTO_EXTEND;
654 const char *data = "testing";
655 CX_TEST_DO {
656 size_t written = cxBufferWrite(data, 1, 7, &buf);
657 CX_TEST_ASSERT(written == 7);
658 CX_TEST_ASSERT(buf.size == 11);
659 CX_TEST_ASSERT(buf.pos == 11);
660 CX_TEST_ASSERT(buf.capacity >= 11);
661 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptesting", 11));
662 }
663 cxBufferDestroy(&buf);
664 cxBufferDestroy(&target);
665 }
667 CX_TEST(test_buffer_write_multibyte_fit) {
668 CxBuffer buf, target;
669 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
670 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
671 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
672 buf.capacity = 8;
673 buf.size = buf.pos = 4;
674 const char *data = "test";
675 CX_TEST_DO {
676 size_t written = cxBufferWrite(data, 2, 2, &buf);
677 CX_TEST_ASSERT(written == 2);
678 CX_TEST_ASSERT(buf.size == 8);
679 CX_TEST_ASSERT(buf.pos == 8);
680 CX_TEST_ASSERT(buf.capacity == 8);
681 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptest", 8));
682 }
683 cxBufferDestroy(&buf);
684 cxBufferDestroy(&target);
685 }
687 CX_TEST(test_buffer_write_multibyte_discard) {
688 CxBuffer buf, target;
689 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
690 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
691 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
692 buf.capacity = 8;
693 buf.size = 4;
694 buf.pos = 3;
695 const char *data = "testing";
696 CX_TEST_DO {
697 size_t written = cxBufferWrite(data, 2, 4, &buf);
698 // remember: whole elements are discarded if they do not fit
699 CX_TEST_ASSERT(written == 2);
700 CX_TEST_ASSERT(buf.size == 7);
701 CX_TEST_ASSERT(buf.pos == 7);
702 CX_TEST_ASSERT(buf.capacity == 8);
703 CX_TEST_ASSERT(0 == memcmp(buf.space, "pretest\0", 8));
704 }
705 cxBufferDestroy(&buf);
706 cxBufferDestroy(&target);
707 }
709 CX_TEST(test_buffer_write_multibyte_extend) {
710 CxBuffer buf, target;
711 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
712 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
713 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
714 buf.capacity = 8;
715 buf.size = 4;
716 buf.pos = 3;
717 buf.flags |= CX_BUFFER_AUTO_EXTEND;
718 const char *data = "tester";
719 CX_TEST_DO {
720 size_t written = cxBufferWrite(data, 2, 3, &buf);
721 // remember: whole elements are discarded if they do not fit
722 CX_TEST_ASSERT(written == 3);
723 CX_TEST_ASSERT(buf.size == 9);
724 CX_TEST_ASSERT(buf.pos == 9);
725 CX_TEST_ASSERT(buf.capacity >= 9);
726 CX_TEST_ASSERT(0 == memcmp(buf.space, "pretester", 9));
727 }
728 cxBufferDestroy(&buf);
729 cxBufferDestroy(&target);
730 }
732 CX_TEST(test_buffer_put_fit) {
733 CxBuffer buf, target;
734 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
735 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
736 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
737 buf.capacity = 8;
738 buf.size = buf.pos = 4;
739 CX_TEST_DO {
740 int c = cxBufferPut(&buf, 0x200 | 'a');
741 CX_TEST_ASSERT(c == 'a');
742 CX_TEST_ASSERT(buf.size == 5);
743 CX_TEST_ASSERT(buf.pos == 5);
744 CX_TEST_ASSERT(buf.capacity == 8);
745 CX_TEST_ASSERT(0 == memcmp(buf.space, "prepa\0", 6));
746 }
747 cxBufferDestroy(&buf);
748 cxBufferDestroy(&target);
749 }
751 CX_TEST(test_buffer_put_discard) {
752 CxBuffer buf, target;
753 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
754 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
755 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
756 buf.capacity = 8;
757 buf.size = 4;
758 buf.pos = 8;
759 CX_TEST_DO {
760 int c = cxBufferPut(&buf, 0x200 | 'a');
761 CX_TEST_ASSERT(c == EOF);
762 CX_TEST_ASSERT(buf.size == 4);
763 CX_TEST_ASSERT(buf.pos == 8);
764 CX_TEST_ASSERT(buf.capacity == 8);
765 CX_TEST_ASSERT(0 == memcmp(buf.space, "prep\0\0\0\0\0", 9));
766 }
767 cxBufferDestroy(&buf);
768 cxBufferDestroy(&target);
769 }
771 CX_TEST(test_buffer_put_extend) {
772 CxBuffer buf, target;
773 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
774 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
775 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
776 buf.capacity = 8;
777 buf.size = 4;
778 buf.pos = 8;
779 buf.flags |= CX_BUFFER_AUTO_EXTEND;
780 CX_TEST_DO {
781 int c = cxBufferPut(&buf, 0x200 | 'a');
782 CX_TEST_ASSERT(c == 'a');
783 CX_TEST_ASSERT(buf.size == 9);
784 CX_TEST_ASSERT(buf.pos == 9);
785 CX_TEST_ASSERT(buf.capacity >= 9);
786 CX_TEST_ASSERT(0 == memcmp(buf.space, "prep\0\0\0\0a", 9));
787 }
788 cxBufferDestroy(&buf);
789 cxBufferDestroy(&target);
790 }
792 CX_TEST(test_buffer_put_string_fit) {
793 CxBuffer buf, target;
794 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
795 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
796 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
797 buf.capacity = 8;
798 buf.size = buf.pos = 4;
799 const char *data = "test";
800 CX_TEST_DO {
801 size_t written = cxBufferPutString(&buf, data);
802 CX_TEST_ASSERT(written == 4);
803 CX_TEST_ASSERT(buf.size == 8);
804 CX_TEST_ASSERT(buf.pos == 8);
805 CX_TEST_ASSERT(buf.capacity == 8);
806 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptest", 8));
807 }
808 cxBufferDestroy(&buf);
809 cxBufferDestroy(&target);
810 }
812 CX_TEST(test_buffer_put_string_discard) {
813 CxBuffer buf, target;
814 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
815 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
816 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
817 buf.capacity = 8;
818 buf.size = buf.pos = 4;
819 const char *data = "testing";
820 CX_TEST_DO {
821 size_t written = cxBufferPutString(&buf, data);
822 CX_TEST_ASSERT(written == 4);
823 CX_TEST_ASSERT(buf.size == 8);
824 CX_TEST_ASSERT(buf.pos == 8);
825 CX_TEST_ASSERT(buf.capacity == 8);
826 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptest\0", 9));
827 }
828 cxBufferDestroy(&buf);
829 cxBufferDestroy(&target);
830 }
832 CX_TEST(test_buffer_put_string_extend) {
833 CxBuffer buf, target;
834 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
835 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
836 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
837 buf.capacity = 8;
838 buf.size = buf.pos = 4;
839 buf.flags |= CX_BUFFER_AUTO_EXTEND;
840 const char *data = "testing";
841 CX_TEST_DO {
842 size_t written = cxBufferPutString(&buf, data);
843 CX_TEST_ASSERT(written == 7);
844 CX_TEST_ASSERT(buf.size == 11);
845 CX_TEST_ASSERT(buf.pos == 11);
846 CX_TEST_ASSERT(buf.capacity >= 11);
847 CX_TEST_ASSERT(0 == memcmp(buf.space, "preptesting", 11));
848 }
849 cxBufferDestroy(&buf);
850 cxBufferDestroy(&target);
851 }
853 CX_TEST(test_buffer_write_size_overflow) {
854 CxBuffer buf, target;
855 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
856 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
857 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
858 buf.capacity = 8;
859 buf.size = buf.pos = 4;
860 const char *data = "testing";
861 CX_TEST_DO {
862 size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf);
863 CX_TEST_ASSERT(written == 0);
864 CX_TEST_ASSERT(buf.capacity == 8);
865 CX_TEST_ASSERT(buf.pos == 4);
866 CX_TEST_ASSERT(buf.size == 4);
867 CX_TEST_ASSERT(0 == memcmp(buf.space, "prep\0", 5));
868 }
869 cxBufferDestroy(&buf);
870 cxBufferDestroy(&target);
871 }
873 CX_TEST(test_buffer_write_capacity_overflow) {
874 CxBuffer buf, target;
875 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
876 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
877 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
878 buf.capacity = 8;
879 buf.size = buf.pos = 4;
880 buf.flags |= CX_BUFFER_AUTO_EXTEND;
881 const char *data = "testing";
882 CX_TEST_DO {
883 size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf);
884 CX_TEST_ASSERT(written == 0);
885 CX_TEST_ASSERT(buf.capacity == 8);
886 CX_TEST_ASSERT(buf.pos == 4);
887 CX_TEST_ASSERT(buf.size == 4);
888 CX_TEST_ASSERT(0 == memcmp(buf.space, "prep\0", 5));
889 }
890 cxBufferDestroy(&buf);
891 cxBufferDestroy(&target);
892 }
894 CX_TEST(test_buffer_write_only_overwrite) {
895 CxBuffer buf, target;
896 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
897 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
898 memcpy(buf.space, "preptest\0\0\0\0\0\0\0\0", 16);
899 buf.capacity = 8;
900 buf.pos = 3;
901 buf.size = 8;
902 buf.flags |= CX_BUFFER_AUTO_EXTEND;
903 CX_TEST_DO {
904 size_t written = cxBufferWrite("XXX", 2, 2, &buf);
905 CX_TEST_ASSERT(written == 2);
906 CX_TEST_ASSERT(buf.capacity == 8);
907 CX_TEST_ASSERT(buf.size == 8);
908 CX_TEST_ASSERT(buf.pos == 7);
909 CX_TEST_ASSERT(0 == memcmp(buf.space, "preXXX\0t", 8));
910 }
911 cxBufferDestroy(&buf);
912 cxBufferDestroy(&target);
913 }
915 CX_TEST(test_buffer_write_flush_at_capacity) {
916 CxBuffer buf, target;
917 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
918 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
919 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
920 buf.capacity = 8;
921 buf.size = buf.pos = 4;
922 buf.flush_target = ⌖
923 buf.flush_func = (cx_write_func)cxBufferWrite;
924 buf.flush_blkmax = 1;
925 CX_TEST_DO {
926 size_t written = cxBufferWrite("foo", 1, 3, &buf);
927 CX_TEST_ASSERT(written == 3);
928 CX_TEST_ASSERT(buf.pos == 7);
929 CX_TEST_ASSERT(buf.size == 7);
930 CX_TEST_ASSERT(target.pos == 0);
931 CX_TEST_ASSERT(target.size == 0);
932 written = cxBufferWrite("hello", 1, 5, &buf);
933 CX_TEST_ASSERT(written == 5);
934 CX_TEST_ASSERT(buf.pos == 0);
935 CX_TEST_ASSERT(buf.size == 0);
936 CX_TEST_ASSERT(buf.capacity == 8);
937 CX_TEST_ASSERT(target.pos == 12);
938 CX_TEST_ASSERT(target.size == 12);
939 CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoohello", 12));
940 }
941 cxBufferDestroy(&buf);
942 cxBufferDestroy(&target);
943 }
945 CX_TEST(test_buffer_write_flush_at_threshold) {
946 CxBuffer buf, target;
947 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
948 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
949 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
950 buf.capacity = 8;
951 buf.size = buf.pos = 4;
952 buf.flush_target = ⌖
953 buf.flush_func = (cx_write_func)cxBufferWrite;
954 buf.flush_blkmax = 1;
955 buf.flush_threshold = 12;
956 buf.flags |= CX_BUFFER_AUTO_EXTEND;
957 CX_TEST_DO {
958 size_t written = cxBufferWrite("foobar", 1, 6, &buf);
959 CX_TEST_ASSERT(written == 6);
960 CX_TEST_ASSERT(buf.pos == 10);
961 CX_TEST_ASSERT(buf.size == 10);
962 CX_TEST_ASSERT(buf.capacity >= 10);
963 CX_TEST_ASSERT(buf.capacity <= 12);
964 CX_TEST_ASSERT(target.pos == 0);
965 CX_TEST_ASSERT(target.size == 0);
966 written = cxBufferWrite("hello", 1, 5, &buf);
967 CX_TEST_ASSERT(written == 5);
968 CX_TEST_ASSERT(buf.pos == 0);
969 CX_TEST_ASSERT(buf.size == 0);
970 CX_TEST_ASSERT(buf.capacity <= 12);
971 CX_TEST_ASSERT(target.pos == 15);
972 CX_TEST_ASSERT(target.size == 15);
973 CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoobarhello", 15));
974 }
975 cxBufferDestroy(&buf);
976 cxBufferDestroy(&target);
977 }
979 CX_TEST(test_buffer_write_flush_rate_limited) {
980 CxBuffer buf, target;
981 cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
982 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
983 memcpy(buf.space, "prep\0\0\0\0\0\0\0\0\0\0\0\0", 16);
984 buf.capacity = 8;
985 buf.size = buf.pos = 4;
986 buf.flush_target = ⌖
987 buf.flush_blkmax = 1;
988 // limit the rate of the flush function and the capacity of the target
989 buf.flush_func = (cx_write_func) mock_write_limited_rate;
990 target.capacity = 16;
991 target.flags &= ~CX_BUFFER_AUTO_EXTEND;
992 CX_TEST_DO {
993 size_t written = cxBufferWrite("foo", 1, 3, &buf);
994 CX_TEST_ASSERT(written == 3);
995 CX_TEST_ASSERT(buf.pos == 7);
996 CX_TEST_ASSERT(buf.size == 7);
997 CX_TEST_ASSERT(target.pos == 0);
998 CX_TEST_ASSERT(target.size == 0);
999 written = cxBufferWrite("hello, world!", 1, 13, &buf);
1000 // " world!" fits into this buffer, the remaining stuff is flushed out
1001 CX_TEST_ASSERT(written == 13);
1002 CX_TEST_ASSERT(buf.pos == 7);
1003 CX_TEST_ASSERT(buf.size == 7);
1004 CX_TEST_ASSERT(buf.capacity == 8);
1005 CX_TEST_ASSERT(0 == memcmp(buf.space, " world!", 7));
1006 CX_TEST_ASSERT(target.pos == 13);
1007 CX_TEST_ASSERT(target.size == 13);
1008 CX_TEST_ASSERT(target.capacity == 16);
1009 CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoohello,", 13));
1010 }
1011 cxBufferDestroy(&buf);
1012 cxBufferDestroy(&target);
1013 }
1015 CX_TEST(test_buffer_get) {
1016 CxBuffer buf;
1017 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1018 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1019 buf.capacity = 12;
1020 buf.size = 9;
1021 buf.pos = 2;
1022 CX_TEST_DO {
1023 CX_TEST_ASSERT(cxBufferGet(&buf) == 'm');
1024 CX_TEST_ASSERT(cxBufferGet(&buf) == 'e');
1025 CX_TEST_ASSERT(cxBufferGet(&buf) == ' ');
1026 CX_TEST_ASSERT(cxBufferGet(&buf) == 'd');
1027 CX_TEST_ASSERT(buf.pos == 6);
1028 }
1029 cxBufferDestroy(&buf);
1030 }
1032 CX_TEST(test_buffer_get_eof) {
1033 CxBuffer buf;
1034 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1035 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1036 buf.capacity = 12;
1037 buf.pos = buf.size = 9;
1038 CX_TEST_DO {
1039 CX_TEST_ASSERT(cxBufferGet(&buf) == EOF);
1040 }
1041 cxBufferDestroy(&buf);
1042 }
1044 CX_TEST(test_buffer_read) {
1045 CxBuffer buf;
1046 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1047 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1048 buf.capacity = 12;
1049 buf.size = 9;
1050 buf.pos = 2;
1051 CX_TEST_DO {
1052 char target[4];
1053 size_t read = cxBufferRead(&target, 1, 4, &buf);
1054 CX_TEST_ASSERT(read == 4);
1055 CX_TEST_ASSERT(0 == memcmp(&target, "me d", 4));
1056 CX_TEST_ASSERT(buf.pos == 6);
1057 }
1058 cxBufferDestroy(&buf);
1059 }
1061 CX_TEST(test_buffer_read_oob) {
1062 CxBuffer buf;
1063 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1064 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1065 buf.capacity = 12;
1066 buf.size = 9;
1067 buf.pos = 6;
1068 CX_TEST_DO {
1069 char target[4];
1070 size_t read = cxBufferRead(&target, 1, 4, &buf);
1071 CX_TEST_ASSERT(read == 3);
1072 CX_TEST_ASSERT(0 == memcmp(&target, "ata", 3));
1073 CX_TEST_ASSERT(buf.pos == 9);
1074 }
1075 cxBufferDestroy(&buf);
1076 }
1078 CX_TEST(test_buffer_read_oob_multibyte) {
1079 CxBuffer buf;
1080 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1081 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1082 buf.capacity = 12;
1083 buf.size = 9;
1084 buf.pos = 6;
1085 CX_TEST_DO {
1086 char target[4];
1087 target[2] = '\0';
1088 size_t read = cxBufferRead(&target, 2, 2, &buf);
1089 CX_TEST_ASSERT(read == 1);
1090 CX_TEST_ASSERT(0 == memcmp(&target, "at\0", 3));
1091 CX_TEST_ASSERT(buf.pos == 8);
1092 }
1093 cxBufferDestroy(&buf);
1094 }
1096 CX_TEST(test_buffer_read_eof) {
1097 CxBuffer buf;
1098 cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
1099 memcpy(buf.space, "some data\0\0\0\0\0\0\0", 16);
1100 buf.capacity = 12;
1101 buf.size = buf.pos = 9;
1102 CX_TEST_DO {
1103 char target[4];
1104 size_t read = cxBufferRead(&target, 1, 1, &buf);
1105 CX_TEST_ASSERT(read == 0);
1106 CX_TEST_ASSERT(buf.pos == 9);
1107 }
1108 cxBufferDestroy(&buf);
1109 }
1111 CxTestSuite *cx_test_suite_buffer(void) {
1112 CxTestSuite *suite = cx_test_suite_new("buffer");
1114 cx_test_register(suite, test_buffer_init_wrap_space);
1115 cx_test_register(suite, test_buffer_init_wrap_space_auto_extend);
1116 cx_test_register(suite, test_buffer_init_wrap_space_auto_free);
1117 cx_test_register(suite, test_buffer_init_fresh_space);
1118 cx_test_register(suite, test_buffer_init_on_heap);
1119 cx_test_register(suite, test_buffer_minimum_capacity_sufficient);
1120 cx_test_register(suite, test_buffer_minimum_capacity_extend);
1121 cx_test_register(suite, test_buffer_clear);
1122 cx_test_register(suite, test_buffer_reset);
1123 cx_test_register(suite, test_buffer_seek_set_zero);
1124 cx_test_register(suite, test_buffer_seek_set_valid);
1125 cx_test_register(suite, test_buffer_seek_set_invalid);
1126 cx_test_register(suite, test_buffer_seek_cur_zero);
1127 cx_test_register(suite, test_buffer_seek_cur_valid_positive);
1128 cx_test_register(suite, test_buffer_seek_cur_valid_negative);
1129 cx_test_register(suite, test_buffer_seek_cur_invalid_positive);
1130 cx_test_register(suite, test_buffer_seek_cur_invalid_negative);
1131 cx_test_register(suite, test_buffer_seek_end_zero);
1132 cx_test_register(suite, test_buffer_seek_end_valid);
1133 cx_test_register(suite, test_buffer_seek_end_invalid);
1134 cx_test_register(suite, test_buffer_seek_whence_invalid);
1135 cx_test_register(suite, test_buffer_eof_reached);
1136 cx_test_register(suite, test_buffer_eof_not_reached);
1137 cx_test_register(suite, test_buffer_shift_left_zero);
1138 cx_test_register(suite, test_buffer_shift_left_zero_offset_interface);
1139 cx_test_register(suite, test_buffer_shift_left_standard);
1140 cx_test_register(suite, test_buffer_shift_left_overshift);
1141 cx_test_register(suite, test_buffer_shift_left_overshift_pos_only);
1142 cx_test_register(suite, test_buffer_shift_left_offset_interface);
1143 cx_test_register(suite, test_buffer_shift_right_zero);
1144 cx_test_register(suite, test_buffer_shift_right_zero_offset_interface);
1145 cx_test_register(suite, test_buffer_shift_right_standard);
1146 cx_test_register(suite, test_buffer_shift_right_overshift_discard);
1147 cx_test_register(suite, test_buffer_shift_right_overshift_extend);
1148 cx_test_register(suite, test_buffer_shift_right_offset_interface);
1149 cx_test_register(suite, test_buffer_write_size_one_fit);
1150 cx_test_register(suite, test_buffer_write_size_one_discard);
1151 cx_test_register(suite, test_buffer_write_size_one_extend);
1152 cx_test_register(suite, test_buffer_write_multibyte_fit);
1153 cx_test_register(suite, test_buffer_write_multibyte_discard);
1154 cx_test_register(suite, test_buffer_write_multibyte_extend);
1155 cx_test_register(suite, test_buffer_put_fit);
1156 cx_test_register(suite, test_buffer_put_discard);
1157 cx_test_register(suite, test_buffer_put_extend);
1158 cx_test_register(suite, test_buffer_put_string_fit);
1159 cx_test_register(suite, test_buffer_put_string_discard);
1160 cx_test_register(suite, test_buffer_put_string_extend);
1161 cx_test_register(suite, test_buffer_write_size_overflow);
1162 cx_test_register(suite, test_buffer_write_capacity_overflow);
1163 cx_test_register(suite, test_buffer_write_only_overwrite);
1164 cx_test_register(suite, test_buffer_write_flush_at_capacity);
1165 cx_test_register(suite, test_buffer_write_flush_at_threshold);
1166 cx_test_register(suite, test_buffer_write_flush_rate_limited);
1167 cx_test_register(suite, test_buffer_get);
1168 cx_test_register(suite, test_buffer_get_eof);
1169 cx_test_register(suite, test_buffer_read);
1170 cx_test_register(suite, test_buffer_read_oob);
1171 cx_test_register(suite, test_buffer_read_oob_multibyte);
1172 cx_test_register(suite, test_buffer_read_eof);
1174 return suite;
1175 }