X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftal%2Ftest%2Frun-allocfail.c;fp=ccan%2Ftal%2Ftest%2Frun-allocfail.c;h=dd6abff4dc6f7a0678bb3055305330382516143e;hb=0e34459a02e2615f50bac2767c7dce6632470946;hp=0000000000000000000000000000000000000000;hpb=33527c60ba3c5c72ed31fbb064c38db2b3d2c733;p=ccan diff --git a/ccan/tal/test/run-allocfail.c b/ccan/tal/test/run-allocfail.c new file mode 100644 index 00000000..dd6abff4 --- /dev/null +++ b/ccan/tal/test/run-allocfail.c @@ -0,0 +1,126 @@ +#include +#include +#include + +static int alloc_count, when_to_fail, err_count; +static bool stealing; + +static void *failing_alloc(size_t len) +{ + if (alloc_count++ == when_to_fail) + return NULL; + /* once we've failed once, it shouldn't ask again (steal can though). */ + assert(stealing || alloc_count <= when_to_fail); + + return malloc(len); +} + +static void nofail_on_error(const char *msg) +{ + diag("ERROR: %s", msg); + err_count++; +} + +static void destroy_p(void *p) +{ +} + +int main(void) +{ + void *p, *c1, *c2; + bool success; + + plan_tests(21); + + tal_set_backend(failing_alloc, NULL, NULL, nofail_on_error); + + /* Fail at each possible point in an allocation. */ + when_to_fail = err_count = 0; + do { + alloc_count = 0; + p = tal(NULL, char); + when_to_fail++; + } while (!p); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + /* Do it again. */ + when_to_fail = err_count = 0; + do { + alloc_count = 0; + c1 = tal(p, char); + when_to_fail++; + } while (!c1); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + /* Now for second child. */ + when_to_fail = err_count = 0; + do { + alloc_count = 0; + c2 = tal(p, char); + when_to_fail++; + } while (!c2); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + /* Note: adding a child will fall through if group alloc fails. */ + ok1 (err_count == when_to_fail - 1 || err_count == when_to_fail); + + /* Now while adding a destructor. */ + when_to_fail = err_count = 0; + do { + alloc_count = 0; + success = tal_add_destructor(p, destroy_p); + when_to_fail++; + } while (!success); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + /* Now while adding a name. */ + when_to_fail = err_count = 0; + do { + const char name[] = "some name"; + alloc_count = 0; + success = tal_set_name(p, name); + when_to_fail++; + } while (!success); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + /* Now while stealing. */ + stealing = true; + when_to_fail = err_count = 0; + do { + alloc_count = 0; + success = tal_steal(c2, c1) != NULL; + when_to_fail++; + } while (!success); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + /* Now stealing with more children (more coverage). */ + when_to_fail = 1000; + (void)tal(p, char); + c1 = tal(p, char); + c2 = tal(p, char); + (void)tal(p, char); + + /* Now steal again. */ + when_to_fail = err_count = 0; + do { + alloc_count = 0; + success = tal_steal(c2, c1) != NULL; + when_to_fail++; + } while (!success); + ok1(alloc_count >= 1); + ok1(when_to_fail > 1); + ok1(err_count == when_to_fail - 1); + + tal_free(p); + return exit_status(); +}