diff --git a/include/buffer/cc_buf.h b/include/buffer/cc_buf.h index 4fe111dd3..ce7a6053b 100644 --- a/include/buffer/cc_buf.h +++ b/include/buffer/cc_buf.h @@ -38,25 +38,25 @@ extern "C" { /* name type default description */ -#define BUF_OPTION(ACTION) \ - ACTION( buf_init_size, OPTION_TYPE_UINT, BUF_DEFAULT_SIZE, "default size when buf is created" )\ - ACTION( buf_poolsize, OPTION_TYPE_UINT, BUF_POOLSIZE, "buf pool size" ) +#define BUF_OPTION(ACTION) \ + ACTION( buf_init_size, OPTION_TYPE_UINT, BUF_DEFAULT_SIZE, "init buf size incl header" )\ + ACTION( buf_poolsize, OPTION_TYPE_UINT, BUF_POOLSIZE, "buf pool size" ) typedef struct { BUF_OPTION(OPTION_DECLARE) } buf_options_st; /* name type description */ -#define BUF_METRIC(ACTION) \ - ACTION( buf_curr, METRIC_GAUGE, "# buf allocated" )\ - ACTION( buf_active, METRIC_GAUGE, "# buf in use/borrowed" )\ - ACTION( buf_create, METRIC_COUNTER, "# buf creates" )\ - ACTION( buf_create_ex, METRIC_COUNTER, "# buf create exceptions")\ - ACTION( buf_destroy, METRIC_COUNTER, "# buf destroys" )\ - ACTION( buf_borrow, METRIC_COUNTER, "# buf borrows" )\ - ACTION( buf_borrow_ex, METRIC_COUNTER, "# buf borrow exceptions")\ - ACTION( buf_return, METRIC_COUNTER, "# buf returns" )\ - ACTION( buf_memory, METRIC_GAUGE, "memory allocated to buf") +#define BUF_METRIC(ACTION) \ + ACTION( buf_curr, METRIC_GAUGE, "# buf allocated" )\ + ACTION( buf_active, METRIC_GAUGE, "# buf in use/borrowed" )\ + ACTION( buf_create, METRIC_COUNTER, "# buf creates" )\ + ACTION( buf_create_ex, METRIC_COUNTER, "# buf create exceptions" )\ + ACTION( buf_destroy, METRIC_COUNTER, "# buf destroys" )\ + ACTION( buf_borrow, METRIC_COUNTER, "# buf borrows" )\ + ACTION( buf_borrow_ex, METRIC_COUNTER, "# buf borrow exceptions" )\ + ACTION( buf_return, METRIC_COUNTER, "# buf returns" )\ + ACTION( buf_memory, METRIC_GAUGE, "memory alloc'd to buf including header" ) typedef struct { BUF_METRIC(METRIC_DECLARE) @@ -103,7 +103,7 @@ void buf_destroy(struct buf **buf); /* Size of data that has yet to be read */ static inline uint32_t -buf_rsize(struct buf *buf) +buf_rsize(const struct buf *buf) { ASSERT(buf->rpos <= buf->wpos); @@ -112,37 +112,38 @@ buf_rsize(struct buf *buf) /* Amount of room left in buffer for writing new data */ static inline uint32_t -buf_wsize(struct buf *buf) +buf_wsize(const struct buf *buf) { ASSERT(buf->wpos <= buf->end); return (uint32_t)(buf->end - buf->wpos); } -/* Total capacity of given buf */ +/* Total size of given buf, including header */ static inline uint32_t -buf_size(struct buf *buf) +buf_size(const struct buf *buf) { ASSERT(buf->begin < buf->end); - return (uint32_t)(buf->end - (char*)buf); + return (uint32_t)(buf->end - (char *)buf); } +/* Size of given buf, not including header */ static inline uint32_t -buf_capacity(struct buf *buf) +buf_capacity(const struct buf *buf) { ASSERT(buf->begin < buf->end); return (uint32_t)(buf->end - buf->begin); } -/* new capacity needed to append count bytes to the buffer */ +/* new capacity needed to write count bytes to the buffer */ static inline uint32_t -buf_new_cap(struct buf *buf, uint32_t count) +buf_new_cap(const struct buf *buf, uint32_t count) { ASSERT(buf->begin <= buf->wpos); - return buf->wpos - buf->begin + count; + return count <= buf_wsize(buf) ? 0 : count - buf_wsize(buf); } static inline void diff --git a/include/buffer/cc_dbuf.h b/include/buffer/cc_dbuf.h index 185de4734..07ad34f96 100644 --- a/include/buffer/cc_dbuf.h +++ b/include/buffer/cc_dbuf.h @@ -29,8 +29,8 @@ extern "C" { /* name type default description */ -#define DBUF_OPTION(ACTION) \ - ACTION( dbuf_max_power, OPTION_TYPE_UINT, DBUF_DEFAULT_MAX, "max number of doubling" ) +#define DBUF_OPTION(ACTION) \ + ACTION( dbuf_max_power, OPTION_TYPE_UINT, DBUF_DEFAULT_MAX, "max number of doubles") typedef struct { DBUF_OPTION(OPTION_DECLARE) @@ -43,7 +43,7 @@ typedef struct { ACTION( dbuf_double, METRIC_COUNTER, "# double completed" )\ ACTION( dbuf_double_ex, METRIC_COUNTER, "# double failed" )\ ACTION( dbuf_shrink, METRIC_COUNTER, "# shrink completed" )\ - ACTION( dbuf_shrink_ex, METRIC_COUNTER, "# srhink failed" )\ + ACTION( dbuf_shrink_ex, METRIC_COUNTER, "# shrink failed" )\ ACTION( dbuf_fit, METRIC_COUNTER, "# fit completed" )\ ACTION( dbuf_fit_ex, METRIC_COUNTER, "# fit failed" ) diff --git a/src/buffer/cc_buf.c b/src/buffer/cc_buf.c index 4ac2b12e6..c23404719 100644 --- a/src/buffer/cc_buf.c +++ b/src/buffer/cc_buf.c @@ -157,8 +157,8 @@ buf_destroy(struct buf **buf) return; } - cap = buf_capacity(*buf); - log_verb("destroy buf %p capacity %"PRIu32, *buf, cap); + cap = buf_size(*buf); + log_verb("destroy buf %p size %"PRIu32, *buf, cap); cc_free(*buf); *buf = NULL; diff --git a/src/buffer/cc_dbuf.c b/src/buffer/cc_dbuf.c index db2432210..46ab23341 100644 --- a/src/buffer/cc_dbuf.c +++ b/src/buffer/cc_dbuf.c @@ -51,9 +51,15 @@ static rstatus_i _dbuf_resize(struct buf **buf, uint32_t nsize) { struct buf *nbuf; - uint32_t osize = buf_size(*buf); - uint32_t roffset = (*buf)->rpos - (*buf)->begin; - uint32_t woffset = (*buf)->wpos - (*buf)->begin; + uint32_t osize, roffset, woffset; + + if (nsize > max_size) { + return CC_ERROR; + } + + osize = buf_size(*buf); + roffset = (*buf)->rpos - (*buf)->begin; + woffset = (*buf)->wpos - (*buf)->begin; nbuf = cc_realloc(*buf, nsize); if (nbuf == NULL) { /* realloc failed, but *buf is still valid */ @@ -80,10 +86,6 @@ dbuf_double(struct buf **buf) rstatus_i status; uint32_t nsize = buf_size(*buf) * 2; - if (nsize > max_size) { - return CC_ERROR; - } - status = _dbuf_resize(buf, nsize); if (status == CC_OK) { INCR(dbuf_metrics, dbuf_double); @@ -100,12 +102,14 @@ dbuf_fit(struct buf **buf, uint32_t cap) rstatus_i status = CC_OK; uint32_t nsize = buf_init_size; - buf_lshift(*buf); - if (buf_rsize(*buf) > cap || cap + BUF_HDR_SIZE > max_size) { + /* check if new cap can contain unread bytes */ + if (buf_rsize(*buf) > cap) { return CC_ERROR; } - /* cap is checked, given how max_size is initialized this is safe */ + buf_lshift(*buf); + + /* double size of buf until it can fit cap */ while (nsize < cap + BUF_HDR_SIZE) { nsize *= 2; } @@ -125,9 +129,9 @@ dbuf_fit(struct buf **buf, uint32_t cap) rstatus_i dbuf_shrink(struct buf **buf) { - rstatus_i status = CC_OK; uint32_t nsize = buf_init_size; uint32_t cap = buf_rsize(*buf); + rstatus_i status = CC_OK; buf_lshift(*buf); @@ -136,7 +140,12 @@ dbuf_shrink(struct buf **buf) } if (nsize != buf_size(*buf)) { + /* + * realloc is not guaranteed to succeed even on trim, but in the case + * that it fails, original buf will still be valid. + */ status = _dbuf_resize(buf, nsize); + if (status == CC_OK) { INCR(dbuf_metrics, dbuf_shrink); } else { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 388d3948f..6bea60886 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) add_subdirectory(array) add_subdirectory(bstring) +add_subdirectory(buffer) add_subdirectory(channel) add_subdirectory(event) add_subdirectory(log) diff --git a/test/buffer/CMakeLists.txt b/test/buffer/CMakeLists.txt new file mode 100644 index 000000000..4f3fd14a1 --- /dev/null +++ b/test/buffer/CMakeLists.txt @@ -0,0 +1,10 @@ +set(suite buf) +set(test_name check_${suite}) + +set(source check_${suite}.c) + +add_executable(${test_name} ${source}) +target_link_libraries(${test_name} ccommon-static ${CHECK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} m) + +add_dependencies(check ${test_name}) +add_test(${test_name} ${test_name}) diff --git a/test/buffer/check_buf.c b/test/buffer/check_buf.c new file mode 100644 index 000000000..65ad13c45 --- /dev/null +++ b/test/buffer/check_buf.c @@ -0,0 +1,429 @@ +#include +#include + +#include + +#include + +#define SUITE_NAME "buffer" +#define DEBUG_LOG SUITE_NAME ".log" + +#define TEST_BUF_CAP 32 +#define TEST_BUF_SIZE (TEST_BUF_CAP + BUF_HDR_SIZE) +#define TEST_BUF_POOLSIZE 0 +#define TEST_DBUF_MAX 2 + +static buf_metrics_st bmetrics; +static dbuf_metrics_st dmetrics; + +static buf_options_st boptions; +static dbuf_options_st doptions; + +/* + * utilities + */ +static void +test_setup(void) +{ + bmetrics = (buf_metrics_st) { BUF_METRIC(METRIC_INIT) }; + dmetrics = (dbuf_metrics_st) { DBUF_METRIC(METRIC_INIT) }; + + boptions = (buf_options_st){ + .buf_init_size = { + .set = true, + .type = OPTION_TYPE_UINT, + .val.vuint = TEST_BUF_SIZE, + }, + .buf_poolsize = { + .set = true, + .type = OPTION_TYPE_UINT, + .val.vuint = TEST_BUF_POOLSIZE, + }}; + + doptions = (dbuf_options_st){ + .dbuf_max_power = { + .set = true, + .type = OPTION_TYPE_UINT, + .val.vuint = TEST_DBUF_MAX, + }}; + + buf_setup(&boptions, &bmetrics); + dbuf_setup(&doptions, &dmetrics); +} + +static void +test_teardown(void) +{ + buf_teardown(); + dbuf_teardown(); +} + +static void +test_reset(void) +{ + test_teardown(); + test_setup(); +} + +/* + * tests + */ +START_TEST(test_create_write_read_destroy_basic) +{ +#define MSG "Hello World" +#define NEW_CAP 100 + struct buf *buf = NULL; + char message[sizeof(MSG)]; + + test_reset(); + cc_memset(message, 0, sizeof(MSG)); + + /* Test create and metrics */ + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + ck_assert_int_eq(bmetrics.buf_curr.gauge, 1); + ck_assert_uint_eq(bmetrics.buf_create.counter, 1); + ck_assert_uint_eq(bmetrics.buf_destroy.counter, 0); + ck_assert_int_eq(bmetrics.buf_memory.gauge, TEST_BUF_SIZE); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP); + ck_assert_uint_eq(buf_size(buf), TEST_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), TEST_BUF_CAP); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP - TEST_BUF_CAP); + + /* Write message to buffer, and read, check buffer state */ + ck_assert_uint_eq(buf_write(buf, MSG, sizeof(MSG)), sizeof(MSG)); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG)); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP - sizeof(MSG)); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), + NEW_CAP - (TEST_BUF_CAP - sizeof(MSG))); + + /* Read message from buffer, check buf state and if message is intact */ + ck_assert_uint_eq(buf_read(message, buf, sizeof(MSG)), sizeof(MSG)); + ck_assert_int_eq(cc_memcmp(message, MSG, sizeof(MSG)), 0); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP - sizeof(MSG)); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), + NEW_CAP - (TEST_BUF_CAP - sizeof(MSG))); + + /* Test destroy and metrics */ + buf_destroy(&buf); + ck_assert_ptr_eq(buf, NULL); + ck_assert_int_eq(bmetrics.buf_curr.gauge, 0); + ck_assert_uint_eq(bmetrics.buf_create.counter, 1); + ck_assert_uint_eq(bmetrics.buf_destroy.counter, 1); + ck_assert_int_eq(bmetrics.buf_memory.gauge, 0); +#undef MSG +#undef CAP +} +END_TEST + +START_TEST(test_create_write_read_destroy_long) +{ +#define MSG "this is a message that is long enough to fill up the entire buffer" +#define NEW_CAP 100 + struct buf *buf = NULL; + char message[sizeof(MSG)]; + + test_reset(); + cc_memset(message, 0, sizeof(MSG)); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* Write message to buffer, expect full buffer */ + ck_assert_uint_eq(buf_write(buf, MSG, sizeof(MSG)), TEST_BUF_CAP); + ck_assert_uint_eq(buf_rsize(buf), TEST_BUF_CAP); + ck_assert_uint_eq(buf_wsize(buf), 0); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP); + + /* Read message from buffer, expect clipped message */ + ck_assert_uint_eq(buf_read(message, buf, sizeof(MSG)), TEST_BUF_CAP); + ck_assert_int_eq(cc_memcmp(message, MSG, TEST_BUF_CAP), 0); + ck_assert_int_ne(cc_memcmp(message, MSG, TEST_BUF_CAP + 1), 0); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), 0); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP); + + buf_destroy(&buf); +#undef MSG +#undef NEW_CAP +} +END_TEST + +START_TEST(test_lshift) +{ +#define MSG "Hello World" +#define NEW_CAP 100 +#define READ_LEN 5 + struct buf *buf = NULL; + char message[sizeof(MSG)]; + + test_reset(); + cc_memset(message, 0, sizeof(MSG)); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* Write message to buffer */ + ck_assert_uint_eq(buf_write(buf, MSG, sizeof(MSG)), sizeof(MSG)); + + /* Read part of message */ + ck_assert_uint_eq(buf_read(message, buf, READ_LEN), READ_LEN); + ck_assert_int_eq(cc_memcmp(message, MSG, READ_LEN), 0); + ck_assert_int_ne(cc_memcmp(message, MSG, READ_LEN + 1), 0); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG) - READ_LEN); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP - sizeof(MSG)); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), + NEW_CAP - (TEST_BUF_CAP - sizeof(MSG))); + + /* lshift buffer, check state */ + buf_lshift(buf); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG) - READ_LEN); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP - (sizeof(MSG) - READ_LEN)); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), + NEW_CAP - (TEST_BUF_CAP - (sizeof(MSG) - READ_LEN))); + + /* Read rest of message */ + ck_assert_uint_eq(buf_read(message + READ_LEN, buf, sizeof(MSG)), + sizeof(MSG) - READ_LEN); + ck_assert_int_eq(cc_memcmp(message, MSG, sizeof(MSG)), 0); + ck_assert_uint_eq(buf_rsize(buf), 0); + + /* lshift again */ + buf_lshift(buf); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP); + ck_assert_uint_eq(buf_size(buf), TEST_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), TEST_BUF_CAP); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP - TEST_BUF_CAP); + + buf_destroy(&buf); +#undef MSG +#undef NEW_CAP +#undef READ_LEN +} +END_TEST + +START_TEST(test_rshift) +{ +#define MSG "Hello World" +#define NEW_CAP 100 +#define READ_LEN 5 + struct buf *buf = NULL; + char message[sizeof(MSG)]; + + test_reset(); + cc_memset(message, 0, sizeof(MSG)); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* Write message to buffer */ + ck_assert_uint_eq(buf_write(buf, MSG, sizeof(MSG)), sizeof(MSG)); + + /* Read part of message */ + ck_assert_uint_eq(buf_read(message, buf, READ_LEN), READ_LEN); + + /* rshift buffer, check state */ + buf_rshift(buf); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG) - READ_LEN); + ck_assert_uint_eq(buf_wsize(buf), 0); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP); + + /* Read rest of message */ + ck_assert_uint_eq(buf_read(message + READ_LEN, buf, sizeof(MSG)), + sizeof(MSG) - READ_LEN); + ck_assert_int_eq(cc_memcmp(message, MSG, sizeof(MSG)), 0); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), 0); + + buf_destroy(&buf); +#undef MSG +#undef NEW_CAP +#undef READ_LEN +} +END_TEST + +START_TEST(test_dbuf_double_basic) +{ +#define EXPECTED_BUF_SIZE (TEST_BUF_SIZE * 2) +#define EXPECTED_BUF_CAP (EXPECTED_BUF_SIZE - BUF_HDR_SIZE) +#define NEW_CAP 200 + struct buf *buf; + + test_reset(); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* double buffer, check state */ + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + ck_assert_ptr_ne(buf, NULL); + ck_assert_int_eq(bmetrics.buf_curr.gauge, 1); + ck_assert_uint_eq(bmetrics.buf_create.counter, 1); + ck_assert_uint_eq(bmetrics.buf_destroy.counter, 0); + ck_assert_int_eq(bmetrics.buf_memory.gauge, EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), EXPECTED_BUF_CAP); + ck_assert_uint_eq(buf_size(buf), EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), EXPECTED_BUF_CAP); + ck_assert_uint_eq(buf_new_cap(buf, NEW_CAP), NEW_CAP - EXPECTED_BUF_CAP); + + /* destroy, check if memory gauge decremented correctly */ + buf_destroy(&buf); + ck_assert_int_eq(bmetrics.buf_memory.gauge, 0); +#undef EXPECTED_BUF_SIZE +#undef EXPECTED_BUF_CAP +#undef NEW_CAP +} +END_TEST + +START_TEST(test_dbuf_double_over_max) +{ + int i; + struct buf *buf; + + test_reset(); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + for (i = 0; i < TEST_DBUF_MAX; ++i) { + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + } + + ck_assert_int_eq(dbuf_double(&buf), CC_ERROR); + + buf_destroy(&buf); +} +END_TEST + +START_TEST(test_dbuf_fit) +{ +#define CAP_SMALL (TEST_BUF_CAP * 4) +#define EXPECTED_BUF_SIZE (TEST_BUF_SIZE * 4) +#define EXPECTED_BUF_CAP (EXPECTED_BUF_SIZE - BUF_HDR_SIZE) +#define CAP_LARGE (TEST_BUF_CAP * 16) + struct buf *buf; + + test_reset(); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* fit to small size, check state */ + ck_assert_int_eq(dbuf_fit(&buf, CAP_SMALL), CC_OK); + ck_assert_int_eq(bmetrics.buf_memory.gauge, EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_rsize(buf), 0); + ck_assert_uint_eq(buf_wsize(buf), EXPECTED_BUF_CAP); + ck_assert_uint_eq(buf_size(buf), EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), EXPECTED_BUF_CAP); + + /* attempt to fit to large size */ + ck_assert_int_eq(dbuf_fit(&buf, CAP_LARGE), CC_ERROR); + + buf_destroy(&buf); +#undef CAP_SMALL +#undef EXPECTED_BUF_SIZE +#undef EXPECTED_BUF_CAP +#undef CAP_LARGE +} +END_TEST + +START_TEST(test_dbuf_shrink) +{ +#define MSG1 "Hello World" +#define MSG2 "this message can be contained by a singly doubled buffer" +#define EXPECTED_BUF_SIZE (TEST_BUF_SIZE * 2) +#define EXPECTED_BUF_CAP (EXPECTED_BUF_SIZE - BUF_HDR_SIZE) + struct buf *buf; + + test_reset(); + + buf = buf_create(); + ck_assert_ptr_ne(buf, NULL); + + /* write first message, double twice, then shrink */ + ck_assert_uint_eq(buf_write(buf, MSG1, sizeof(MSG1)), sizeof(MSG1)); + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + + /* shrink, then check state */ + ck_assert_int_eq(dbuf_shrink(&buf), CC_OK); + ck_assert_int_eq(bmetrics.buf_memory.gauge, TEST_BUF_SIZE); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG1)); + ck_assert_uint_eq(buf_wsize(buf), TEST_BUF_CAP - sizeof(MSG1)); + ck_assert_uint_eq(buf_size(buf), TEST_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), TEST_BUF_CAP); + + buf_reset(buf); + + /* double twice, then write second message */ + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + ck_assert_int_eq(dbuf_double(&buf), CC_OK); + ck_assert_uint_eq(buf_write(buf, MSG2, sizeof(MSG2)), sizeof(MSG2)); + + /* shrink, then check state */ + ck_assert_int_eq(dbuf_shrink(&buf), CC_OK); + ck_assert_int_eq(bmetrics.buf_memory.gauge, EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_rsize(buf), sizeof(MSG2)); + ck_assert_uint_eq(buf_wsize(buf), EXPECTED_BUF_CAP - sizeof(MSG2)); + ck_assert_uint_eq(buf_size(buf), EXPECTED_BUF_SIZE); + ck_assert_uint_eq(buf_capacity(buf), EXPECTED_BUF_CAP); + + buf_destroy(&buf); +#undef MSG1 +#undef MSG2 +#undef EXPECTED_BUF_SIZE +#undef EXPECTED_BUF_CAP +} +END_TEST + +/* + * test suite + */ +static Suite * +buf_suite(void) +{ + Suite *s = suite_create(SUITE_NAME); + + TCase *tc_buf = tcase_create("buf test"); + suite_add_tcase(s, tc_buf); + + tcase_add_test(tc_buf, test_create_write_read_destroy_basic); + tcase_add_test(tc_buf, test_create_write_read_destroy_long); + tcase_add_test(tc_buf, test_lshift); + tcase_add_test(tc_buf, test_rshift); + + TCase *tc_dbuf = tcase_create("dbuf test"); + suite_add_tcase(s, tc_dbuf); + + tcase_add_test(tc_dbuf, test_dbuf_double_basic); + tcase_add_test(tc_dbuf, test_dbuf_double_over_max); + tcase_add_test(tc_dbuf, test_dbuf_fit); + tcase_add_test(tc_dbuf, test_dbuf_shrink); + + return s; +} + +int +main(void) +{ + int nfail; + + /* setup */ + test_setup(); + + Suite *suite = buf_suite(); + SRunner *srunner = srunner_create(suite); + srunner_set_log(srunner, DEBUG_LOG); + srunner_run_all(srunner, CK_ENV); /* set CK_VEBOSITY in ENV to customize */ + nfail = srunner_ntests_failed(srunner); + srunner_free(srunner); + + /* teardown */ + test_teardown(); + + return (nfail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/rbuf/check_rbuf.c b/test/rbuf/check_rbuf.c index 3656747ea..e34925ec4 100644 --- a/test/rbuf/check_rbuf.c +++ b/test/rbuf/check_rbuf.c @@ -49,7 +49,6 @@ write_read_rbuf(struct rbuf *buffer, char *write_data, size_t w1_len, size_t w2_ ck_assert_int_eq(rbuf_rcap(buffer), w1_len); ck_assert_int_eq(rbuf_wcap(buffer), w2_len); - written = rbuf_write(buffer, &write_data[w1_len], w2_len); ck_assert_int_eq(written, w2_len);