diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-02-22 14:59:32 +1030 |
---|---|---|
committer | Amitay Isaacs <amitay@gmail.com> | 2012-03-07 13:16:16 +1100 |
commit | 361f3ea9ee577c5a3e2fed687a0b417b257c31de (patch) | |
tree | 6d356c3aa64317c609ff4e208be76e18996a55f8 /lib/ccan/failtest/failtest.h | |
parent | 4f5412dda687c3ff76b426842bf284d01d56a997 (diff) | |
download | samba-361f3ea9ee577c5a3e2fed687a0b417b257c31de.tar.gz samba-361f3ea9ee577c5a3e2fed687a0b417b257c31de.tar.bz2 samba-361f3ea9ee577c5a3e2fed687a0b417b257c31de.zip |
lib/ccan: import failtest and required ccan modules for TDB2 unit tests.
New modules: failtest, list, time, read_write_all and tlist.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/ccan/failtest/failtest.h')
-rw-r--r-- | lib/ccan/failtest/failtest.h | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/lib/ccan/failtest/failtest.h b/lib/ccan/failtest/failtest.h new file mode 100644 index 0000000000..9af5669678 --- /dev/null +++ b/lib/ccan/failtest/failtest.h @@ -0,0 +1,258 @@ +/* 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 <sys/types.h> +#include <stdbool.h> +#include <fcntl.h> +#include <ccan/compiler/compiler.h> +#include <ccan/tlist/tlist.h> + +/** + * failtest_init - initialize the failtest module + * @argc: the number of commandline arguments + * @argv: the commandline argument array + * + * This initializes the module, and in particular if argv[1] is "--failpath=" + * then it ensures that failures follow that pattern. This allows easy + * debugging of complex failure paths. + */ +void failtest_init(int argc, char *argv[]); + +/** + * failtest_exit - clean up and exit the test + * @status: the status (usually exit_status() from ccan/tap). + * + * This cleans up and changes to files made in this child, and exits the test. + * It also calls your failtest_default_hook, if any. + * + * A child which does not exit via failtest_exit() will cause the overall test + * to fail. + */ +void NORETURN failtest_exit(int status); + +/** + * enum failtest_call_type - discriminator for failtest_call.u + */ +enum failtest_call_type { + FAILTEST_MALLOC, + FAILTEST_CALLOC, + FAILTEST_REALLOC, + FAILTEST_OPEN, + FAILTEST_CLOSE, + FAILTEST_PIPE, + FAILTEST_READ, + FAILTEST_WRITE, + FAILTEST_FCNTL, + FAILTEST_MMAP, + FAILTEST_LSEEK +}; + +struct calloc_call { + void *ret; + size_t nmemb; + size_t size; +}; + +struct malloc_call { + void *ret; + size_t size; +}; + +struct realloc_call { + void *ret; + void *ptr; + size_t size; +}; + +struct open_call { + int ret; + 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 { + int fd; +}; + +struct pipe_call { + int ret; + int fds[2]; + bool closed[2]; +}; + +struct read_call { + ssize_t ret; + off_t off; + int fd; + void *buf; + size_t count; +}; + +struct write_call { + ssize_t ret; + int fd; + const void *buf; + size_t count; + off_t off; + bool is_pwrite; + struct failtest_call *opener; + struct contents_saved *saved; +}; + +struct fcntl_call { + int ret; + int fd; + int cmd; + union { + struct flock fl; + long l; + int i; + } 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 + * @file: the filename of the caller + * @line: the line number of the caller + * @fail: did this call fail + * @error: the errno (if any) + * @u: the union of call data + * + * This structure is used to represent the ordered history of calls. + * + * See Also: + * 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; + unsigned int line; + /* Did we fail? */ + bool fail; + /* What we set errno to. */ + int error; + /* How do we clean this up? */ + 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; + struct malloc_call malloc; + struct realloc_call realloc; + struct open_call open; + struct close_call close; + struct pipe_call pipe; + 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, + /* No, don't try failing this call. */ + FAIL_DONT_FAIL, + /* Try failing this call but don't go too far down that path. */ + FAIL_PROBE, +}; + +/** + * failtest_hook - whether a certain call should fail or not. + * @history: the ordered history of all failtest calls. + * + * The default value of this hook is failtest_default_hook(), which returns + * FAIL_OK (ie. yes, fail the call). + * + * You can override it, and avoid failing certain calls. The parameters + * of the call (but not the return value(s)) will be filled in for the last + * call. + * + * Example: + * static enum failtest_result dont_fail_alloc(struct tlist_calls *history) + * { + * 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 tlist_calls *history); + +/** + * failtest_exit_check - hook for additional checks on a failed child. + * @history: the ordered history of all failtest calls. + * + * 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 + * logged. + * + * If this returns false, the path to this failure will be printed and the + * overall test will fail. + */ +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. + * + * Default is 20,000 (20 seconds). + */ +extern unsigned int failtest_timeout_ms; +#endif /* CCAN_FAILTEST_H */ |