1 /* $OpenBSD: test.h,v 1.7 2024/08/29 15:18:17 claudio Exp $ */
2
3 #ifndef _h_test_
4 #define _h_test_
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <signal.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13
14 static void __vpanic(const char *, const char *, const char *,
15 int, const char *, va_list) __attribute__((__noreturn__));
16 static void __panic(const char *, const char *, const char *,
17 int, const char *, ...) __attribute__((__noreturn__))
18 __attribute__((__format__ (printf, 5, 6)));
19
20 #if defined(__OpenBSD__) || defined(__FreeBSD__)
21 #include <pthread.h>
22 #include <pthread_np.h>
23 void _thread_dump_info(void);
24 int _thread_sys_write(int, const char*, size_t);
25 void _thread_sys__exit(int) __attribute__((__noreturn__));
26 #define SET_NAME(x) pthread_set_name_np(pthread_self(), x)
27 #define DUMP_INFO() _thread_dump_info()
28 #else
29 #define _thread_sys_write(fd,buf,len) write(fd,buf,len)
30 #define _thread_sys__exit(ret) _exit(ret)
31 #define strlcat(dst,src,siz) strcat(dst,src)
32 #define SET_NAME(x) /* nada */
33 #define DUMP_INFO() /* nada */
34 #endif
35
36 static void
__vpanic(const char * type,const char * errstr,const char * filenm,int lineno,const char * fmt,va_list ap)37 __vpanic(const char *type, const char *errstr, const char *filenm, int lineno,
38 const char *fmt, va_list ap)
39 {
40 char buf[1024];
41
42 /* "<type> at <filenm>:<lineno>: <fmt ap...>:<errstr>" */
43 snprintf(buf, sizeof buf, "%s at %s:%d\n", type, filenm, lineno);
44 _thread_sys_write(2, buf, strlen(buf));
45 vsnprintf(buf, sizeof buf, fmt, ap);
46 if (errstr != NULL) {
47 strlcat(buf, ": ", sizeof buf);
48 strlcat(buf, errstr, sizeof buf);
49 }
50 strlcat(buf, "\n", sizeof buf);
51 _thread_sys_write(2, buf, strlen(buf));
52
53 DUMP_INFO();
54 _thread_sys__exit(1);
55
56 _thread_sys_write(2, "[locking]\n", 10);
57 while(1);
58 }
59
60 static void
__panic(const char * type,const char * errstr,const char * filenm,int lineno,const char * fmt,...)61 __panic(const char *type, const char *errstr, const char *filenm, int lineno,
62 const char *fmt, ...)
63 {
64 va_list ap;
65
66 va_start(ap, fmt);
67 __vpanic(type, errstr, filenm, lineno, fmt, ap);
68 va_end(ap);
69 }
70
71 #define DIE(e, m, args...) \
72 __panic("died", strerror(e), __FILE__, __LINE__, m , ## args)
73
74 #define PANIC(m, args...) \
75 __panic("panic", NULL, __FILE__, __LINE__, m, ## args)
76
77 #define ASSERT(x) do { \
78 if (!(x)) \
79 __panic("assert failed", NULL, __FILE__, __LINE__, "%s", #x); \
80 } while(0)
81
82 #define ASSERTe(x,rhs) do { \
83 int _x; \
84 _x = (x); \
85 if (!(_x rhs)) { \
86 if (_x > 0) \
87 __panic("assert failed", strerror(_x), __FILE__, __LINE__, \
88 "%s %s", #x, #rhs); \
89 else \
90 __panic("assert failed", NULL, __FILE__, __LINE__, \
91 "%s [=%d] %s", #x, _x, #rhs); \
92 } \
93 } while(0)
94
95 #define _T(x) __builtin_classify_type(x)
96
97 #define _CHECK(x, rhs, efn) do { \
98 typeof(x) _x; \
99 _x = (x); \
100 if (!(_x rhs)) \
101 __panic("check failed", efn, __FILE__, __LINE__, \
102 ((_T(0) == _T(_x) )? "failed check %s (=%d) %s " : \
103 (_T("") == _T(_x) )? "failed check %s (=%s) %s " : \
104 (_T('x') == _T(_x) )? "failed check %s (=%c) %s " : \
105 (_T(0L) == _T(_x) )? "failed check %s (=%ld) %s " : "?") \
106 , #x, _x, #rhs); \
107 } while(0)
108
109 #define CHECKr(x) _CHECK(x, == 0, strerror(_x))
110 #define CHECKe(x) _CHECK(x, != -1, strerror(errno))
111 #define CHECKn(x) _CHECK(x, != 0, strerror(errno))
112 #define CHECKhn(x) _CHECK(x, != 0, hstrerror(h_errno))
113
114 #define SUCCEED exit(0)
115
116 #define OK (0)
117 #define NOTOK (-1)
118
119 #endif /* _h_test_ */
120