diff -r 3672b89e606c -r cc60b7d07912 tests/test_buffer.c --- a/tests/test_buffer.c Thu Jan 16 18:56:17 2025 +0100 +++ b/tests/test_buffer.c Thu Jan 16 18:56:44 2025 +0100 @@ -1180,6 +1180,93 @@ cxBufferDestroy(&target); } +CX_TEST(test_buffer_write_flush_multibyte) { + // this test case tests that flushing works correctly even when the + // contents in the buffer are currently not aligned with the item size + 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, "pre"); + CX_TEST_DO { + CxBufferFlushConfig flush; + flush.threshold = 0; + flush.blksize = 4; // test blksize that is not aligned + flush.blkmax = 2; // test with two blocks + flush.target = ⌖ + flush.wfunc = cxBufferWriteFunc; + CX_TEST_ASSERT(0 == cxBufferEnableFlushing(&buf, flush)); + // first case: string fits after flush + size_t written = cxBufferWrite("foobar", 3, 2, &buf); + CX_TEST_ASSERT(written == 2); + CX_TEST_ASSERT(buf.pos == 6); + CX_TEST_ASSERT(buf.size == 6); + CX_TEST_ASSERT(target.pos == 3); + CX_TEST_ASSERT(target.size == 3); + CX_TEST_ASSERT(0 == memcmp(buf.space, "foobar", 6)); + CX_TEST_ASSERT(0 == memcmp(target.space, "pre", 3)); + // second case: string does not fit, data is relayed, but only two blocks! + written = cxBufferWrite("bazfooBAR", 3, 3, &buf); + CX_TEST_ASSERT(written == 3); + CX_TEST_ASSERT(buf.pos == 3); + CX_TEST_ASSERT(buf.size == 3); + CX_TEST_ASSERT(target.pos == 15); + CX_TEST_ASSERT(target.size == 15); + CX_TEST_ASSERT(0 == memcmp(buf.space, "BAR", 3)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prefoobarbazfoo", 15)); + // third case: everything can be relayed, block size is large enough + buf.flush->blkmax = 3; + written = cxBufferWrite("abcdef012", 3, 3, &buf); + CX_TEST_ASSERT(written == 3); + CX_TEST_ASSERT(buf.pos == 0); + CX_TEST_ASSERT(buf.size == 0); + CX_TEST_ASSERT(target.pos == 27); + CX_TEST_ASSERT(target.size == 27); + CX_TEST_ASSERT(0 == memcmp(target.space, "prefoobarbazfooBARabcdef012", 27)); + } + cxBufferDestroy(&buf); + cxBufferDestroy(&target); +} + +CX_TEST(test_buffer_write_flush_misaligned) { + // this test case tests that flushing works correctly even when the + // contents in the buffer are currently not aligned with the item size + 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; + flush.threshold = 0; + flush.blksize = 32; + flush.blkmax = 1; + flush.target = ⌖ + flush.wfunc = cxBufferWriteFunc; + CX_TEST_ASSERT(0 == cxBufferEnableFlushing(&buf, flush)); + // first case: string fits after flush + size_t written = cxBufferWrite("foobar", 3, 2, &buf); + CX_TEST_ASSERT(written == 2); + CX_TEST_ASSERT(buf.pos == 7); + CX_TEST_ASSERT(buf.size == 7); + CX_TEST_ASSERT(target.pos == 3); + CX_TEST_ASSERT(target.size == 3); + 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 + 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(target.pos == 9); + CX_TEST_ASSERT(target.size == 9); + CX_TEST_ASSERT(0 == memcmp(buf.space, "r", 1)); + CX_TEST_ASSERT(0 == memcmp(target.space, "prepfooba", 9)); + } + cxBufferDestroy(&buf); + cxBufferDestroy(&target); +} + CX_TEST(test_buffer_flush) { CxBuffer buf, target; cxBufferInit(&target, NULL, 8, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); @@ -1377,6 +1464,8 @@ cx_test_register(suite, test_buffer_write_flush_at_capacity); cx_test_register(suite, test_buffer_write_flush_at_threshold); 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_flush); cx_test_register(suite, test_buffer_get); cx_test_register(suite, test_buffer_get_eof);