Home | History | Annotate | Line # | Download | only in cpp
      1 #include <stdio.h>
      2 
      3 #include "test/jemalloc_test.h"
      4 
      5 /*
      6  * We can't test C++ in unit tests.  In order to intercept abort, use a secret
      7  * safety check abort hook in integration tests.
      8  */
      9 typedef void (*abort_hook_t)(const char *message);
     10 bool fake_abort_called;
     11 void fake_abort(const char *message) {
     12 	if (strcmp(message, "<jemalloc>: Allocation failed and "
     13 	    "opt.experimental_infallible_new is true. Aborting.\n") != 0) {
     14 		abort();
     15 	}
     16 	fake_abort_called = true;
     17 }
     18 
     19 static bool
     20 own_operator_new(void) {
     21 	uint64_t before, after;
     22 	size_t sz = sizeof(before);
     23 
     24 	/* thread.allocated is always available, even w/o config_stats. */
     25 	expect_d_eq(mallctl("thread.allocated", (void *)&before, &sz, NULL, 0),
     26 	    0, "Unexpected mallctl failure reading stats");
     27 	void *volatile ptr = ::operator new((size_t)8);
     28 	expect_ptr_not_null(ptr, "Unexpected allocation failure");
     29 	expect_d_eq(mallctl("thread.allocated", (void *)&after, &sz, NULL, 0),
     30 	    0, "Unexpected mallctl failure reading stats");
     31 
     32 	return (after != before);
     33 }
     34 
     35 TEST_BEGIN(test_failing_alloc) {
     36 	abort_hook_t abort_hook = &fake_abort;
     37 	expect_d_eq(mallctl("experimental.hooks.safety_check_abort", NULL, NULL,
     38 	    (void *)&abort_hook, sizeof(abort_hook)), 0,
     39 	    "Unexpected mallctl failure setting abort hook");
     40 
     41 	/*
     42 	 * Not owning operator new is only expected to happen on MinGW which
     43 	 * does not support operator new / delete replacement.
     44 	 */
     45 #ifdef _WIN32
     46 	test_skip_if(!own_operator_new());
     47 #else
     48 	expect_true(own_operator_new(), "No operator new overload");
     49 #endif
     50 	void *volatile ptr = (void *)1;
     51 	try {
     52 		/* Too big of an allocation to succeed. */
     53 		ptr = ::operator new((size_t)-1);
     54 	} catch (...) {
     55 		abort();
     56 	}
     57 	expect_ptr_null(ptr, "Allocation should have failed");
     58 	expect_b_eq(fake_abort_called, true, "Abort hook not invoked");
     59 }
     60 TEST_END
     61 
     62 int
     63 main(void) {
     64 	return test(
     65 	    test_failing_alloc);
     66 }
     67 
     68