tests/test_buffer.c

Thu, 04 Jan 2024 21:05:32 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 04 Jan 2024 21:05:32 +0100
changeset 793
db1c8dfe403a
parent 792
3ca984931e1d
permissions
-rw-r--r--

migrate remaining buffer tests - relates to #342

     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 = &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 = &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 = &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));
  1011     cxBufferDestroy(&buf);
  1012     cxBufferDestroy(&target);
  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);
  1029     cxBufferDestroy(&buf);
  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);
  1041     cxBufferDestroy(&buf);
  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);
  1058     cxBufferDestroy(&buf);
  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);
  1075     cxBufferDestroy(&buf);
  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);
  1093     cxBufferDestroy(&buf);
  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);
  1108     cxBufferDestroy(&buf);
  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;

mercurial