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