mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-04-14 14:41:42 +03:00
Add unit tests for conf parsing and its helpers
This commit is contained in:
parent
ad726adf75
commit
86b7219213
7 changed files with 354 additions and 2 deletions
|
|
@ -216,6 +216,11 @@ TESTS_UNIT := \
|
|||
$(srcroot)test/unit/buf_writer.c \
|
||||
$(srcroot)test/unit/cache_bin.c \
|
||||
$(srcroot)test/unit/ckh.c \
|
||||
$(srcroot)test/unit/conf.c \
|
||||
$(srcroot)test/unit/conf_init_0.c \
|
||||
$(srcroot)test/unit/conf_init_1.c \
|
||||
$(srcroot)test/unit/conf_init_confirm.c \
|
||||
$(srcroot)test/unit/conf_parse.c \
|
||||
$(srcroot)test/unit/counter.c \
|
||||
$(srcroot)test/unit/decay.c \
|
||||
$(srcroot)test/unit/div.c \
|
||||
|
|
|
|||
113
test/unit/conf.c
Normal file
113
test/unit/conf.c
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
#include "jemalloc/internal/conf.h"
|
||||
|
||||
TEST_BEGIN(test_conf_next_simple) {
|
||||
const char *opts = "key:value";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
|
||||
had_conf_error = false;
|
||||
bool end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_false(end, "Should not be at end");
|
||||
expect_zu_eq(klen, 3, "Key length should be 3");
|
||||
expect_false(strncmp(k, "key", klen), "Key should be \"key\"");
|
||||
expect_zu_eq(vlen, 5, "Value length should be 5");
|
||||
expect_false(strncmp(v, "value", vlen), "Value should be \"value\"");
|
||||
expect_false(had_conf_error, "Should not have had an error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_next_multi) {
|
||||
const char *opts = "k1:v1,k2:v2";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
bool end;
|
||||
|
||||
had_conf_error = false;
|
||||
|
||||
end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_false(end, "Should not be at end after first pair");
|
||||
expect_zu_eq(klen, 2, "First key length should be 2");
|
||||
expect_false(strncmp(k, "k1", klen), "First key should be \"k1\"");
|
||||
expect_zu_eq(vlen, 2, "First value length should be 2");
|
||||
expect_false(strncmp(v, "v1", vlen), "First value should be \"v1\"");
|
||||
|
||||
end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_false(end, "Should not be at end after second pair");
|
||||
expect_zu_eq(klen, 2, "Second key length should be 2");
|
||||
expect_false(strncmp(k, "k2", klen), "Second key should be \"k2\"");
|
||||
expect_zu_eq(vlen, 2, "Second value length should be 2");
|
||||
expect_false(strncmp(v, "v2", vlen), "Second value should be \"v2\"");
|
||||
|
||||
expect_false(had_conf_error, "Should not have had an error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_next_empty) {
|
||||
const char *opts = "";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
|
||||
had_conf_error = false;
|
||||
bool end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_true(end, "Empty string should return true (end)");
|
||||
expect_false(had_conf_error, "Empty string should not set error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_next_missing_value) {
|
||||
const char *opts = "key_only";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
|
||||
had_conf_error = false;
|
||||
bool end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_true(end, "Key without value should return true (end)");
|
||||
expect_true(had_conf_error, "Key without value should set error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_next_malformed) {
|
||||
const char *opts = "bad!key:val";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
|
||||
had_conf_error = false;
|
||||
bool end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_true(end, "Malformed key should return true (end)");
|
||||
expect_true(had_conf_error, "Malformed key should set error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_next_trailing_comma) {
|
||||
const char *opts = "k:v,";
|
||||
const char *k;
|
||||
size_t klen;
|
||||
const char *v;
|
||||
size_t vlen;
|
||||
|
||||
had_conf_error = false;
|
||||
bool end = conf_next(&opts, &k, &klen, &v, &vlen);
|
||||
expect_false(end, "Should parse the first pair successfully");
|
||||
expect_true(had_conf_error,
|
||||
"Trailing comma should set error");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_conf_next_simple, test_conf_next_multi,
|
||||
test_conf_next_empty, test_conf_next_missing_value,
|
||||
test_conf_next_malformed, test_conf_next_trailing_comma);
|
||||
}
|
||||
22
test/unit/conf_init_0.c
Normal file
22
test/unit/conf_init_0.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
TEST_BEGIN(test_default_dirty_decay_ms) {
|
||||
#ifdef _WIN32
|
||||
test_skip("not supported on win32");
|
||||
#endif
|
||||
|
||||
ssize_t dirty_decay_ms;
|
||||
size_t sz = sizeof(dirty_decay_ms);
|
||||
|
||||
int err = mallctl("opt.dirty_decay_ms", &dirty_decay_ms, &sz, NULL, 0);
|
||||
assert_d_eq(err, 0, "Unexpected mallctl failure");
|
||||
expect_zd_eq(dirty_decay_ms, 10000,
|
||||
"dirty_decay_ms should be the default (10000)"
|
||||
" when no global variables are set");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_default_dirty_decay_ms);
|
||||
}
|
||||
23
test/unit/conf_init_1.c
Normal file
23
test/unit/conf_init_1.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
const char *malloc_conf = "dirty_decay_ms:1234";
|
||||
|
||||
TEST_BEGIN(test_malloc_conf_dirty_decay_ms) {
|
||||
#ifdef _WIN32
|
||||
test_skip("not supported on win32");
|
||||
#endif
|
||||
|
||||
ssize_t dirty_decay_ms;
|
||||
size_t sz = sizeof(dirty_decay_ms);
|
||||
|
||||
int err = mallctl("opt.dirty_decay_ms", &dirty_decay_ms, &sz, NULL, 0);
|
||||
assert_d_eq(err, 0, "Unexpected mallctl failure");
|
||||
expect_zd_eq(dirty_decay_ms, 1234,
|
||||
"dirty_decay_ms should be 1234 (set via malloc_conf)");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_malloc_conf_dirty_decay_ms);
|
||||
}
|
||||
39
test/unit/conf_init_confirm.c
Normal file
39
test/unit/conf_init_confirm.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
const char *malloc_conf = "dirty_decay_ms:1234,confirm_conf:true";
|
||||
|
||||
TEST_BEGIN(test_confirm_conf_two_pass) {
|
||||
#ifdef _WIN32
|
||||
test_skip("not supported on win32");
|
||||
#endif
|
||||
|
||||
bool confirm_conf;
|
||||
size_t sz = sizeof(confirm_conf);
|
||||
|
||||
int err = mallctl("opt.confirm_conf", &confirm_conf, &sz, NULL, 0);
|
||||
assert_d_eq(err, 0, "Unexpected mallctl failure");
|
||||
expect_true(confirm_conf,
|
||||
"confirm_conf should be true (processed in pass 1)");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_option_applied_in_second_pass) {
|
||||
#ifdef _WIN32
|
||||
test_skip("not supported on win32");
|
||||
#endif
|
||||
|
||||
ssize_t dirty_decay_ms;
|
||||
size_t sz = sizeof(dirty_decay_ms);
|
||||
|
||||
int err = mallctl("opt.dirty_decay_ms", &dirty_decay_ms, &sz, NULL, 0);
|
||||
assert_d_eq(err, 0, "Unexpected mallctl failure");
|
||||
expect_zd_eq(dirty_decay_ms, 1234,
|
||||
"dirty_decay_ms should be 1234 (processed in pass 2)");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_confirm_conf_two_pass,
|
||||
test_conf_option_applied_in_second_pass);
|
||||
}
|
||||
130
test/unit/conf_parse.c
Normal file
130
test/unit/conf_parse.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
#include "jemalloc/internal/conf.h"
|
||||
|
||||
TEST_BEGIN(test_conf_handle_bool_true) {
|
||||
bool result = false;
|
||||
bool err = conf_handle_bool("true", sizeof("true") - 1, &result);
|
||||
expect_false(err, "conf_handle_bool should succeed for \"true\"");
|
||||
expect_true(result, "result should be true");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_bool_false) {
|
||||
bool result = true;
|
||||
bool err = conf_handle_bool("false", sizeof("false") - 1, &result);
|
||||
expect_false(err, "conf_handle_bool should succeed for \"false\"");
|
||||
expect_false(result, "result should be false");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_bool_invalid) {
|
||||
bool result = false;
|
||||
bool err = conf_handle_bool("yes", sizeof("yes") - 1, &result);
|
||||
expect_true(err, "conf_handle_bool should fail for \"yes\"");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_unsigned_in_range) {
|
||||
uintmax_t result = 0;
|
||||
bool err = conf_handle_unsigned("100", sizeof("100") - 1,
|
||||
1, 2048, true, true, true, &result);
|
||||
expect_false(err, "Should succeed for in-range value");
|
||||
expect_u64_eq((uint64_t)result, 100, "result should be 100");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_unsigned_clip_max) {
|
||||
uintmax_t result = 0;
|
||||
bool err = conf_handle_unsigned("9999", sizeof("9999") - 1,
|
||||
1, 2048, true, true, true, &result);
|
||||
expect_false(err, "Should succeed with clipping");
|
||||
expect_u64_eq((uint64_t)result, 2048,
|
||||
"result should be clipped to max 2048");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_unsigned_clip_min) {
|
||||
uintmax_t result = 0;
|
||||
bool err = conf_handle_unsigned("0", sizeof("0") - 1,
|
||||
1, 2048, true, true, true, &result);
|
||||
expect_false(err, "Should succeed with clipping");
|
||||
expect_u64_eq((uint64_t)result, 1,
|
||||
"result should be clipped to min 1");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_unsigned_no_clip_reject) {
|
||||
uintmax_t result = 0;
|
||||
bool err = conf_handle_unsigned("9999", sizeof("9999") - 1,
|
||||
1, 2048, true, true, false, &result);
|
||||
expect_true(err, "Should fail for out-of-range value without clip");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_unsigned_invalid) {
|
||||
uintmax_t result = 0;
|
||||
bool err = conf_handle_unsigned("abc", sizeof("abc") - 1,
|
||||
1, 2048, true, true, true, &result);
|
||||
expect_true(err, "Should fail for non-numeric input");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_signed_valid) {
|
||||
intmax_t result = 0;
|
||||
bool err = conf_handle_signed("5000", sizeof("5000") - 1,
|
||||
-1, INTMAX_MAX, true, false, false, &result);
|
||||
expect_false(err, "Should succeed for valid value");
|
||||
expect_d64_eq((int64_t)result, 5000, "result should be 5000");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_signed_negative) {
|
||||
intmax_t result = 0;
|
||||
bool err = conf_handle_signed("-1", sizeof("-1") - 1,
|
||||
-1, INTMAX_MAX, true, false, false, &result);
|
||||
expect_false(err, "Should succeed for -1");
|
||||
expect_d64_eq((int64_t)result, -1, "result should be -1");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_signed_out_of_range) {
|
||||
intmax_t result = 0;
|
||||
bool err = conf_handle_signed("5000", sizeof("5000") - 1,
|
||||
-1, 4999, true, true, false, &result);
|
||||
expect_true(err, "Should fail for out-of-range value");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_conf_handle_char_p) {
|
||||
char buf[8];
|
||||
bool err;
|
||||
|
||||
/* Normal copy. */
|
||||
err = conf_handle_char_p("hello", sizeof("hello") - 1, buf, sizeof(buf));
|
||||
expect_false(err, "Should succeed");
|
||||
expect_str_eq(buf, "hello", "Should copy string");
|
||||
|
||||
/* Truncation. */
|
||||
err = conf_handle_char_p("longstring", sizeof("longstring") - 1,
|
||||
buf, sizeof(buf));
|
||||
expect_false(err, "Should succeed even when truncating");
|
||||
expect_str_eq(buf, "longstr", "Should truncate to dest_sz - 1");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_conf_handle_bool_true,
|
||||
test_conf_handle_bool_false,
|
||||
test_conf_handle_bool_invalid,
|
||||
test_conf_handle_unsigned_in_range,
|
||||
test_conf_handle_unsigned_clip_max,
|
||||
test_conf_handle_unsigned_clip_min,
|
||||
test_conf_handle_unsigned_no_clip_reject,
|
||||
test_conf_handle_unsigned_invalid,
|
||||
test_conf_handle_signed_valid,
|
||||
test_conf_handle_signed_negative,
|
||||
test_conf_handle_signed_out_of_range,
|
||||
test_conf_handle_char_p);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "test/jemalloc_test.h"
|
||||
|
||||
const char *malloc_conf = "dirty_decay_ms:1000";
|
||||
const char *malloc_conf = "dirty_decay_ms:1000,muzzy_decay_ms:2000";
|
||||
const char *malloc_conf_2_conf_harder = "dirty_decay_ms:1234";
|
||||
|
||||
TEST_BEGIN(test_malloc_conf_2) {
|
||||
|
|
@ -49,7 +49,27 @@ TEST_BEGIN(test_mallctl_global_var) {
|
|||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_non_conflicting_var) {
|
||||
#ifdef _WIN32
|
||||
bool windows = true;
|
||||
#else
|
||||
bool windows = false;
|
||||
#endif
|
||||
/* Windows doesn't support weak symbol linker trickery. */
|
||||
test_skip_if(windows);
|
||||
|
||||
ssize_t muzzy_decay_ms;
|
||||
size_t sz = sizeof(muzzy_decay_ms);
|
||||
|
||||
int err = mallctl("opt.muzzy_decay_ms", &muzzy_decay_ms, &sz, NULL, 0);
|
||||
assert_d_eq(err, 0, "Unexpected mallctl failure");
|
||||
expect_zd_eq(muzzy_decay_ms, 2000,
|
||||
"Non-conflicting option from malloc_conf should pass through");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(test_malloc_conf_2, test_mallctl_global_var);
|
||||
return test(test_malloc_conf_2, test_mallctl_global_var,
|
||||
test_non_conflicting_var);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue