123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #include "test/jemalloc_test.h"
- #include "jemalloc/internal/buf_writer.h"
- #define TEST_BUF_SIZE 16
- #define UNIT_MAX (TEST_BUF_SIZE * 3)
- static size_t test_write_len;
- static char test_buf[TEST_BUF_SIZE];
- static uint64_t arg;
- static uint64_t arg_store;
- static void
- test_write_cb(void *cbopaque, const char *s) {
- size_t prev_test_write_len = test_write_len;
- test_write_len += strlen(s); /* only increase the length */
- arg_store = *(uint64_t *)cbopaque; /* only pass along the argument */
- assert_zu_le(prev_test_write_len, test_write_len,
- "Test write overflowed");
- }
- static void
- test_buf_writer_body(tsdn_t *tsdn, buf_writer_t *buf_writer) {
- char s[UNIT_MAX + 1];
- size_t n_unit, remain, i;
- ssize_t unit;
- assert(buf_writer->buf != NULL);
- memset(s, 'a', UNIT_MAX);
- arg = 4; /* Starting value of random argument. */
- arg_store = arg;
- for (unit = UNIT_MAX; unit >= 0; --unit) {
- /* unit keeps decreasing, so strlen(s) is always unit. */
- s[unit] = '\0';
- for (n_unit = 1; n_unit <= 3; ++n_unit) {
- test_write_len = 0;
- remain = 0;
- for (i = 1; i <= n_unit; ++i) {
- arg = prng_lg_range_u64(&arg, 64);
- buf_writer_cb(buf_writer, s);
- remain += unit;
- if (remain > buf_writer->buf_size) {
- /* Flushes should have happened. */
- assert_u64_eq(arg_store, arg, "Call "
- "back argument didn't get through");
- remain %= buf_writer->buf_size;
- if (remain == 0) {
- /* Last flush should be lazy. */
- remain += buf_writer->buf_size;
- }
- }
- assert_zu_eq(test_write_len + remain, i * unit,
- "Incorrect length after writing %zu strings"
- " of length %zu", i, unit);
- }
- buf_writer_flush(buf_writer);
- expect_zu_eq(test_write_len, n_unit * unit,
- "Incorrect length after flushing at the end of"
- " writing %zu strings of length %zu", n_unit, unit);
- }
- }
- buf_writer_terminate(tsdn, buf_writer);
- }
- TEST_BEGIN(test_buf_write_static) {
- buf_writer_t buf_writer;
- tsdn_t *tsdn = tsdn_fetch();
- assert_false(buf_writer_init(tsdn, &buf_writer, test_write_cb, &arg,
- test_buf, TEST_BUF_SIZE),
- "buf_writer_init() should not encounter error on static buffer");
- test_buf_writer_body(tsdn, &buf_writer);
- }
- TEST_END
- TEST_BEGIN(test_buf_write_dynamic) {
- buf_writer_t buf_writer;
- tsdn_t *tsdn = tsdn_fetch();
- assert_false(buf_writer_init(tsdn, &buf_writer, test_write_cb, &arg,
- NULL, TEST_BUF_SIZE), "buf_writer_init() should not OOM");
- test_buf_writer_body(tsdn, &buf_writer);
- }
- TEST_END
- TEST_BEGIN(test_buf_write_oom) {
- buf_writer_t buf_writer;
- tsdn_t *tsdn = tsdn_fetch();
- assert_true(buf_writer_init(tsdn, &buf_writer, test_write_cb, &arg,
- NULL, SC_LARGE_MAXCLASS + 1), "buf_writer_init() should OOM");
- assert(buf_writer.buf == NULL);
- char s[UNIT_MAX + 1];
- size_t n_unit, i;
- ssize_t unit;
- memset(s, 'a', UNIT_MAX);
- arg = 4; /* Starting value of random argument. */
- arg_store = arg;
- for (unit = UNIT_MAX; unit >= 0; unit -= UNIT_MAX / 4) {
- /* unit keeps decreasing, so strlen(s) is always unit. */
- s[unit] = '\0';
- for (n_unit = 1; n_unit <= 3; ++n_unit) {
- test_write_len = 0;
- for (i = 1; i <= n_unit; ++i) {
- arg = prng_lg_range_u64(&arg, 64);
- buf_writer_cb(&buf_writer, s);
- assert_u64_eq(arg_store, arg,
- "Call back argument didn't get through");
- assert_zu_eq(test_write_len, i * unit,
- "Incorrect length after writing %zu strings"
- " of length %zu", i, unit);
- }
- buf_writer_flush(&buf_writer);
- expect_zu_eq(test_write_len, n_unit * unit,
- "Incorrect length after flushing at the end of"
- " writing %zu strings of length %zu", n_unit, unit);
- }
- }
- buf_writer_terminate(tsdn, &buf_writer);
- }
- TEST_END
- static int test_read_count;
- static size_t test_read_len;
- static uint64_t arg_sum;
- ssize_t
- test_read_cb(void *cbopaque, void *buf, size_t limit) {
- static uint64_t rand = 4;
- arg_sum += *(uint64_t *)cbopaque;
- assert_zu_gt(limit, 0, "Limit for read_cb must be positive");
- --test_read_count;
- if (test_read_count == 0) {
- return -1;
- } else {
- size_t read_len = limit;
- if (limit > 1) {
- rand = prng_range_u64(&rand, (uint64_t)limit);
- read_len -= (size_t)rand;
- }
- assert(read_len > 0);
- memset(buf, 'a', read_len);
- size_t prev_test_read_len = test_read_len;
- test_read_len += read_len;
- assert_zu_le(prev_test_read_len, test_read_len,
- "Test read overflowed");
- return read_len;
- }
- }
- static void
- test_buf_writer_pipe_body(tsdn_t *tsdn, buf_writer_t *buf_writer) {
- arg = 4; /* Starting value of random argument. */
- for (int count = 5; count > 0; --count) {
- arg = prng_lg_range_u64(&arg, 64);
- arg_sum = 0;
- test_read_count = count;
- test_read_len = 0;
- test_write_len = 0;
- buf_writer_pipe(buf_writer, test_read_cb, &arg);
- assert(test_read_count == 0);
- expect_u64_eq(arg_sum, arg * count, "");
- expect_zu_eq(test_write_len, test_read_len,
- "Write length should be equal to read length");
- }
- buf_writer_terminate(tsdn, buf_writer);
- }
- TEST_BEGIN(test_buf_write_pipe) {
- buf_writer_t buf_writer;
- tsdn_t *tsdn = tsdn_fetch();
- assert_false(buf_writer_init(tsdn, &buf_writer, test_write_cb, &arg,
- test_buf, TEST_BUF_SIZE),
- "buf_writer_init() should not encounter error on static buffer");
- test_buf_writer_pipe_body(tsdn, &buf_writer);
- }
- TEST_END
- TEST_BEGIN(test_buf_write_pipe_oom) {
- buf_writer_t buf_writer;
- tsdn_t *tsdn = tsdn_fetch();
- assert_true(buf_writer_init(tsdn, &buf_writer, test_write_cb, &arg,
- NULL, SC_LARGE_MAXCLASS + 1), "buf_writer_init() should OOM");
- test_buf_writer_pipe_body(tsdn, &buf_writer);
- }
- TEST_END
- int
- main(void) {
- return test(
- test_buf_write_static,
- test_buf_write_dynamic,
- test_buf_write_oom,
- test_buf_write_pipe,
- test_buf_write_pipe_oom);
- }
|