diff --git a/src/t_misc.c b/src/t_misc.c index 59d6260de716d2d78e61db02fe162e8c607e54e4..04ce96c1f6153de2b196be2dbacda55f8e6d9e23 100644 --- a/src/t_misc.c +++ b/src/t_misc.c @@ -30,41 +30,50 @@ static void test_tt_registry(void) { g_check_cmp_int32(h_get_token_type_number("com.upstandinghackers.test.unkown_token_type"), ==, 0); } -// perform a big allocation during parsing to trigger out-of-memory handling -static HParsedToken *act_big_alloc(const HParseResult *r, void *user) { - void *buf = h_arena_malloc(r->arena, 500*1024*1024); +// test out-of-memory handling with a selectively failing allocator +static void *fail_alloc(HAllocator *mm__, size_t size) { + if(size - 0xdead <= 0x30) // allow for overhead of arena link structure + return NULL; + return system_allocator.alloc(&system_allocator, size); +} +static void *fail_realloc(HAllocator *mm__, void *ptr, size_t size) { + return system_allocator.realloc(&system_allocator, ptr, size); +} +static void fail_free(HAllocator *mm__, void *ptr) { + return system_allocator.free(&system_allocator, ptr); +} +static HAllocator fail_allocator = {fail_alloc, fail_realloc, fail_free}; +static HParsedToken *act_oom(const HParseResult *r, void *user) { + void *buf = h_arena_malloc(r->arena, 0xdead); assert(buf != NULL); - g_test_message("Memory allocation was supposed to fail"); - return NULL; + return NULL; // succeed with null token } static void test_oom(void) { - HParser *p = h_action(h_ch('x'), act_big_alloc, NULL); + HParser *p = h_action(h_ch('x'), act_oom, NULL); // this should always fail, but never crash - struct rlimit bak, lim; - int i; - i = getrlimit(RLIMIT_DATA, &bak); - assert(i == 0); - lim.rlim_cur = 499*1024*1024; // never enough - if(lim.rlim_cur > bak.rlim_max) - lim.rlim_cur = bak.rlim_max; - lim.rlim_max = bak.rlim_max; - i = setrlimit(RLIMIT_DATA, &lim); - assert(i == 0); - - g_check_parse_failed(p, PB_PACKRAT, "x",1); - g_check_parse_failed(p, PB_REGULAR, "x",1); - g_check_parse_failed(p, PB_LLk, "x",1); - g_check_parse_failed(p, PB_LALR, "x",1); - g_check_parse_failed(p, PB_GLR, "x",1); - - //g_check_parse_chunks_failed(p, PB_REGULAR, "",0, "x",1); - g_check_parse_chunks_failed(p, PB_LLk, "",0, "x",1); - g_check_parse_chunks_failed(p, PB_LALR, "",0, "x",1); - //g_check_parse_chunks_failed(p, PB_GLR, "",0, "x",1); + // sanity-check: parses should succeed with the normal allocator... + g_check_parse_ok(p, PB_PACKRAT, "x",1); + g_check_parse_ok(p, PB_REGULAR, "x",1); + g_check_parse_ok(p, PB_LLk, "x",1); + g_check_parse_ok(p, PB_LALR, "x",1); + g_check_parse_ok(p, PB_GLR, "x",1); + //XXX g_check_parse_chunks_ok(p, PB_REGULAR, "",0, "x",1); + g_check_parse_chunks_ok(p, PB_LLk, "",0, "x",1); + g_check_parse_chunks_ok(p, PB_LALR, "",0, "x",1); + //XXX g_check_parse_chunks_ok(p, PB_GLR, "",0, "x",1); - i = setrlimit(RLIMIT_DATA, &bak); - assert(i == 0); + // ...and fail gracefully with the broken one + HAllocator *mm__ = &fail_allocator; + g_check_parse_failed__m(mm__, p, PB_PACKRAT, "x",1); + g_check_parse_failed__m(mm__, p, PB_REGULAR, "x",1); + g_check_parse_failed__m(mm__, p, PB_LLk, "x",1); + g_check_parse_failed__m(mm__, p, PB_LALR, "x",1); + g_check_parse_failed__m(mm__, p, PB_GLR, "x",1); + //XXX g_check_parse_chunks_failed__m(mm__, p, PB_REGULAR, "",0, "x",1); + g_check_parse_chunks_failed__m(mm__, p, PB_LLk, "",0, "x",1); + g_check_parse_chunks_failed__m(mm__, p, PB_LALR, "",0, "x",1); + //XXX g_check_parse_chunks_failed__m(mm__, p, PB_GLR, "",0, "x",1); } void register_misc_tests(void) {