--- a/tests/test_buffer.c Sat Jan 18 14:10:51 2025 +0100 +++ b/tests/test_buffer.c Sun Jan 19 17:17:01 2025 +0100 @@ -1275,7 +1275,6 @@ CxBuffer buf, target; cxBufferInit(&target, NULL, 8, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); cxBufferInit(&buf, NULL, 8, cxDefaultAllocator, CX_BUFFER_DEFAULT); - memset(buf.space, 0, 8); cxBufferPutString(&buf, "prep"); CX_TEST_DO { CxBufferFlushConfig flush; @@ -1295,19 +1294,75 @@ CX_TEST_ASSERT(0 == memcmp(buf.space, "pfoobar", 7)); CX_TEST_ASSERT(0 == memcmp(target.space, "pre", 3)); // second case: string does not fit, relaying not possible due to misalignment + // string will be truncated (two items fit into buffer, the third does not) written = cxBufferWrite("bazfoobar", 3, 3, &buf); - CX_TEST_ASSERT(written == 0); - CX_TEST_ASSERT(buf.pos == 1); - CX_TEST_ASSERT(buf.size == 1); + CX_TEST_ASSERT(written == 2); + CX_TEST_ASSERT(buf.pos == 7); + CX_TEST_ASSERT(buf.size == 7); CX_TEST_ASSERT(target.pos == 9); CX_TEST_ASSERT(target.size == 9); - CX_TEST_ASSERT(0 == memcmp(buf.space, "r", 1)); + CX_TEST_ASSERT(0 == memcmp(buf.space, "rbazfoo", 7)); CX_TEST_ASSERT(0 == memcmp(target.space, "prepfooba", 9)); } cxBufferDestroy(&buf); cxBufferDestroy(&target); } +CX_TEST(test_buffer_write_flush_target_full) { + CxBuffer buf, target; + // target does NOT auto-extend and can get completely full + cxBufferInit(&target, NULL, 8, cxDefaultAllocator, CX_BUFFER_DEFAULT); + cxBufferInit(&buf, NULL, 8, cxDefaultAllocator, CX_BUFFER_DEFAULT); + cxBufferPutString(&buf, "prep"); + CX_TEST_DO { + CxBufferFlushConfig flush; + flush.threshold = 0; + flush.blksize = 32; + flush.blkmax = 1; + flush.target = ⌖ + flush.wfunc = cxBufferWriteFunc; + CX_TEST_ASSERT(0 == cxBufferEnableFlushing(&buf, flush)); + // step one - flush 4 existing bytes, write 6 new bytes + size_t written = cxBufferWrite("foobar", 1, 6, &buf); + CX_TEST_ASSERT(written == 6); + CX_TEST_ASSERT(buf.pos == 6); + CX_TEST_ASSERT(buf.size == 6); + CX_TEST_ASSERT(target.pos == 4); + CX_TEST_ASSERT(target.size == 4); + CX_TEST_ASSERT(0 == memcmp(buf.space, "foobar", 6)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prep", 4)); + // step two - can only flush 4 more bytes, but rest fits into buffer + written = cxBufferWrite("xyz", 1, 3, &buf); + CX_TEST_ASSERT(written == 3); + CX_TEST_ASSERT(buf.pos == 5); + CX_TEST_ASSERT(buf.size == 5); + CX_TEST_ASSERT(target.pos == 8); + CX_TEST_ASSERT(target.size == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "arxyz", 5)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoob", 8)); + // step three - cannot flush more, but can write 3 more bytes + written = cxBufferWrite("123456", 1, 6, &buf); + CX_TEST_ASSERT(written == 3); + CX_TEST_ASSERT(buf.pos == 8); + CX_TEST_ASSERT(buf.size == 8); + CX_TEST_ASSERT(target.pos == 8); + CX_TEST_ASSERT(target.size == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "arxyz123", 8)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoob", 8)); + // final test, cannot write anything more + written = cxBufferWrite("baz", 1, 3, &buf); + CX_TEST_ASSERT(written == 0); + CX_TEST_ASSERT(buf.pos == 8); + CX_TEST_ASSERT(buf.size == 8); + CX_TEST_ASSERT(target.pos == 8); + CX_TEST_ASSERT(target.size == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "arxyz123", 8)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prepfoob", 8)); + } + cxBufferDestroy(&buf); + cxBufferDestroy(&target); +} + CX_TEST(test_buffer_flush) { CxBuffer buf, target; cxBufferInit(&target, NULL, 8, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); @@ -1508,6 +1563,7 @@ cx_test_register(suite, test_buffer_write_flush_rate_limited_and_buffer_too_small); cx_test_register(suite, test_buffer_write_flush_multibyte); cx_test_register(suite, test_buffer_write_flush_misaligned); + cx_test_register(suite, test_buffer_write_flush_target_full); cx_test_register(suite, test_buffer_flush); cx_test_register(suite, test_buffer_get); cx_test_register(suite, test_buffer_get_eof);