]> git.ozlabs.org Git - ccan/blob - ccan/failtest/failtest.h
21bc9f7c59e342fd12dec4140314b252d364763c
[ccan] / ccan / failtest / failtest.h
1 #ifndef CCAN_FAILTEST_H
2 #define CCAN_FAILTEST_H
3 #include <sys/types.h>
4 #include <stdbool.h>
5 #include <fcntl.h>
6 #include <ccan/compiler/compiler.h>
7
8 /**
9  * failtest_init - initialize the failtest module
10  * @argc: the number of commandline arguments
11  * @argv: the commandline argument array
12  *
13  * This initializes the module, and in particular if argv[1] is "--failpath="
14  * then it ensures that failures follow that pattern.  This allows easy
15  * debugging of complex failure paths.
16  */
17 void failtest_init(int argc, char *argv[]);
18
19 /**
20  * failtest_exit - clean up and exit the test
21  * @status: the status (usually exit_status() from ccan/tap).
22  *
23  * This cleans up and changes to files made in this child, and exits the test.
24  * It also calls your failtest_default_hook, if any.
25  *
26  * A child which does not exit via failtest_exit() will cause the overall test
27  * to fail.
28  */
29 void NORETURN failtest_exit(int status);
30
31 /**
32  * enum failtest_call_type - discriminator for failtest_call.u
33  */
34 enum failtest_call_type {
35         FAILTEST_MALLOC,
36         FAILTEST_CALLOC,
37         FAILTEST_REALLOC,
38         FAILTEST_OPEN,
39         FAILTEST_PIPE,
40         FAILTEST_READ,
41         FAILTEST_WRITE,
42         FAILTEST_FCNTL,
43 };
44
45 struct calloc_call {
46         void *ret;
47         size_t nmemb;
48         size_t size;
49 };
50
51 struct malloc_call {
52         void *ret;
53         size_t size;
54 };
55
56 struct realloc_call {
57         void *ret;
58         void *ptr;
59         size_t size;
60 };
61
62 struct open_call {
63         int ret;
64         const char *pathname;
65         int flags;
66         mode_t mode;
67         int dup_fd;
68 };
69
70 struct pipe_call {
71         int ret;
72         int fds[2];
73         bool closed[2];
74 };
75
76 struct read_call {
77         ssize_t ret;
78         off_t off;
79         int fd;
80         void *buf;
81         size_t count;
82 };
83
84 struct write_call {
85         ssize_t ret;
86         int fd;
87         const void *buf;
88         size_t count;
89         off_t off;
90         off_t old_filelen;
91         off_t saved_len;
92         void *saved_contents;
93         int dup_fd;
94 };
95
96 struct fcntl_call {
97         int ret;
98         int fd;
99         int cmd;
100         union {
101                 struct flock fl;
102                 long l;
103                 int i;
104         } arg;
105 };
106
107 /**
108  * struct failtest_call - description of a call redirected to failtest module
109  * @type: the call type
110  * @file: the filename of the caller
111  * @line: the line number of the caller
112  * @fail: did this call fail
113  * @error: the errno (if any)
114  * @u: the union of call data
115  *
116  * This structure is used to represent the ordered history of calls.
117  *
118  * See Also:
119  *      failtest_hook, failtest_exit_check
120  */
121 struct failtest_call {
122         enum failtest_call_type type;
123         /* Where we were called from. */
124         const char *file;
125         unsigned int line;
126         /* Did we fail? */
127         bool fail;
128         /* What we set errno to. */
129         int error;
130         /* How do we clean this up? */
131         void (*cleanup)(void *u);
132         /* The actual call data. */
133         union {
134                 struct calloc_call calloc;
135                 struct malloc_call malloc;
136                 struct realloc_call realloc;
137                 struct open_call open;
138                 struct pipe_call pipe;
139                 struct read_call read;
140                 struct write_call write;
141                 struct fcntl_call fcntl;
142         } u;
143 };
144
145 /**
146  * failtest_hook - whether a certain call should fail or not.
147  * @history: the ordered history of all failtest calls.
148  * @num: the number of elements in @history (greater than 0)
149  *
150  * The default value of this hook is failtest_default_hook(), which returns
151  * true (ie. yes, fail the call).
152  *
153  * You can override it, and avoid failing certain calls.  The parameters
154  * of the call (but not the return value(s)) will be filled in for the last
155  * call.
156  *
157  * Example:
158  *      static bool dont_fail_allocations(struct failtest_call *history,
159  *                                        unsigned num)
160  *      {
161  *              return history[num-1].type != FAILTEST_MALLOC
162  *                      && history[num-1].type != FAILTEST_CALLOC
163  *                      && history[num-1].type != FAILTEST_REALLOC;
164  *      }
165  *      ...
166  *              failtest_hook = dont_fail_allocations;
167  */
168 extern bool (*failtest_hook)(struct failtest_call *history, unsigned num);
169
170 /**
171  * failtest_exit_check - hook for additional checks on a failed child.
172  * @history: the ordered history of all failtest calls.
173  * @num: the number of elements in @history (greater than 0)
174  *
175  * Your program might have additional checks to do on failure, such as
176  * check that a file is not corrupted, or than an error message has been
177  * logged.
178  *
179  * If this returns false, the path to this failure will be printed and the
180  * overall test will fail.
181  */
182 extern bool (*failtest_exit_check)(struct failtest_call *history,
183                                    unsigned num);
184
185 /* This usually fails the call. */
186 bool failtest_default_hook(struct failtest_call *history, unsigned num);
187
188 /**
189  * failtest_timeout_ms - how long to wait before killing child.
190  *
191  * Default is 20,000 (20 seconds).
192  */
193 extern unsigned int failtest_timeout_ms;
194 #endif /* CCAN_FAILTEST_H */