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 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 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