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