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