* 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
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;
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",
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? */
--- /dev/null
+#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 */