2019-06-08 05:04:59 +08:00
|
|
|
#include "test/jemalloc_test.h"
|
|
|
|
|
2020-01-10 08:36:09 +08:00
|
|
|
#include "jemalloc/internal/buf_writer.h"
|
|
|
|
|
2019-06-08 05:04:59 +08:00
|
|
|
#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];
|
2020-02-04 07:56:13 +08:00
|
|
|
static uint64_t arg;
|
2019-06-08 05:04:59 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2020-02-04 07:56:13 +08:00
|
|
|
static void test_buf_writer_body(tsdn_t *tsdn, buf_writer_t *buf_writer) {
|
2019-06-08 05:04:59 +08:00
|
|
|
char s[UNIT_MAX + 1];
|
|
|
|
size_t n_unit, remain, i;
|
|
|
|
ssize_t unit;
|
2020-02-04 07:56:13 +08:00
|
|
|
assert_ptr_not_null(buf_writer->buf, "Buffer is null");
|
|
|
|
write_cb_t *write_cb = buf_writer_get_write_cb(buf_writer);
|
|
|
|
void *cbopaque = buf_writer_get_cbopaque(buf_writer);
|
2019-06-08 05:04:59 +08:00
|
|
|
|
|
|
|
memset(s, 'a', UNIT_MAX);
|
2020-02-04 07:56:13 +08:00
|
|
|
arg = 4; /* Starting value of random argument. */
|
2019-06-08 05:04:59 +08:00
|
|
|
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);
|
2020-02-04 07:56:13 +08:00
|
|
|
write_cb(cbopaque, s);
|
2019-06-08 05:04:59 +08:00
|
|
|
remain += unit;
|
2020-02-04 07:56:13 +08:00
|
|
|
if (remain > buf_writer->buf_size) {
|
2019-06-08 05:04:59 +08:00
|
|
|
/* Flushes should have happened. */
|
|
|
|
assert_u64_eq(arg_store, arg, "Call "
|
|
|
|
"back argument didn't get through");
|
2020-02-04 07:56:13 +08:00
|
|
|
remain %= buf_writer->buf_size;
|
2019-06-08 05:04:59 +08:00
|
|
|
if (remain == 0) {
|
|
|
|
/* Last flush should be lazy. */
|
2020-02-04 07:56:13 +08:00
|
|
|
remain += buf_writer->buf_size;
|
2019-06-08 05:04:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_zu_eq(test_write_len + remain, i * unit,
|
|
|
|
"Incorrect length after writing %zu strings"
|
|
|
|
" of length %zu", i, unit);
|
|
|
|
}
|
2020-02-04 07:56:13 +08:00
|
|
|
buf_writer_flush(buf_writer);
|
|
|
|
assert_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_ptr_null(buf_writer.buf, "Buffer should be null");
|
|
|
|
write_cb_t *write_cb = buf_writer_get_write_cb(&buf_writer);
|
|
|
|
assert_ptr_eq(write_cb, test_write_cb, "Should use test_write_cb");
|
|
|
|
void *cbopaque = buf_writer_get_cbopaque(&buf_writer);
|
|
|
|
assert_ptr_eq(cbopaque, &arg, "Should use arg");
|
|
|
|
|
|
|
|
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);
|
|
|
|
write_cb(cbopaque, 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);
|
|
|
|
}
|
2020-01-24 07:00:01 +08:00
|
|
|
buf_writer_flush(&buf_writer);
|
2019-06-08 05:04:59 +08:00
|
|
|
assert_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);
|
|
|
|
}
|
|
|
|
}
|
2020-02-04 07:56:13 +08:00
|
|
|
buf_writer_terminate(tsdn, &buf_writer);
|
2019-06-08 05:04:59 +08:00
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
|
|
|
int
|
|
|
|
main(void) {
|
2020-02-04 07:56:13 +08:00
|
|
|
return test(
|
|
|
|
test_buf_write_static,
|
|
|
|
test_buf_write_dynamic,
|
|
|
|
test_buf_write_oom);
|
2019-06-08 05:04:59 +08:00
|
|
|
}
|