From 97f93f50918abc3578bf868f0e1207eeb6ab1c83 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Jan 2011 11:08:34 +1030 Subject: [PATCH 1/1] failtest: failtest_restore.h as an antidote to function overload. This makes some cases simpler, where you no longer want malloc etc. to fail. --- ccan/failtest/_info | 3 ++- ccan/failtest/failtest.c | 13 +++++++++++++ ccan/failtest/failtest_undo.h | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 ccan/failtest/failtest_undo.h diff --git a/ccan/failtest/_info b/ccan/failtest/_info index 73aa6a2d..4b43246f 100644 --- a/ccan/failtest/_info +++ b/ccan/failtest/_info @@ -8,7 +8,8 @@ * The failtest module overrides various standard functions, and forks * your unit test at those points to test failure paths. The failing * child are expected to fail (eg. when malloc fails), but should not - * leak memory or crash. + * leak memory or crash. After including failtest_override.h, you can + * include failtest_restore.h to return to non-failing versions. * * The unit test is a normal CCAN tap-style test, except it should * start by calling failtest_init() and end by calling diff --git a/ccan/failtest/failtest.c b/ccan/failtest/failtest.c index 092d2091..1127e4fd 100644 --- a/ccan/failtest/failtest.c +++ b/ccan/failtest/failtest.c @@ -66,12 +66,19 @@ static unsigned int fd_orig_num = 0; static const char info_to_arg[] = "mceoprw"; +/* Dummy call used for failtest_undo wrappers. */ +static struct failtest_call unrecorded_call; + static struct failtest_call *add_history_(enum failtest_call_type type, const char *file, unsigned int line, const void *elem, size_t elem_size) { + /* NULL file is how we suppress failure. */ + if (!file) + return &unrecorded_call; + history = realloc(history, (history_num + 1) * sizeof(*history)); history[history_num].type = type; history[history_num].file = file; @@ -172,6 +179,9 @@ static bool should_fail(struct failtest_call *call) char *out = NULL; size_t outlen = 0; + if (call == &unrecorded_call) + return false; + if (failpath) { if (tolower(*failpath) != info_to_arg[call->type]) errx(1, "Failpath expected '%c' got '%c'\n", @@ -341,6 +351,9 @@ int failtest_open(const char *pathname, int flags, va_end(ap); } p = add_history(FAILTEST_OPEN, file, line, &call); + /* Avoid memory leak! */ + if (p == &unrecorded_call) + free((char *)call.pathname); if (should_fail(p)) { p->u.open.ret = -1; /* FIXME: Play with error codes? */ diff --git a/ccan/failtest/failtest_undo.h b/ccan/failtest/failtest_undo.h new file mode 100644 index 00000000..17bf3566 --- /dev/null +++ b/ccan/failtest/failtest_undo.h @@ -0,0 +1,36 @@ +#ifndef CCAN_FAILTEST_RESTORE_H +#define CCAN_FAILTEST_RESTORE_H +/* This file undoes the effect of failtest_override.h. */ + +#undef calloc +#define calloc(nmemb, size) \ + failtest_calloc((nmemb), (size), NULL, 0) + +#undef malloc +#define malloc(size) \ + failtest_malloc((size), NULL, 0) + +#undef realloc +#define realloc(ptr, size) \ + failtest_realloc((ptr), (size), NULL, 0) + +#undef open +#define open(pathname, flags, ...) \ + failtest_open((pathname), (flags), NULL, 0, __VA_ARGS__) + +#undef pipe +#define pipe(pipefd) \ + failtest_pipe((pipefd), NULL, 0) + +#undef read +#define read(fd, buf, count) \ + failtest_read((fd), (buf), (count), NULL, 0) + +#undef write +#define write(fd, buf, count) \ + failtest_write((fd), (buf), (count), NULL, 0) + +#undef close +#define close(fd) failtest_close(fd) + +#endif /* CCAN_FAILTEST_RESTORE_H */ -- 2.39.2