--- a/tests/test_buffer.c Sun Dec 15 15:23:29 2024 +0100 +++ b/tests/test_buffer.c Wed Dec 18 15:35:42 2024 +0100 @@ -215,6 +215,22 @@ cxBufferDestroy(&buf); } +CX_TEST(test_buffer_clear_copy_on_write) { + char space[16]; + strcpy(space, "clear test"); + CxBuffer buf; + cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_COPY_ON_WRITE); + CX_TEST_DO { + buf.size = 5; + buf.pos = 3; + cxBufferClear(&buf); + CX_TEST_ASSERT(0 == memcmp(space, "clear test", 10)); + CX_TEST_ASSERT(buf.size == 0); + CX_TEST_ASSERT(buf.pos == 0); + } + cxBufferDestroy(&buf); +} + CX_TEST(test_buffer_reset) { char space[16]; strcpy(space, "reset test"); @@ -506,6 +522,24 @@ } } +CX_TEST(test_buffer_shift_left_copy_on_write) { + TEST_BUFFER_SHIFT_SETUP(buf); + buf.flags |= CX_BUFFER_COPY_ON_WRITE; + char *original = buf.space; + CX_TEST_DO { + int ret = cxBufferShiftLeft(&buf, 2); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_FREE_CONTENTS)); + CX_TEST_ASSERT(ret == 0); + CX_TEST_ASSERT(buf.pos == 2); + CX_TEST_ASSERT(buf.size == 2); + CX_TEST_ASSERT(memcmp(original, "test____XXXXXXXX", 16) == 0); + CX_TEST_ASSERT(memcmp(buf.space, "st", 2) == 0); + cxFree(buf.allocator, original); + TEST_BUFFER_SHIFT_TEARDOWN(buf); + } +} + CX_TEST(test_buffer_shift_right_zero) { TEST_BUFFER_SHIFT_SETUP(buf); CX_TEST_DO { @@ -584,6 +618,24 @@ } } +CX_TEST(test_buffer_shift_right_copy_on_write) { + TEST_BUFFER_SHIFT_SETUP(buf); + buf.flags |= CX_BUFFER_COPY_ON_WRITE; + char *original = buf.space; + CX_TEST_DO { + int ret = cxBufferShiftRight(&buf, 3); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_FREE_CONTENTS)); + CX_TEST_ASSERT(ret == 0); + CX_TEST_ASSERT(buf.pos == 7); + CX_TEST_ASSERT(buf.size == 7); + CX_TEST_ASSERT(memcmp(original, "test____XXXXXXXX", 16) == 0); + CX_TEST_ASSERT(memcmp(buf.space, "testest", 7) == 0); + cxFree(buf.allocator, original); + TEST_BUFFER_SHIFT_TEARDOWN(buf); + } +} + static size_t mock_write_limited_rate( const void *ptr, size_t size, @@ -657,6 +709,28 @@ cxBufferDestroy(&buf); } +CX_TEST(test_buffer_write_copy_on_write) { + CxBuffer buf; + char original[16] = "preparedXXXXXXX\0"; + cxBufferInit(&buf, original, 16, cxDefaultAllocator, CX_BUFFER_COPY_ON_WRITE); + buf.capacity = 8; + buf.size = 8; + buf.pos = 0; + const char *data = "testing"; + CX_TEST_DO { + size_t written = cxBufferWrite(data, 1, 7, &buf); + CX_TEST_ASSERT(written == 7); + CX_TEST_ASSERT(buf.size == 8); + CX_TEST_ASSERT(buf.pos == 7); + CX_TEST_ASSERT(buf.capacity == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "testingd", 8)); + CX_TEST_ASSERT(0 == memcmp(original, "preparedXXXXXXX\0", 16)); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_FREE_CONTENTS)); + } + cxBufferDestroy(&buf); +} + CX_TEST(test_buffer_write_multibyte_fit) { CxBuffer buf; cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); @@ -770,6 +844,40 @@ cxBufferDestroy(&buf); } +CX_TEST(test_buffer_put_copy_on_write) { + CxBuffer buf; + char original[16] = "preparedXXXXXXX\0"; + cxBufferInit(&buf, original, 16, cxDefaultAllocator, CX_BUFFER_COPY_ON_WRITE); + buf.capacity = 8; + buf.size = 8; + buf.pos = 8; + CX_TEST_DO { + int c = cxBufferPut(&buf, 0x200 | 'a'); + CX_TEST_ASSERT(c == EOF); + CX_TEST_ASSERT(buf.size == 8); + CX_TEST_ASSERT(buf.pos == 8); + CX_TEST_ASSERT(buf.capacity == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "prepared", 8)); + // discarded, no write happend! + CX_TEST_ASSERT(original == buf.space); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_FREE_CONTENTS)); + // now actually write somewhere + buf.pos = 2; + c = cxBufferPut(&buf, 0x200 | 'a'); + CX_TEST_ASSERT(c == 'a'); + CX_TEST_ASSERT(buf.size == 8); + CX_TEST_ASSERT(buf.pos == 3); + CX_TEST_ASSERT(buf.capacity == 8); + CX_TEST_ASSERT(0 == memcmp(buf.space, "prapared", 8)); + CX_TEST_ASSERT(original != buf.space); + CX_TEST_ASSERT(0 == memcmp(original, "preparedXXXXXXX\0", 16)); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_FREE_CONTENTS)); + } + cxBufferDestroy(&buf); +} + CX_TEST(test_buffer_put_string_fit) { CxBuffer buf; cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); @@ -825,6 +933,30 @@ cxBufferDestroy(&buf); } +CX_TEST(test_buffer_put_string_extend_copy_on_write) { + CxBuffer buf; + char original[16] = "preparedXXXXXXX\0"; + cxBufferInit(&buf, original, 16, cxDefaultAllocator, CX_BUFFER_COPY_ON_WRITE); + buf.capacity = 8; + buf.size = 8; + buf.pos = 4; + buf.flags |= CX_BUFFER_AUTO_EXTEND; + const char *data = "testing"; + CX_TEST_DO { + size_t written = cxBufferPutString(&buf, data); + CX_TEST_ASSERT(written == 7); + CX_TEST_ASSERT(buf.size == 11); + CX_TEST_ASSERT(buf.pos == 11); + CX_TEST_ASSERT(buf.capacity >= 11); + CX_TEST_ASSERT(0 == memcmp(buf.space, "preptesting", 11)); + CX_TEST_ASSERT(original != buf.space); + CX_TEST_ASSERT(0 == memcmp(original, "preparedXXXXXXX\0", 16)); + CX_TEST_ASSERT(0 == (buf.flags & CX_BUFFER_COPY_ON_WRITE)); + CX_TEST_ASSERT(0 != (buf.flags & CX_BUFFER_FREE_CONTENTS)); + } + cxBufferDestroy(&buf); +} + CX_TEST(test_buffer_terminate) { CxBuffer buf; cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); @@ -1113,6 +1245,7 @@ cx_test_register(suite, test_buffer_minimum_capacity_sufficient); cx_test_register(suite, test_buffer_minimum_capacity_extend); cx_test_register(suite, test_buffer_clear); + cx_test_register(suite, test_buffer_clear_copy_on_write); cx_test_register(suite, test_buffer_reset); cx_test_register(suite, test_buffer_seek_set_zero); cx_test_register(suite, test_buffer_seek_set_valid); @@ -1134,24 +1267,29 @@ cx_test_register(suite, test_buffer_shift_left_overshift); cx_test_register(suite, test_buffer_shift_left_overshift_pos_only); cx_test_register(suite, test_buffer_shift_left_offset_interface); + cx_test_register(suite, test_buffer_shift_left_copy_on_write); cx_test_register(suite, test_buffer_shift_right_zero); cx_test_register(suite, test_buffer_shift_right_zero_offset_interface); cx_test_register(suite, test_buffer_shift_right_standard); cx_test_register(suite, test_buffer_shift_right_overshift_discard); cx_test_register(suite, test_buffer_shift_right_overshift_extend); cx_test_register(suite, test_buffer_shift_right_offset_interface); + cx_test_register(suite, test_buffer_shift_right_copy_on_write); cx_test_register(suite, test_buffer_write_size_one_fit); cx_test_register(suite, test_buffer_write_size_one_discard); cx_test_register(suite, test_buffer_write_size_one_extend); cx_test_register(suite, test_buffer_write_multibyte_fit); cx_test_register(suite, test_buffer_write_multibyte_discard); cx_test_register(suite, test_buffer_write_multibyte_extend); + cx_test_register(suite, test_buffer_write_copy_on_write); cx_test_register(suite, test_buffer_put_fit); cx_test_register(suite, test_buffer_put_discard); cx_test_register(suite, test_buffer_put_extend); + cx_test_register(suite, test_buffer_put_copy_on_write); cx_test_register(suite, test_buffer_put_string_fit); cx_test_register(suite, test_buffer_put_string_discard); cx_test_register(suite, test_buffer_put_string_extend); + cx_test_register(suite, test_buffer_put_string_extend_copy_on_write); cx_test_register(suite, test_buffer_terminate); cx_test_register(suite, test_buffer_write_size_overflow); cx_test_register(suite, test_buffer_write_capacity_overflow);