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