X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ffailtest%2Ffailtest.h;h=9af5669678f2295edccb5cbea4cb777016f40b8f;hp=4df286241d0ef35f8a271251861ae7d0f2c11ac7;hb=c438ec17d7b2efe76e56e5fc5ab88bd4a02735e8;hpb=e50b1a072279e2ecf461f379094ff1726a4c19e9 diff --git a/ccan/failtest/failtest.h b/ccan/failtest/failtest.h index 4df28624..9af56696 100644 --- a/ccan/failtest/failtest.h +++ b/ccan/failtest/failtest.h @@ -1,10 +1,15 @@ +/* Licensed under LGPL - see LICENSE file for details */ #ifndef CCAN_FAILTEST_H #define CCAN_FAILTEST_H #include "config.h" +#if HAVE_FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif #include #include #include #include +#include /** * failtest_init - initialize the failtest module @@ -42,6 +47,8 @@ enum failtest_call_type { FAILTEST_READ, FAILTEST_WRITE, FAILTEST_FCNTL, + FAILTEST_MMAP, + FAILTEST_LSEEK }; struct calloc_call { @@ -66,6 +73,10 @@ struct open_call { const char *pathname; int flags; mode_t mode; + bool always_save; + bool closed; + /* This is used for O_TRUNC opens on existing files. */ + struct contents_saved *saved; }; struct close_call { @@ -92,6 +103,9 @@ struct write_call { const void *buf; size_t count; off_t off; + bool is_pwrite; + struct failtest_call *opener; + struct contents_saved *saved; }; struct fcntl_call { @@ -105,6 +119,26 @@ struct fcntl_call { } arg; }; +struct mmap_call { + void *ret; + void *addr; + size_t length; + int prot; + int flags; + int fd; + off_t offset; + struct failtest_call *opener; + struct contents_saved *saved; +}; + +struct lseek_call { + ssize_t ret; + int fd; + off_t offset; + int whence; + off_t old_off; +}; + /** * struct failtest_call - description of a call redirected to failtest module * @type: the call type @@ -120,6 +154,8 @@ struct fcntl_call { * failtest_hook, failtest_exit_check */ struct failtest_call { + /* We're in the history list. */ + struct list_node list; enum failtest_call_type type; /* Where we were called from. */ const char *file; @@ -129,7 +165,12 @@ struct failtest_call { /* What we set errno to. */ int error; /* How do we clean this up? */ - void (*cleanup)(void *u); + void (*cleanup)(void *u, bool restore); + /* Should their program have cleaned up? */ + bool can_leak; + /* Backtrace of call chain. */ + void **backtrace; + unsigned int backtrace_num; /* The actual call data. */ union { struct calloc_call calloc; @@ -141,9 +182,14 @@ struct failtest_call { struct read_call read; struct write_call write; struct fcntl_call fcntl; + struct mmap_call mmap; + struct lseek_call lseek; } u; }; +/* This defines struct tlist_calls. */ +TLIST_TYPE(calls, struct failtest_call); + enum failtest_result { /* Yes try failing this call. */ FAIL_OK, @@ -156,7 +202,6 @@ enum failtest_result { /** * failtest_hook - whether a certain call should fail or not. * @history: the ordered history of all failtest calls. - * @num: the number of elements in @history (greater than 0) * * The default value of this hook is failtest_default_hook(), which returns * FAIL_OK (ie. yes, fail the call). @@ -166,25 +211,24 @@ enum failtest_result { * call. * * Example: - * static enum failtest_result dont_fail_alloc(struct failtest_call *hist, - * unsigned num) + * static enum failtest_result dont_fail_alloc(struct tlist_calls *history) * { - * if (hist[num-1].type == FAILTEST_MALLOC - * || hist[num-1].type == FAILTEST_CALLOC - * || hist[num-1].type == FAILTEST_REALLOC) + * struct failtest_call *call; + * call = tlist_tail(history, list); + * if (call->type == FAILTEST_MALLOC + * || call->type == FAILTEST_CALLOC + * || call->type == FAILTEST_REALLOC) * return FAIL_DONT_FAIL; * return FAIL_OK; * } * ... * failtest_hook = dont_fail_alloc; */ -extern enum failtest_result -(*failtest_hook)(struct failtest_call *history, unsigned num); +extern enum failtest_result (*failtest_hook)(struct tlist_calls *history); /** * failtest_exit_check - hook for additional checks on a failed child. * @history: the ordered history of all failtest calls. - * @num: the number of elements in @history (greater than 0) * * Your program might have additional checks to do on failure, such as * check that a file is not corrupted, or than an error message has been @@ -193,8 +237,17 @@ extern enum failtest_result * If this returns false, the path to this failure will be printed and the * overall test will fail. */ -extern bool (*failtest_exit_check)(struct failtest_call *history, - unsigned num); +extern bool (*failtest_exit_check)(struct tlist_calls *history); + +/** + * failtest_has_failed - determine if a failure has occurred. + * + * Sometimes you want to exit immediately if you've experienced an + * injected failure. This is useful when you have four separate tests + * in your test suite, and you don't want to do the next one if you've + * had a failure in a previous one. + */ +extern bool failtest_has_failed(void); /** * failtest_timeout_ms - how long to wait before killing child.