]> git.ozlabs.org Git - ccan/blob - ccan/failtest/failtest.h
failtest: internally eliminate duplicate calls.
[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         /* Backtrace of call chain. */
141         void **backtrace;
142         unsigned int backtrace_num;
143         /* The actual call data. */
144         union {
145                 struct calloc_call calloc;
146                 struct malloc_call malloc;
147                 struct realloc_call realloc;
148                 struct open_call open;
149                 struct close_call close;
150                 struct pipe_call pipe;
151                 struct read_call read;
152                 struct write_call write;
153                 struct fcntl_call fcntl;
154         } u;
155 };
156
157 /* This defines struct tlist_calls. */
158 TLIST_TYPE(calls, struct failtest_call);
159
160 enum failtest_result {
161         /* Yes try failing this call. */
162         FAIL_OK,
163         /* No, don't try failing this call. */
164         FAIL_DONT_FAIL,
165         /* Try failing this call but don't go too far down that path. */
166         FAIL_PROBE,
167 };
168
169 /**
170  * failtest_hook - whether a certain call should fail or not.
171  * @history: the ordered history of all failtest calls.
172  *
173  * The default value of this hook is failtest_default_hook(), which returns
174  * FAIL_OK (ie. yes, fail the call).
175  *
176  * You can override it, and avoid failing certain calls.  The parameters
177  * of the call (but not the return value(s)) will be filled in for the last
178  * call.
179  *
180  * Example:
181  *      static enum failtest_result dont_fail_alloc(struct tlist_calls *history)
182  *      {
183  *              struct failtest_call *call;
184  *              call = tlist_tail(history, struct failtest_call, list);
185  *              if (call->type == FAILTEST_MALLOC
186  *                      || call->type == FAILTEST_CALLOC
187  *                      || call->type == FAILTEST_REALLOC)
188  *                      return FAIL_DONT_FAIL;
189  *              return FAIL_OK;
190  *      }
191  *      ...
192  *              failtest_hook = dont_fail_alloc;
193  */
194 extern enum failtest_result (*failtest_hook)(struct tlist_calls *history);
195
196 /**
197  * failtest_exit_check - hook for additional checks on a failed child.
198  * @history: the ordered history of all failtest calls.
199  *
200  * Your program might have additional checks to do on failure, such as
201  * check that a file is not corrupted, or than an error message has been
202  * logged.
203  *
204  * If this returns false, the path to this failure will be printed and the
205  * overall test will fail.
206  */
207 extern bool (*failtest_exit_check)(struct tlist_calls *history);
208
209 /**
210  * failtest_has_failed - determine if a failure has occurred.
211  *
212  * Sometimes you want to exit immediately if you've experienced an
213  * injected failure.  This is useful when you have four separate tests
214  * in your test suite, and you don't want to do the next one if you've
215  * had a failure in a previous one.
216  */
217 extern bool failtest_has_failed(void);
218
219 /**
220  * failtest_timeout_ms - how long to wait before killing child.
221  *
222  * Default is 20,000 (20 seconds).
223  */
224 extern unsigned int failtest_timeout_ms;
225 #endif /* CCAN_FAILTEST_H */