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