failtest: new module.
[ccan] / ccan / failtest / test / run-malloc.c
1 #include <stdlib.h>
2 #include <setjmp.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <assert.h>
6 #include <ccan/tap/tap.h>
7
8 /* We don't actually want it to exit... */
9 static jmp_buf exited;
10 #define exit(status) longjmp(exited, (status) + 1)
11
12 #define printf saved_printf
13 static int saved_printf(const char *fmt, ...);
14
15 #define fprintf saved_fprintf
16 static int saved_fprintf(FILE *ignored, const char *fmt, ...);
17
18 #define vfprintf saved_vfprintf
19 static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap);
20
21 /* Hack to avoid a memory leak which valgrind complains about. */
22 #define realloc set_realloc
23 static void *set_realloc(void *ptr, size_t size);
24
25 #define free set_free
26 static void set_free(void *ptr);
27
28 /* Include the C files directly. */
29 #include <ccan/failtest/failtest.c>
30
31 #undef realloc
32 #undef free
33
34 static char *buffer;
35 static void *set_realloc(void *ptr, size_t size)
36 {
37         return buffer = realloc(ptr, size);
38 }
39
40 static void set_free(void *ptr)
41 {
42         if (ptr == buffer)
43                 buffer = NULL;
44         free(ptr);
45 }
46
47 static char *output = NULL;
48
49 static int saved_vprintf(const char *fmt, va_list ap)
50 {
51         int ret = vsnprintf(NULL, 0, fmt, ap);
52         int len = 0;
53
54         if (output)
55                 len = strlen(output);
56
57         output = realloc(output, len + ret + 1);
58         return vsprintf(output + len, fmt, ap);
59 }
60
61 static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap)
62 {
63         return saved_vprintf(fmt, ap);
64 }
65
66 static int saved_printf(const char *fmt, ...)
67 {
68         va_list ap;
69         int ret;
70
71         va_start(ap, fmt);
72         ret = saved_vprintf(fmt, ap);
73         va_end(ap);
74         return ret;
75 }       
76
77 static int saved_fprintf(FILE *ignored, const char *fmt, ...)
78 {
79         va_list ap;
80         int ret;
81
82         va_start(ap, fmt);
83         ret = saved_vprintf(fmt, ap);
84         va_end(ap);
85         return ret;
86 }       
87
88 int main(void)
89 {
90         int status;
91
92         plan_tests(3);
93
94         status = setjmp(exited);
95         if (status == 0) {
96                 char *p = failtest_malloc(1, "run-malloc.c", 1);
97                 /* If we just segv, valgrind counts that as a failure.
98                  * So kill ourselves creatively. */
99                 if (!p)
100                         kill(getpid(), SIGSEGV);
101                 fail("Expected child to crash!");
102         } else {
103                 ok1(status == 2);
104                 ok1(strstr(output, "Killed by signal"));
105                 ok1(strstr(output, "--failpath=M\n"));
106         }
107         free(buffer);
108         return exit_status();
109 }