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