#include "cx/test.h"
#include "util_allocator.h"
#include <errno.h>
#include "cx/buffer.h"
CX_TEST(test_buffer_init_wrap_space) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
void *space = cxMalloc(alloc,
16);
cxBufferInit(&buf, space,
16, alloc,
CX_BUFFER_DEFAULT);
CX_TEST_ASSERT(buf.flush ==
NULL);
CX_TEST_ASSERT(buf.space == space);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_AUTO_EXTEND) ==
0);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_FREE_CONTENTS) ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.allocator == alloc);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxFree(alloc, space);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_init_wrap_space_auto_extend) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
void *space = cxMalloc(alloc,
16);
cxBufferInit(&buf, space,
16, alloc,
CX_BUFFER_AUTO_EXTEND);
CX_TEST_ASSERT(buf.flush ==
NULL);
CX_TEST_ASSERT(buf.space == space);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_AUTO_EXTEND) ==
CX_BUFFER_AUTO_EXTEND);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_FREE_CONTENTS) ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.allocator == alloc);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxFree(alloc, space);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_init_wrap_space_auto_free) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
void *space = cxMalloc(alloc,
16);
cxBufferInit(&buf, space,
16, alloc,
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf.flush ==
NULL);
CX_TEST_ASSERT(buf.space == space);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_AUTO_EXTEND) ==
0);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_FREE_CONTENTS) ==
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.allocator == alloc);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_init_fresh_space) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
8, alloc,
CX_BUFFER_DEFAULT);
CX_TEST_ASSERT(buf.flush ==
NULL);
CX_TEST_ASSERT(buf.space !=
NULL);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_AUTO_EXTEND) ==
0);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_FREE_CONTENTS) ==
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(buf.allocator == alloc);
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_init_on_heap) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer *buf;
void *space = cxMalloc(alloc,
16);
buf = cxBufferCreate(space,
16, alloc,
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf !=
NULL);
CX_TEST_ASSERT(buf->flush ==
NULL);
CX_TEST_ASSERT(buf->space == space);
CX_TEST_ASSERT((buf->flags &
CX_BUFFER_AUTO_EXTEND) ==
0);
CX_TEST_ASSERT((buf->flags &
CX_BUFFER_FREE_CONTENTS) ==
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf->pos ==
0);
CX_TEST_ASSERT(buf->size ==
0);
CX_TEST_ASSERT(buf->capacity ==
16);
CX_TEST_ASSERT(buf->allocator == alloc);
cxBufferFree(buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_create_defaulted_allocator) {
CX_TEST_DO {
CxBuffer *buf;
buf = cxBufferCreate(
NULL,
16,
NULL,
0);
CX_TEST_ASSERT(buf !=
NULL);
CX_TEST_ASSERT(buf->flush ==
NULL);
CX_TEST_ASSERT(buf->space !=
NULL);
CX_TEST_ASSERT((buf->flags &
CX_BUFFER_AUTO_EXTEND) ==
0);
CX_TEST_ASSERT((buf->flags &
CX_BUFFER_FREE_CONTENTS) ==
CX_BUFFER_FREE_CONTENTS);
CX_TEST_ASSERT(buf->pos ==
0);
CX_TEST_ASSERT(buf->size ==
0);
CX_TEST_ASSERT(buf->capacity ==
16);
CX_TEST_ASSERT(buf->allocator == cxDefaultAllocator);
cxBufferFree(buf);
}
}
CX_TEST(test_buffer_minimum_capacity_sufficient) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *space = cxMalloc(alloc,
8);
CxBuffer buf;
cxBufferInit(&buf, space,
8, alloc,
CX_BUFFER_FREE_CONTENTS);
memcpy(space,
"Testing",
8);
buf.size =
8;
cxBufferMinimumCapacity(&buf,
6);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_minimum_capacity_extend) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
void *space = cxMalloc(alloc,
8);
CxBuffer buf;
cxBufferInit(&buf, space,
8, alloc,
CX_BUFFER_FREE_CONTENTS);
memcpy(space,
"Testing",
8);
buf.size =
8;
cxBufferMinimumCapacity(&buf,
16);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
cxBufferMinimumCapacity(&buf,
200);
CX_TEST_ASSERT(buf.capacity ==
256);
cxBufferMinimumCapacity(&buf, cx_system_page_size() +
200);
CX_TEST_ASSERT(buf.capacity == cx_system_page_size()*
2);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_shrink) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, alloc,
CX_BUFFER_FREE_CONTENTS);
cxBufferPutString(&buf,
"Testing");
cxBufferTerminate(&buf);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.size ==
7);
cxBufferShrink(&buf,
4);
CX_TEST_ASSERT(buf.capacity ==
11);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_shrink_copy_on_write) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
const char* space =
"Testing";
cxBufferInit(&buf, (
void*)space,
16, alloc,
CX_BUFFER_COPY_ON_WRITE);
buf.size =
8;
CX_TEST_ASSERT(buf.capacity ==
16);
cxBufferShrink(&buf,
4);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
CX_TEST_ASSERT(talloc.alloc_total ==
0);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_shrink_copy_on_extend) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
char space[
16] =
"Testing";
cxBufferInit(&buf, space,
16, alloc,
CX_BUFFER_COPY_ON_EXTEND);
buf.size =
8;
CX_TEST_ASSERT(buf.capacity ==
16);
cxBufferShrink(&buf,
4);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
CX_TEST_ASSERT(talloc.alloc_total ==
0);
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_reserve) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
CxAllocator *alloc = &talloc.base;
CX_TEST_DO {
CxBuffer buf;
char space[
16] =
"Testing";
cxBufferInit(&buf, space,
16, alloc,
CX_BUFFER_COPY_ON_EXTEND);
buf.size =
8;
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(talloc.alloc_total ==
0);
cxBufferReserve(&buf,
32);
CX_TEST_ASSERT(buf.capacity ==
32);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
CX_TEST_ASSERT(talloc.alloc_total >
0);
CX_TEST_ASSERT((buf.flags &
CX_BUFFER_COPY_ON_EXTEND) ==
0);
buf.size =
24;
cxBufferReserve(&buf,
16);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(buf.size ==
16);
CX_TEST_ASSERT(memcmp(buf.space,
"Testing",
8) ==
0);
cxBufferReserve(&buf,
0);
CX_TEST_ASSERT(buf.capacity ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.space ==
NULL);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cxBufferDestroy(&buf);
}
cx_testing_allocator_destroy(&talloc);
}
CX_TEST(test_buffer_clear) {
char space[
16];
strcpy(space,
"clear test");
CxBuffer buf;
cxBufferInit(&buf, space,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
CX_TEST_DO {
CX_TEST_ASSERT(buf.size ==
0);
cxBufferClear(&buf);
CX_TEST_ASSERT(
0 == memcmp(space,
"clear test",
10));
buf.size =
5;
buf.pos =
3;
cxBufferClear(&buf);
CX_TEST_ASSERT(
0 == memcmp(space,
"\0\0\0\0\0 test",
10));
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
}
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");
CxBuffer buf;
cxBufferInit(&buf, space,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
CX_TEST_DO {
buf.size =
5;
buf.pos =
3;
cxBufferReset(&buf);
CX_TEST_ASSERT(
0 == memcmp(space,
"reset test",
10));
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_set_zero) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
0,
SEEK_SET);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_set_valid) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
5,
SEEK_SET);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
5);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_set_invalid) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
7,
SEEK_SET);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_cur_zero) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
0,
SEEK_CUR);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_cur_valid_positive) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
2,
SEEK_CUR);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
5);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_cur_valid_negative) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
-3,
SEEK_CUR);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_cur_invalid_positive) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
4,
SEEK_CUR);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_cur_invalid_negative) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
-4,
SEEK_CUR);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_end_zero) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
0,
SEEK_END);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
6);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_end_valid) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
-6,
SEEK_END);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_end_invalid) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
1,
SEEK_END);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_seek_whence_invalid) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
buf.pos =
3;
CX_TEST_DO {
int result = cxBufferSeek(&buf,
2,
9000);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(buf.size ==
6);
CX_TEST_ASSERT(buf.pos ==
3);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_eof_reached) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size = buf.pos =
3;
CX_TEST_DO {
CX_TEST_ASSERT(cxBufferEof(&buf));
buf.pos = buf.size -
1;
CX_TEST_ASSERT(!cxBufferEof(&buf));
cxBufferPut(&buf,
'a');
CX_TEST_ASSERT(cxBufferEof(&buf));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_eof_not_reached) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
buf.size =
6;
CX_TEST_DO {
buf.pos = buf.size -
1;
CX_TEST_ASSERT(!cxBufferEof(&buf));
buf.pos =
0;
cxBufferWrite(
"test",
1,
5, &buf);
CX_TEST_ASSERT(!cxBufferEof(&buf));
}
cxBufferDestroy(&buf);
}
#define TEST_BUFFER_SHIFT_SETUP(buf) \
CxTestingAllocator talloc; \
cx_testing_allocator_init(&talloc); \
CxAllocator *alloc = &talloc.base; \
CxBuffer buf; \
cxBufferInit(&buf,
NULL,
16, alloc,
CX_BUFFER_DEFAULT); \
memcpy(buf.space,
"test____XXXXXXXX",
16); \
buf.capacity =
8; \
buf.pos =
4; \
buf.size =
4
#define TEST_BUFFER_SHIFT_TEARDOWN(buf) \
cxBufferDestroy(&buf); \
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); \
cx_testing_allocator_destroy(&talloc)
CX_TEST(test_buffer_shift_left_zero) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShiftLeft(&buf,
0);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_left_zero_offset_interface) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShift(&buf,
-0);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_left_standard) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShiftLeft(&buf,
2);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
2);
CX_TEST_ASSERT(buf.size ==
2);
CX_TEST_ASSERT(memcmp(buf.space,
"stst____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_left_overshift) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShiftLeft(&buf,
6);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_left_overshift_pos_only) {
TEST_BUFFER_SHIFT_SETUP(buf);
buf.pos =
2;
CX_TEST_DO {
int ret = cxBufferShiftLeft(&buf,
3);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
1);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_left_offset_interface) {
TEST_BUFFER_SHIFT_SETUP(buf);
buf.pos =
3;
CX_TEST_DO {
int ret = cxBufferShift(&buf,
-2);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
1);
CX_TEST_ASSERT(buf.size ==
2);
CX_TEST_ASSERT(memcmp(buf.space,
"stst____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
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 {
int ret = cxBufferShiftRight(&buf,
0);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_right_zero_offset_interface) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShift(&buf,
+0);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(memcmp(buf.space,
"test____XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_right_standard) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShiftRight(&buf,
3);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(memcmp(buf.space,
"testest_XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_right_overshift_discard) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
int ret = cxBufferShiftRight(&buf,
6);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
8);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(memcmp(buf.space,
"test__teXXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_right_overshift_extend) {
TEST_BUFFER_SHIFT_SETUP(buf);
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
CX_TEST_DO {
int ret = cxBufferShiftRight(&buf,
6);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
10);
CX_TEST_ASSERT(buf.size ==
10);
CX_TEST_ASSERT(buf.capacity >=
10);
CX_TEST_ASSERT(memcmp(buf.space,
"test__test",
10) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
CX_TEST(test_buffer_shift_right_offset_interface) {
TEST_BUFFER_SHIFT_SETUP(buf);
buf.pos =
3;
CX_TEST_DO {
int ret = cxBufferShift(&buf,
2);
CX_TEST_ASSERT(ret ==
0);
CX_TEST_ASSERT(buf.pos ==
5);
CX_TEST_ASSERT(buf.size ==
6);
CX_TEST_ASSERT(memcmp(buf.space,
"tetest__XXXXXXXX",
16) ==
0);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
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);
}
}
CX_TEST(test_buffer_shift_right_overflow) {
TEST_BUFFER_SHIFT_SETUP(buf);
CX_TEST_DO {
errno =
0;
int ret = cxBufferShiftRight(&buf,
SIZE_MAX -
2);
CX_TEST_ASSERT(ret !=
0);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
TEST_BUFFER_SHIFT_TEARDOWN(buf);
}
}
static size_t mock_write_limited_rate(
const void *ptr,
size_t size,
cx_attr_unused
size_t nitems,
CxBuffer *buffer
) {
return cxBufferWrite(ptr, size, nitems >
2 ?
2 : nitems, buffer);
}
CX_TEST(test_buffer_write_size_one_fit) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"test";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
1,
4, &buf);
CX_TEST_ASSERT(written ==
4);
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,
"preptest",
8));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_size_one_discard) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"testing";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
1,
7, &buf);
CX_TEST_ASSERT(written ==
4);
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,
"preptest\0",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_size_one_extend) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
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 ==
11);
CX_TEST_ASSERT(buf.pos ==
11);
CX_TEST_ASSERT(buf.capacity >=
11);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"preptesting",
11));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_copy_on_write) {
CxBuffer buf;
char original[
16] =
"preparedXXXXXXX";
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);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"test";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
2,
2, &buf);
CX_TEST_ASSERT(written ==
2);
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,
"preptest",
8));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_multibyte_discard) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size =
4;
buf.pos =
3;
const char *data =
"testing";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
2,
4, &buf);
CX_TEST_ASSERT(written ==
2);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"pretest\0",
8));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_multibyte_extend) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size =
4;
buf.pos =
3;
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
const char *data =
"tester";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
2,
3, &buf);
CX_TEST_ASSERT(written ==
3);
CX_TEST_ASSERT(buf.size ==
9);
CX_TEST_ASSERT(buf.pos ==
9);
CX_TEST_ASSERT(buf.capacity >=
9);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"pretester",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_append) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
memcpy(buf.space,
"prepXXXX\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size =
6;
buf.pos =
4;
CX_TEST_DO {
size_t written = cxBufferAppend(
"testing",
1,
7, &buf);
CX_TEST_ASSERT(written ==
7);
CX_TEST_ASSERT(buf.size ==
13);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.capacity >=
13);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prepXXtesting",
13));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_append_flush) {
CxBuffer buf, target;
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
memcpy(buf.space,
"prepXXXX",
8);
buf.capacity =
8;
buf.size =
6;
buf.pos =
4;
CxBufferFlushConfig flush;
flush.threshold =
0;
flush.blksize =
4;
flush.blkmax =
1;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
cxBufferEnableFlushing(&buf, flush);
CX_TEST_DO{
size_t written = cxBufferAppend(
"testing",
1,
7, &buf);
CX_TEST_ASSERT(written ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERTM(buf.pos ==
0,
"position not correctly reset");
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(target.size ==
6);
CX_TEST_ASSERT(target.pos ==
6);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"testing",
7));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepXX",
6));
buf.pos =
6;
written = cxBufferAppend(
"foo",
1,
3, &buf);
CX_TEST_ASSERT(written ==
3);
CX_TEST_ASSERT(buf.size ==
6);
CX_TEST_ASSERTM(buf.pos ==
2,
"position not correctly adjusted");
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(target.size ==
10);
CX_TEST_ASSERT(target.pos ==
10);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"ingfoo",
6));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepXXtest",
10));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_put_fit) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
CX_TEST_DO {
int c = cxBufferPut(&buf,
0x200 |
'a');
CX_TEST_ASSERT(c ==
'a');
CX_TEST_ASSERT(buf.size ==
5);
CX_TEST_ASSERT(buf.pos ==
5);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prepa\0",
6));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_discard) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size =
4;
buf.pos =
8;
CX_TEST_DO {
int c = cxBufferPut(&buf,
0x200 |
'a');
CX_TEST_ASSERT(c ==
EOF);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(buf.pos ==
8);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prep\0\0\0\0\0",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_extend) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size =
4;
buf.pos =
8;
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
CX_TEST_DO {
int c = cxBufferPut(&buf,
0x200 |
'a');
CX_TEST_ASSERT(c ==
'a');
CX_TEST_ASSERT(buf.size ==
9);
CX_TEST_ASSERT(buf.pos ==
9);
CX_TEST_ASSERT(buf.capacity >=
9);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prep\0\0\0\0a",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_copy_on_write) {
CxBuffer buf;
char original[
16] =
"preparedXXXXXXX";
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));
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));
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);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"test";
CX_TEST_DO {
size_t written = cxBufferPutString(&buf, data);
CX_TEST_ASSERT(written ==
4);
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,
"preptest",
8));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_string_discard) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"testing";
CX_TEST_DO {
size_t written = cxBufferPutString(&buf, data);
CX_TEST_ASSERT(written ==
4);
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,
"preptest\0",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_string_extend) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = 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));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_put_string_copy_on_extend) {
CxTestingAllocator talloc;
cx_testing_allocator_init(&talloc);
const CxAllocator *alloc = &talloc.base;
CxBuffer buf;
char original[
16] =
"preparedXXXXXXX";
CX_TEST_DO {
cxBufferInit(&buf, original,
16, alloc,
CX_BUFFER_COPY_ON_EXTEND);
buf.capacity =
8;
buf.size = buf.pos =
4;
size_t written = cxBufferPutString(&buf,
"test");
CX_TEST_ASSERT(written ==
4);
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,
"preptest",
8));
CX_TEST_ASSERT(original == buf.space);
written = cxBufferPutString(&buf,
"ing");
CX_TEST_ASSERT(written ==
3);
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,
"preptestXXXXXXX\0",
16));
CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc));
cxBufferDestroy(&buf);
CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
cx_testing_allocator_destroy(&talloc);
}
}
CX_TEST(test_buffer_put_string_copy_on_write) {
CxBuffer buf;
char original[
16] =
"preparedXXXXXXX";
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);
memcpy(buf.space,
"prepAAAAAA\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"test";
CX_TEST_DO {
size_t written = cxBufferPutString(&buf, data);
CX_TEST_ASSERT(
0 != cxBufferTerminate(&buf));
CX_TEST_ASSERT(written ==
4);
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,
"preptestAA",
10));
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
CX_TEST_ASSERT(
0 == cxBufferTerminate(&buf));
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(buf.pos ==
9);
CX_TEST_ASSERT(buf.capacity >
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"preptest\0",
9));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_size_overflow) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
const char *data =
"testing";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
8,
SIZE_MAX /
4, &buf);
CX_TEST_ASSERT(written ==
0);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prep\0",
5));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_capacity_overflow) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"prep\0\0\0\0\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.size = buf.pos =
4;
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
const char *data =
"testing";
CX_TEST_DO {
size_t written = cxBufferWrite(data,
1,
SIZE_MAX -
2, &buf);
CX_TEST_ASSERT(written ==
0);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(buf.pos ==
4);
CX_TEST_ASSERT(buf.size ==
4);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prep\0",
5));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_only_overwrite) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"preptest\0\0\0\0\0\0\0\0",
16);
buf.capacity =
8;
buf.pos =
3;
buf.size =
8;
buf.flags |=
CX_BUFFER_AUTO_EXTEND;
CX_TEST_DO {
size_t written = cxBufferWrite(
"XXX",
2,
2, &buf);
CX_TEST_ASSERT(written ==
2);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(buf.size ==
8);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"preXXX\0t",
8));
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_write_flush_at_capacity) {
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));
size_t written = cxBufferWrite(
"foo",
1,
3, &buf);
CX_TEST_ASSERT(written ==
3);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(target.pos ==
0);
CX_TEST_ASSERT(target.size ==
0);
written = cxBufferWrite(
"hello",
1,
5, &buf);
CX_TEST_ASSERT(written ==
5);
CX_TEST_ASSERT(buf.pos ==
5);
CX_TEST_ASSERT(buf.size ==
5);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(target.pos ==
7);
CX_TEST_ASSERT(target.size ==
7);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"hello",
5));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoo",
7));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_write_flush_at_threshold) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
cxBufferPutString(&buf,
"prep");
CX_TEST_DO {
CxBufferFlushConfig flush;
flush.threshold =
16;
flush.blksize =
32;
flush.blkmax =
1;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, flush));
size_t written = cxBufferWrite(
"foobar",
1,
6, &buf);
CX_TEST_ASSERT(written ==
6);
CX_TEST_ASSERT(buf.pos ==
10);
CX_TEST_ASSERT(buf.size ==
10);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(target.pos ==
0);
CX_TEST_ASSERT(target.size ==
0);
written = cxBufferWrite(
"hello world",
1,
11, &buf);
CX_TEST_ASSERT(written ==
11);
CX_TEST_ASSERT(buf.pos ==
11);
CX_TEST_ASSERT(buf.size ==
11);
CX_TEST_ASSERT(buf.capacity ==
16);
CX_TEST_ASSERT(target.pos ==
10);
CX_TEST_ASSERT(target.size ==
10);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"hello",
5));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoobar",
10));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_write_flush_rate_limited_and_buffer_too_small) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
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 = (cx_write_func)mock_write_limited_rate;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, flush));
size_t written = cxBufferWrite(
"foo",
1,
3, &buf);
CX_TEST_ASSERT(written ==
3);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(target.pos ==
0);
CX_TEST_ASSERT(target.size ==
0);
written = cxBufferWrite(
"hello, world!",
1,
13, &buf);
CX_TEST_ASSERT(written ==
13);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(buf.capacity ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
" world!",
7));
CX_TEST_ASSERT(target.pos ==
13);
CX_TEST_ASSERT(target.size ==
13);
CX_TEST_ASSERT(target.capacity >=
13);
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoohello,",
13));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_write_flush_multibyte) {
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;
flush.blkmax =
2;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, 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));
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));
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) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
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));
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));
written = cxBufferWrite(
"bazfoobar",
3,
3, &buf);
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,
"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;
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));
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));
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));
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));
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_write_flush_multibyte_target_full) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
12, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
CX_TEST_DO {
CxBufferFlushConfig flush;
flush.threshold =
12;
flush.blksize =
8;
flush.blkmax =
2;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, flush));
cxBufferPutString(&buf,
"preparation");
size_t written = cxBufferWrite(
"teststring",
2,
5, &buf);
CX_TEST_ASSERT(written ==
5);
CX_TEST_ASSERT(buf.pos ==
11);
CX_TEST_ASSERT(buf.size ==
11);
CX_TEST_ASSERT(target.pos ==
10);
CX_TEST_ASSERT(target.size ==
10);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"nteststring",
11));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"preparatio",
10));
cxBufferPop(&buf,
1,
1);
written = cxBufferWrite(
"123456",
2,
3, &buf);
CX_TEST_ASSERT(written ==
2);
CX_TEST_ASSERT(buf.pos ==
12);
CX_TEST_ASSERT(buf.size ==
12);
CX_TEST_ASSERT(target.pos ==
12);
CX_TEST_ASSERT(target.size ==
12);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"eststrin1234",
12));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"preparationt",
12));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_write_large_data_flush_target_full) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
target.pos = target.size =
16;
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));
size_t written = cxBufferWrite(
"foobarfoobar",
1,
12, &buf);
CX_TEST_ASSERT(written ==
0);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
CX_TEST_ASSERT(target.pos ==
16);
CX_TEST_ASSERT(target.size ==
16);
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_write_flush_at_threshold_target_full) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
cxBufferPutString(&buf,
"prep");
CX_TEST_DO {
CxBufferFlushConfig flush;
flush.threshold =
16;
flush.blksize =
4;
flush.blkmax =
2;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, flush));
size_t written = cxBufferWrite(
"foobar",
1,
6, &buf);
CX_TEST_ASSERT(written ==
6);
CX_TEST_ASSERT(buf.pos ==
10);
CX_TEST_ASSERT(buf.size ==
10);
CX_TEST_ASSERT(target.pos ==
0);
CX_TEST_ASSERT(target.size ==
0);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"prepfoobar",
10));
written = cxBufferWrite(
"12345678",
1,
8, &buf);
CX_TEST_ASSERT(written ==
8);
CX_TEST_ASSERT(buf.pos ==
10);
CX_TEST_ASSERT(buf.size ==
10);
CX_TEST_ASSERT(target.pos ==
8);
CX_TEST_ASSERT(target.size ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"ar12345678",
10));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoob",
8));
written = cxBufferWrite(
"ABCDEFGH",
1,
8, &buf);
CX_TEST_ASSERT(written ==
6);
CX_TEST_ASSERT(buf.pos ==
16);
CX_TEST_ASSERT(buf.size ==
16);
CX_TEST_ASSERT(target.pos ==
8);
CX_TEST_ASSERT(target.size ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"ar12345678ABCDEF",
16));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoob",
8));
written = cxBufferWrite(
"baz",
1,
3, &buf);
CX_TEST_ASSERT(written ==
0);
CX_TEST_ASSERT(buf.pos ==
16);
CX_TEST_ASSERT(buf.size ==
16);
CX_TEST_ASSERT(target.pos ==
8);
CX_TEST_ASSERT(target.size ==
8);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"ar12345678ABCDEF",
16));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepfoob",
8));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_pop) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferPutString(&buf,
"teststring");
CX_TEST_DO {
CX_TEST_ASSERT(buf.pos ==
10);
CX_TEST_ASSERT(buf.size ==
10);
CX_TEST_ASSERT(cxBufferPop(&buf,
1,
3) ==
3);
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
CX_TEST_ASSERT(cxBufferPop(&buf,
2,
2) ==
2);
CX_TEST_ASSERT(buf.pos ==
3);
CX_TEST_ASSERT(buf.size ==
3);
cxBufferPutString(&buf,
"1234");
CX_TEST_ASSERT(buf.pos ==
7);
CX_TEST_ASSERT(buf.size ==
7);
buf.pos =
3;
CX_TEST_ASSERT(cxBufferPop(&buf,
2,
1) ==
1);
CX_TEST_ASSERT(buf.pos ==
3);
CX_TEST_ASSERT(buf.size ==
5);
CX_TEST_ASSERT(cxBufferPop(&buf,
1,
3) ==
3);
CX_TEST_ASSERT(buf.pos ==
2);
CX_TEST_ASSERT(buf.size ==
2);
cxBufferPut(&buf,
'c');
CX_TEST_ASSERT(buf.pos ==
3);
CX_TEST_ASSERT(buf.size ==
3);
CX_TEST_ASSERT(cxBufferPop(&buf,
2,
2) ==
1);
CX_TEST_ASSERT(buf.pos ==
1);
CX_TEST_ASSERT(buf.size ==
1);
CX_TEST_ASSERT(cxBufferPop(&buf,
1,
3) ==
1);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
0);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_flush) {
CxBuffer buf, target;
cxBufferInit(&target,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_AUTO_EXTEND);
cxBufferInit(&buf,
NULL,
8, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
cxBufferPutString(&buf,
"prepare");
CX_TEST_DO {
CxBufferFlushConfig flush;
flush.threshold =
0;
flush.blksize =
2;
flush.blkmax =
2;
flush.target = ⌖
flush.wfunc = cxBufferWriteFunc;
CX_TEST_ASSERT(
0 == cxBufferEnableFlushing(&buf, flush));
CX_TEST_ASSERT(buf.size ==
7);
buf.pos =
5;
size_t flushed = cxBufferFlush(&buf);
CX_TEST_ASSERT(flushed == flush.blkmax * flush.blksize);
CX_TEST_ASSERT(buf.pos ==
1);
CX_TEST_ASSERT(buf.size ==
3);
CX_TEST_ASSERT(target.pos ==
4);
CX_TEST_ASSERT(target.size ==
4);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"are",
3));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prep",
4));
flushed = cxBufferFlush(&buf);
CX_TEST_ASSERT(flushed ==
1);
CX_TEST_ASSERT(buf.pos ==
0);
CX_TEST_ASSERT(buf.size ==
2);
CX_TEST_ASSERT(target.pos ==
5);
CX_TEST_ASSERT(target.size ==
5);
CX_TEST_ASSERT(
0 == memcmp(buf.space,
"re",
2));
CX_TEST_ASSERT(
0 == memcmp(target.space,
"prepa",
5));
}
cxBufferDestroy(&buf);
cxBufferDestroy(&target);
}
CX_TEST(test_buffer_get) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.size =
9;
buf.pos =
2;
CX_TEST_DO {
CX_TEST_ASSERT(cxBufferGet(&buf) ==
'm');
CX_TEST_ASSERT(cxBufferGet(&buf) ==
'e');
CX_TEST_ASSERT(cxBufferGet(&buf) ==
' ');
CX_TEST_ASSERT(cxBufferGet(&buf) ==
'd');
CX_TEST_ASSERT(buf.pos ==
6);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_get_eof) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.pos = buf.size =
9;
CX_TEST_DO {
CX_TEST_ASSERT(cxBufferGet(&buf) ==
EOF);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_read) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.size =
9;
buf.pos =
2;
CX_TEST_DO {
char target[
4];
size_t read = cxBufferRead(&target,
1,
4, &buf);
CX_TEST_ASSERT(read ==
4);
CX_TEST_ASSERT(
0 == memcmp(&target,
"me d",
4));
CX_TEST_ASSERT(buf.pos ==
6);
errno =
0;
read = cxBufferRead(&target,
4,
SIZE_MAX/
2, &buf);
CX_TEST_ASSERT(read ==
0);
CX_TEST_ASSERT(errno ==
EOVERFLOW);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_read_oob) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.size =
9;
buf.pos =
6;
CX_TEST_DO {
char target[
4];
size_t read = cxBufferRead(&target,
1,
4, &buf);
CX_TEST_ASSERT(read ==
3);
CX_TEST_ASSERT(
0 == memcmp(&target,
"ata",
3));
CX_TEST_ASSERT(buf.pos ==
9);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_read_oob_multibyte) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.size =
9;
buf.pos =
6;
CX_TEST_DO {
char target[
4];
target[
2] =
'\0';
size_t read = cxBufferRead(&target,
2,
2, &buf);
CX_TEST_ASSERT(read ==
1);
CX_TEST_ASSERT(
0 == memcmp(&target,
"at\0",
3));
CX_TEST_ASSERT(buf.pos ==
8);
}
cxBufferDestroy(&buf);
}
CX_TEST(test_buffer_read_eof) {
CxBuffer buf;
cxBufferInit(&buf,
NULL,
16, cxDefaultAllocator,
CX_BUFFER_DEFAULT);
memcpy(buf.space,
"some data\0\0\0\0\0\0\0",
16);
buf.capacity =
12;
buf.size = buf.pos =
9;
CX_TEST_DO {
char target[
4];
size_t read = cxBufferRead(&target,
1,
1, &buf);
CX_TEST_ASSERT(read ==
0);
CX_TEST_ASSERT(buf.pos ==
9);
}
cxBufferDestroy(&buf);
}
CxTestSuite *cx_test_suite_buffer(
void) {
CxTestSuite *suite = cx_test_suite_new(
"buffer");
cx_test_register(suite, test_buffer_init_wrap_space);
cx_test_register(suite, test_buffer_init_wrap_space_auto_extend);
cx_test_register(suite, test_buffer_init_wrap_space_auto_free);
cx_test_register(suite, test_buffer_init_fresh_space);
cx_test_register(suite, test_buffer_init_on_heap);
cx_test_register(suite, test_buffer_create_defaulted_allocator);
cx_test_register(suite, test_buffer_minimum_capacity_sufficient);
cx_test_register(suite, test_buffer_minimum_capacity_extend);
cx_test_register(suite, test_buffer_shrink);
cx_test_register(suite, test_buffer_shrink_copy_on_write);
cx_test_register(suite, test_buffer_shrink_copy_on_extend);
cx_test_register(suite, test_buffer_reserve);
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);
cx_test_register(suite, test_buffer_seek_set_invalid);
cx_test_register(suite, test_buffer_seek_cur_zero);
cx_test_register(suite, test_buffer_seek_cur_valid_positive);
cx_test_register(suite, test_buffer_seek_cur_valid_negative);
cx_test_register(suite, test_buffer_seek_cur_invalid_positive);
cx_test_register(suite, test_buffer_seek_cur_invalid_negative);
cx_test_register(suite, test_buffer_seek_end_zero);
cx_test_register(suite, test_buffer_seek_end_valid);
cx_test_register(suite, test_buffer_seek_end_invalid);
cx_test_register(suite, test_buffer_seek_whence_invalid);
cx_test_register(suite, test_buffer_eof_reached);
cx_test_register(suite, test_buffer_eof_not_reached);
cx_test_register(suite, test_buffer_shift_left_zero);
cx_test_register(suite, test_buffer_shift_left_zero_offset_interface);
cx_test_register(suite, test_buffer_shift_left_standard);
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_shift_right_overflow);
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_append);
cx_test_register(suite, test_buffer_append_flush);
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_copy_on_extend);
cx_test_register(suite, test_buffer_put_string_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);
cx_test_register(suite, test_buffer_write_only_overwrite);
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_at_threshold_target_full);
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_write_flush_multibyte_target_full);
cx_test_register(suite, test_buffer_write_large_data_flush_target_full);
cx_test_register(suite, test_buffer_pop);
cx_test_register(suite, test_buffer_flush);
cx_test_register(suite, test_buffer_get);
cx_test_register(suite, test_buffer_get_eof);
cx_test_register(suite, test_buffer_read);
cx_test_register(suite, test_buffer_read_oob);
cx_test_register(suite, test_buffer_read_oob_multibyte);
cx_test_register(suite, test_buffer_read_eof);
return suite;
}