1362aecb2SWilly Tarreau // SPDX-License-Identifier: GPL-2.0 2362aecb2SWilly Tarreau 3362aecb2SWilly Tarreau /* platform-specific include files coming from the compiler */ 4362aecb2SWilly Tarreau #include <limits.h> 5362aecb2SWilly Tarreau 6362aecb2SWilly Tarreau /* libc-specific include files 7362aecb2SWilly Tarreau * The program may be built in 2 ways: 8362aecb2SWilly Tarreau * $(CC) -nostdlib -include /path/to/nolibc.h => NOLIBC already defined 9362aecb2SWilly Tarreau * $(CC) -nostdlib -I/path/to/nolibc/sysroot 10362aecb2SWilly Tarreau */ 11362aecb2SWilly Tarreau #ifndef NOLIBC 12362aecb2SWilly Tarreau #include <stdio.h> 13362aecb2SWilly Tarreau #include <stdlib.h> 14362aecb2SWilly Tarreau #include <string.h> 15362aecb2SWilly Tarreau #endif 16362aecb2SWilly Tarreau 17362aecb2SWilly Tarreau /* will be used by nolibc by getenv() */ 18362aecb2SWilly Tarreau char **environ; 19362aecb2SWilly Tarreau 2023da7bc9SWilly Tarreau /* definition of a series of tests */ 2123da7bc9SWilly Tarreau struct test { 2223da7bc9SWilly Tarreau const char *name; // test name 2323da7bc9SWilly Tarreau int (*func)(int min, int max); // handler 2423da7bc9SWilly Tarreau }; 2523da7bc9SWilly Tarreau 26362aecb2SWilly Tarreau #define CASE_ERR(err) \ 27362aecb2SWilly Tarreau case err: return #err 28362aecb2SWilly Tarreau 29362aecb2SWilly Tarreau /* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0, 30362aecb2SWilly Tarreau * or the decimal value for less common ones. 31362aecb2SWilly Tarreau */ 32362aecb2SWilly Tarreau const char *errorname(int err) 33362aecb2SWilly Tarreau { 34362aecb2SWilly Tarreau switch (err) { 35362aecb2SWilly Tarreau case 0: return "SUCCESS"; 36362aecb2SWilly Tarreau CASE_ERR(EPERM); 37362aecb2SWilly Tarreau CASE_ERR(ENOENT); 38362aecb2SWilly Tarreau CASE_ERR(ESRCH); 39362aecb2SWilly Tarreau CASE_ERR(EINTR); 40362aecb2SWilly Tarreau CASE_ERR(EIO); 41362aecb2SWilly Tarreau CASE_ERR(ENXIO); 42362aecb2SWilly Tarreau CASE_ERR(E2BIG); 43362aecb2SWilly Tarreau CASE_ERR(ENOEXEC); 44362aecb2SWilly Tarreau CASE_ERR(EBADF); 45362aecb2SWilly Tarreau CASE_ERR(ECHILD); 46362aecb2SWilly Tarreau CASE_ERR(EAGAIN); 47362aecb2SWilly Tarreau CASE_ERR(ENOMEM); 48362aecb2SWilly Tarreau CASE_ERR(EACCES); 49362aecb2SWilly Tarreau CASE_ERR(EFAULT); 50362aecb2SWilly Tarreau CASE_ERR(ENOTBLK); 51362aecb2SWilly Tarreau CASE_ERR(EBUSY); 52362aecb2SWilly Tarreau CASE_ERR(EEXIST); 53362aecb2SWilly Tarreau CASE_ERR(EXDEV); 54362aecb2SWilly Tarreau CASE_ERR(ENODEV); 55362aecb2SWilly Tarreau CASE_ERR(ENOTDIR); 56362aecb2SWilly Tarreau CASE_ERR(EISDIR); 57362aecb2SWilly Tarreau CASE_ERR(EINVAL); 58362aecb2SWilly Tarreau CASE_ERR(ENFILE); 59362aecb2SWilly Tarreau CASE_ERR(EMFILE); 60362aecb2SWilly Tarreau CASE_ERR(ENOTTY); 61362aecb2SWilly Tarreau CASE_ERR(ETXTBSY); 62362aecb2SWilly Tarreau CASE_ERR(EFBIG); 63362aecb2SWilly Tarreau CASE_ERR(ENOSPC); 64362aecb2SWilly Tarreau CASE_ERR(ESPIPE); 65362aecb2SWilly Tarreau CASE_ERR(EROFS); 66362aecb2SWilly Tarreau CASE_ERR(EMLINK); 67362aecb2SWilly Tarreau CASE_ERR(EPIPE); 68362aecb2SWilly Tarreau CASE_ERR(EDOM); 69362aecb2SWilly Tarreau CASE_ERR(ERANGE); 70362aecb2SWilly Tarreau CASE_ERR(ENOSYS); 71362aecb2SWilly Tarreau default: 72362aecb2SWilly Tarreau return itoa(err); 73362aecb2SWilly Tarreau } 74362aecb2SWilly Tarreau } 75362aecb2SWilly Tarreau 76362aecb2SWilly Tarreau static int pad_spc(int llen, int cnt, const char *fmt, ...) 77362aecb2SWilly Tarreau { 78362aecb2SWilly Tarreau va_list args; 79362aecb2SWilly Tarreau int len; 80362aecb2SWilly Tarreau int ret; 81362aecb2SWilly Tarreau 82362aecb2SWilly Tarreau for (len = 0; len < cnt - llen; len++) 83362aecb2SWilly Tarreau putchar(' '); 84362aecb2SWilly Tarreau 85362aecb2SWilly Tarreau va_start(args, fmt); 86362aecb2SWilly Tarreau ret = vfprintf(stdout, fmt, args); 87362aecb2SWilly Tarreau va_end(args); 88362aecb2SWilly Tarreau return ret < 0 ? ret : ret + len; 89362aecb2SWilly Tarreau } 90362aecb2SWilly Tarreau 91362aecb2SWilly Tarreau /* The tests below are intended to be used by the macroes, which evaluate 92362aecb2SWilly Tarreau * expression <expr>, print the status to stdout, and update the "ret" 93362aecb2SWilly Tarreau * variable to count failures. The functions themselves return the number 94362aecb2SWilly Tarreau * of failures, thus either 0 or 1. 95362aecb2SWilly Tarreau */ 96362aecb2SWilly Tarreau 97362aecb2SWilly Tarreau #define EXPECT_ZR(cond, expr) \ 98362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) 99362aecb2SWilly Tarreau 100362aecb2SWilly Tarreau static int expect_zr(int expr, int llen) 101362aecb2SWilly Tarreau { 102362aecb2SWilly Tarreau int ret = !(expr == 0); 103362aecb2SWilly Tarreau 104362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 105362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 106362aecb2SWilly Tarreau return ret; 107362aecb2SWilly Tarreau } 108362aecb2SWilly Tarreau 109362aecb2SWilly Tarreau 110362aecb2SWilly Tarreau #define EXPECT_NZ(cond, expr, val) \ 111362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) 112362aecb2SWilly Tarreau 113362aecb2SWilly Tarreau static int expect_nz(int expr, int llen) 114362aecb2SWilly Tarreau { 115362aecb2SWilly Tarreau int ret = !(expr != 0); 116362aecb2SWilly Tarreau 117362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 118362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 119362aecb2SWilly Tarreau return ret; 120362aecb2SWilly Tarreau } 121362aecb2SWilly Tarreau 122362aecb2SWilly Tarreau 123362aecb2SWilly Tarreau #define EXPECT_EQ(cond, expr, val) \ 124362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) 125362aecb2SWilly Tarreau 126362aecb2SWilly Tarreau static int expect_eq(int expr, int llen, int val) 127362aecb2SWilly Tarreau { 128362aecb2SWilly Tarreau int ret = !(expr == val); 129362aecb2SWilly Tarreau 130362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 131362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 132362aecb2SWilly Tarreau return ret; 133362aecb2SWilly Tarreau } 134362aecb2SWilly Tarreau 135362aecb2SWilly Tarreau 136362aecb2SWilly Tarreau #define EXPECT_NE(cond, expr, val) \ 137362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) 138362aecb2SWilly Tarreau 139362aecb2SWilly Tarreau static int expect_ne(int expr, int llen, int val) 140362aecb2SWilly Tarreau { 141362aecb2SWilly Tarreau int ret = !(expr != val); 142362aecb2SWilly Tarreau 143362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 144362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 145362aecb2SWilly Tarreau return ret; 146362aecb2SWilly Tarreau } 147362aecb2SWilly Tarreau 148362aecb2SWilly Tarreau 149362aecb2SWilly Tarreau #define EXPECT_GE(cond, expr, val) \ 150362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) 151362aecb2SWilly Tarreau 152362aecb2SWilly Tarreau static int expect_ge(int expr, int llen, int val) 153362aecb2SWilly Tarreau { 154362aecb2SWilly Tarreau int ret = !(expr >= val); 155362aecb2SWilly Tarreau 156362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 157362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 158362aecb2SWilly Tarreau return ret; 159362aecb2SWilly Tarreau } 160362aecb2SWilly Tarreau 161362aecb2SWilly Tarreau 162362aecb2SWilly Tarreau #define EXPECT_GT(cond, expr, val) \ 163362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) 164362aecb2SWilly Tarreau 165362aecb2SWilly Tarreau static int expect_gt(int expr, int llen, int val) 166362aecb2SWilly Tarreau { 167362aecb2SWilly Tarreau int ret = !(expr > val); 168362aecb2SWilly Tarreau 169362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 170362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 171362aecb2SWilly Tarreau return ret; 172362aecb2SWilly Tarreau } 173362aecb2SWilly Tarreau 174362aecb2SWilly Tarreau 175362aecb2SWilly Tarreau #define EXPECT_LE(cond, expr, val) \ 176362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) 177362aecb2SWilly Tarreau 178362aecb2SWilly Tarreau static int expect_le(int expr, int llen, int val) 179362aecb2SWilly Tarreau { 180362aecb2SWilly Tarreau int ret = !(expr <= val); 181362aecb2SWilly Tarreau 182362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 183362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 184362aecb2SWilly Tarreau return ret; 185362aecb2SWilly Tarreau } 186362aecb2SWilly Tarreau 187362aecb2SWilly Tarreau 188362aecb2SWilly Tarreau #define EXPECT_LT(cond, expr, val) \ 189362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) 190362aecb2SWilly Tarreau 191362aecb2SWilly Tarreau static int expect_lt(int expr, int llen, int val) 192362aecb2SWilly Tarreau { 193362aecb2SWilly Tarreau int ret = !(expr < val); 194362aecb2SWilly Tarreau 195362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 196362aecb2SWilly Tarreau pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 197362aecb2SWilly Tarreau return ret; 198362aecb2SWilly Tarreau } 199362aecb2SWilly Tarreau 200362aecb2SWilly Tarreau 201362aecb2SWilly Tarreau #define EXPECT_SYSZR(cond, expr) \ 202362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) 203362aecb2SWilly Tarreau 204362aecb2SWilly Tarreau static int expect_syszr(int expr, int llen) 205362aecb2SWilly Tarreau { 206362aecb2SWilly Tarreau int ret = 0; 207362aecb2SWilly Tarreau 208362aecb2SWilly Tarreau if (expr) { 209362aecb2SWilly Tarreau ret = 1; 210362aecb2SWilly Tarreau llen += printf(" = %d %s ", expr, errorname(errno)); 211362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 212362aecb2SWilly Tarreau } else { 213362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 214362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 215362aecb2SWilly Tarreau } 216362aecb2SWilly Tarreau return ret; 217362aecb2SWilly Tarreau } 218362aecb2SWilly Tarreau 219362aecb2SWilly Tarreau 220362aecb2SWilly Tarreau #define EXPECT_SYSEQ(cond, expr, val) \ 221362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) 222362aecb2SWilly Tarreau 223362aecb2SWilly Tarreau static int expect_syseq(int expr, int llen, int val) 224362aecb2SWilly Tarreau { 225362aecb2SWilly Tarreau int ret = 0; 226362aecb2SWilly Tarreau 227362aecb2SWilly Tarreau if (expr != val) { 228362aecb2SWilly Tarreau ret = 1; 229362aecb2SWilly Tarreau llen += printf(" = %d %s ", expr, errorname(errno)); 230362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 231362aecb2SWilly Tarreau } else { 232362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 233362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 234362aecb2SWilly Tarreau } 235362aecb2SWilly Tarreau return ret; 236362aecb2SWilly Tarreau } 237362aecb2SWilly Tarreau 238362aecb2SWilly Tarreau 239362aecb2SWilly Tarreau #define EXPECT_SYSNE(cond, expr, val) \ 240362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) 241362aecb2SWilly Tarreau 242362aecb2SWilly Tarreau static int expect_sysne(int expr, int llen, int val) 243362aecb2SWilly Tarreau { 244362aecb2SWilly Tarreau int ret = 0; 245362aecb2SWilly Tarreau 246362aecb2SWilly Tarreau if (expr == val) { 247362aecb2SWilly Tarreau ret = 1; 248362aecb2SWilly Tarreau llen += printf(" = %d %s ", expr, errorname(errno)); 249362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 250362aecb2SWilly Tarreau } else { 251362aecb2SWilly Tarreau llen += printf(" = %d ", expr); 252362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 253362aecb2SWilly Tarreau } 254362aecb2SWilly Tarreau return ret; 255362aecb2SWilly Tarreau } 256362aecb2SWilly Tarreau 257362aecb2SWilly Tarreau 258362aecb2SWilly Tarreau #define EXPECT_SYSER(cond, expr, expret, experr) \ 259362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0) 260362aecb2SWilly Tarreau 261362aecb2SWilly Tarreau static int expect_syserr(int expr, int expret, int experr, int llen) 262362aecb2SWilly Tarreau { 263362aecb2SWilly Tarreau int ret = 0; 264362aecb2SWilly Tarreau int _errno = errno; 265362aecb2SWilly Tarreau 266362aecb2SWilly Tarreau llen += printf(" = %d %s ", expr, errorname(_errno)); 267362aecb2SWilly Tarreau if (expr != expret || _errno != experr) { 268362aecb2SWilly Tarreau ret = 1; 269362aecb2SWilly Tarreau llen += printf(" != (%d %s) ", expret, errorname(experr)); 270362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 271362aecb2SWilly Tarreau } else { 272362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 273362aecb2SWilly Tarreau } 274362aecb2SWilly Tarreau return ret; 275362aecb2SWilly Tarreau } 276362aecb2SWilly Tarreau 277362aecb2SWilly Tarreau 278362aecb2SWilly Tarreau #define EXPECT_PTRZR(cond, expr) \ 279362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) 280362aecb2SWilly Tarreau 281362aecb2SWilly Tarreau static int expect_ptrzr(const void *expr, int llen) 282362aecb2SWilly Tarreau { 283362aecb2SWilly Tarreau int ret = 0; 284362aecb2SWilly Tarreau 285362aecb2SWilly Tarreau llen += printf(" = <%p> ", expr); 286362aecb2SWilly Tarreau if (expr) { 287362aecb2SWilly Tarreau ret = 1; 288362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 289362aecb2SWilly Tarreau } else { 290362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 291362aecb2SWilly Tarreau } 292362aecb2SWilly Tarreau return ret; 293362aecb2SWilly Tarreau } 294362aecb2SWilly Tarreau 295362aecb2SWilly Tarreau 296362aecb2SWilly Tarreau #define EXPECT_PTRNZ(cond, expr) \ 297362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) 298362aecb2SWilly Tarreau 299362aecb2SWilly Tarreau static int expect_ptrnz(const void *expr, int llen) 300362aecb2SWilly Tarreau { 301362aecb2SWilly Tarreau int ret = 0; 302362aecb2SWilly Tarreau 303362aecb2SWilly Tarreau llen += printf(" = <%p> ", expr); 304362aecb2SWilly Tarreau if (!expr) { 305362aecb2SWilly Tarreau ret = 1; 306362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 307362aecb2SWilly Tarreau } else { 308362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 309362aecb2SWilly Tarreau } 310362aecb2SWilly Tarreau return ret; 311362aecb2SWilly Tarreau } 312362aecb2SWilly Tarreau 313362aecb2SWilly Tarreau 314362aecb2SWilly Tarreau #define EXPECT_STRZR(cond, expr) \ 315362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) 316362aecb2SWilly Tarreau 317362aecb2SWilly Tarreau static int expect_strzr(const char *expr, int llen) 318362aecb2SWilly Tarreau { 319362aecb2SWilly Tarreau int ret = 0; 320362aecb2SWilly Tarreau 321362aecb2SWilly Tarreau llen += printf(" = <%s> ", expr); 322362aecb2SWilly Tarreau if (expr) { 323362aecb2SWilly Tarreau ret = 1; 324362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 325362aecb2SWilly Tarreau } else { 326362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 327362aecb2SWilly Tarreau } 328362aecb2SWilly Tarreau return ret; 329362aecb2SWilly Tarreau } 330362aecb2SWilly Tarreau 331362aecb2SWilly Tarreau 332362aecb2SWilly Tarreau #define EXPECT_STRNZ(cond, expr) \ 333362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) 334362aecb2SWilly Tarreau 335362aecb2SWilly Tarreau static int expect_strnz(const char *expr, int llen) 336362aecb2SWilly Tarreau { 337362aecb2SWilly Tarreau int ret = 0; 338362aecb2SWilly Tarreau 339362aecb2SWilly Tarreau llen += printf(" = <%s> ", expr); 340362aecb2SWilly Tarreau if (!expr) { 341362aecb2SWilly Tarreau ret = 1; 342362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 343362aecb2SWilly Tarreau } else { 344362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 345362aecb2SWilly Tarreau } 346362aecb2SWilly Tarreau return ret; 347362aecb2SWilly Tarreau } 348362aecb2SWilly Tarreau 349362aecb2SWilly Tarreau 350362aecb2SWilly Tarreau #define EXPECT_STREQ(cond, expr, cmp) \ 351362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) 352362aecb2SWilly Tarreau 353362aecb2SWilly Tarreau static int expect_streq(const char *expr, int llen, const char *cmp) 354362aecb2SWilly Tarreau { 355362aecb2SWilly Tarreau int ret = 0; 356362aecb2SWilly Tarreau 357362aecb2SWilly Tarreau llen += printf(" = <%s> ", expr); 358362aecb2SWilly Tarreau if (strcmp(expr, cmp) != 0) { 359362aecb2SWilly Tarreau ret = 1; 360362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 361362aecb2SWilly Tarreau } else { 362362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 363362aecb2SWilly Tarreau } 364362aecb2SWilly Tarreau return ret; 365362aecb2SWilly Tarreau } 366362aecb2SWilly Tarreau 367362aecb2SWilly Tarreau 368362aecb2SWilly Tarreau #define EXPECT_STRNE(cond, expr, cmp) \ 369362aecb2SWilly Tarreau do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) 370362aecb2SWilly Tarreau 371362aecb2SWilly Tarreau static int expect_strne(const char *expr, int llen, const char *cmp) 372362aecb2SWilly Tarreau { 373362aecb2SWilly Tarreau int ret = 0; 374362aecb2SWilly Tarreau 375362aecb2SWilly Tarreau llen += printf(" = <%s> ", expr); 376362aecb2SWilly Tarreau if (strcmp(expr, cmp) == 0) { 377362aecb2SWilly Tarreau ret = 1; 378362aecb2SWilly Tarreau llen += pad_spc(llen, 40, "[FAIL]\n"); 379362aecb2SWilly Tarreau } else { 380362aecb2SWilly Tarreau llen += pad_spc(llen, 40, " [OK]\n"); 381362aecb2SWilly Tarreau } 382362aecb2SWilly Tarreau return ret; 383362aecb2SWilly Tarreau } 384362aecb2SWilly Tarreau 38523da7bc9SWilly Tarreau 386362aecb2SWilly Tarreau /* declare tests based on line numbers. There must be exactly one test per line. */ 387362aecb2SWilly Tarreau #define CASE_TEST(name) \ 388362aecb2SWilly Tarreau case __LINE__: llen += printf("%d %s", test, #name); 389362aecb2SWilly Tarreau 390362aecb2SWilly Tarreau 391*b4844fa0SWilly Tarreau /* used by some syscall tests below */ 392*b4844fa0SWilly Tarreau int test_getdents64(const char *dir) 393*b4844fa0SWilly Tarreau { 394*b4844fa0SWilly Tarreau char buffer[4096]; 395*b4844fa0SWilly Tarreau int fd, ret; 396*b4844fa0SWilly Tarreau int err; 397*b4844fa0SWilly Tarreau 398*b4844fa0SWilly Tarreau ret = fd = open(dir, O_RDONLY | O_DIRECTORY, 0); 399*b4844fa0SWilly Tarreau if (ret < 0) 400*b4844fa0SWilly Tarreau return ret; 401*b4844fa0SWilly Tarreau 402*b4844fa0SWilly Tarreau ret = getdents64(fd, (void *)buffer, sizeof(buffer)); 403*b4844fa0SWilly Tarreau err = errno; 404*b4844fa0SWilly Tarreau close(fd); 405*b4844fa0SWilly Tarreau 406*b4844fa0SWilly Tarreau errno = err; 407*b4844fa0SWilly Tarreau return ret; 408*b4844fa0SWilly Tarreau } 409*b4844fa0SWilly Tarreau 410*b4844fa0SWilly Tarreau /* Run syscall tests between IDs <min> and <max>. 411*b4844fa0SWilly Tarreau * Return 0 on success, non-zero on failure. 412*b4844fa0SWilly Tarreau */ 413*b4844fa0SWilly Tarreau int run_syscall(int min, int max) 414*b4844fa0SWilly Tarreau { 415*b4844fa0SWilly Tarreau struct stat stat_buf; 416*b4844fa0SWilly Tarreau int test; 417*b4844fa0SWilly Tarreau int tmp; 418*b4844fa0SWilly Tarreau int ret = 0; 419*b4844fa0SWilly Tarreau void *p1, *p2; 420*b4844fa0SWilly Tarreau 421*b4844fa0SWilly Tarreau for (test = min; test >= 0 && test <= max; test++) { 422*b4844fa0SWilly Tarreau int llen = 0; // line length 423*b4844fa0SWilly Tarreau 424*b4844fa0SWilly Tarreau /* avoid leaving empty lines below, this will insert holes into 425*b4844fa0SWilly Tarreau * test numbers. 426*b4844fa0SWilly Tarreau */ 427*b4844fa0SWilly Tarreau switch (test + __LINE__ + 1) { 428*b4844fa0SWilly Tarreau CASE_TEST(getpid); EXPECT_SYSNE(1, getpid(), -1); break; 429*b4844fa0SWilly Tarreau CASE_TEST(getppid); EXPECT_SYSNE(1, getppid(), -1); break; 430*b4844fa0SWilly Tarreau CASE_TEST(gettid); EXPECT_SYSNE(1, gettid(), -1); break; 431*b4844fa0SWilly Tarreau CASE_TEST(getpgid_self); EXPECT_SYSNE(1, getpgid(0), -1); break; 432*b4844fa0SWilly Tarreau CASE_TEST(getpgid_bad); EXPECT_SYSER(1, getpgid(-1), -1, ESRCH); break; 433*b4844fa0SWilly Tarreau CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break; 434*b4844fa0SWilly Tarreau CASE_TEST(kill_CONT); EXPECT_SYSZR(1, kill(getpid(), 0)); break; 435*b4844fa0SWilly Tarreau CASE_TEST(kill_BADPID); EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break; 436*b4844fa0SWilly Tarreau CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break; 437*b4844fa0SWilly Tarreau CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break; 438*b4844fa0SWilly Tarreau CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); break; 439*b4844fa0SWilly Tarreau CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir(".")); break; 440*b4844fa0SWilly Tarreau CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break; 441*b4844fa0SWilly Tarreau CASE_TEST(chmod_net); EXPECT_SYSZR(1, chmod("/proc/self/net", 0555)); break; 442*b4844fa0SWilly Tarreau CASE_TEST(chmod_self); EXPECT_SYSER(1, chmod("/proc/self", 0555), -1, EPERM); break; 443*b4844fa0SWilly Tarreau CASE_TEST(chown_self); EXPECT_SYSER(1, chown("/proc/self", 0, 0), -1, EPERM); break; 444*b4844fa0SWilly Tarreau CASE_TEST(chroot_root); EXPECT_SYSZR(1, chroot("/")); break; 445*b4844fa0SWilly Tarreau CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break; 446*b4844fa0SWilly Tarreau CASE_TEST(chroot_exe); EXPECT_SYSER(1, chroot("/proc/self/exe"), -1, ENOTDIR); break; 447*b4844fa0SWilly Tarreau CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break; 448*b4844fa0SWilly Tarreau CASE_TEST(close_dup); EXPECT_SYSZR(1, close(dup(0))); break; 449*b4844fa0SWilly Tarreau CASE_TEST(dup_0); tmp = dup(0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; 450*b4844fa0SWilly Tarreau CASE_TEST(dup_m1); tmp = dup(-1); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; 451*b4844fa0SWilly Tarreau CASE_TEST(dup2_0); tmp = dup2(0, 100); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; 452*b4844fa0SWilly Tarreau CASE_TEST(dup2_m1); tmp = dup2(-1, 100); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; 453*b4844fa0SWilly Tarreau CASE_TEST(dup3_0); tmp = dup3(0, 100, 0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; 454*b4844fa0SWilly Tarreau CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; 455*b4844fa0SWilly Tarreau CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break; 456*b4844fa0SWilly Tarreau CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; 457*b4844fa0SWilly Tarreau CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break; 458*b4844fa0SWilly Tarreau CASE_TEST(gettimeofday_null); EXPECT_SYSZR(1, gettimeofday(NULL, NULL)); break; 459*b4844fa0SWilly Tarreau CASE_TEST(gettimeofday_bad1); EXPECT_SYSER(1, gettimeofday((void *)1, NULL), -1, EFAULT); break; 460*b4844fa0SWilly Tarreau CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; 461*b4844fa0SWilly Tarreau CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; 462*b4844fa0SWilly Tarreau CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; 463*b4844fa0SWilly Tarreau CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; 464*b4844fa0SWilly Tarreau CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break; 465*b4844fa0SWilly Tarreau CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break; 466*b4844fa0SWilly Tarreau CASE_TEST(link_dir); EXPECT_SYSER(1, link("/", "/blah"), -1, EPERM); break; 467*b4844fa0SWilly Tarreau CASE_TEST(link_cross); EXPECT_SYSER(1, link("/proc/self/net", "/blah"), -1, EXDEV); break; 468*b4844fa0SWilly Tarreau CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break; 469*b4844fa0SWilly Tarreau CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; 470*b4844fa0SWilly Tarreau CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break; 471*b4844fa0SWilly Tarreau CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; 472*b4844fa0SWilly Tarreau CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; 473*b4844fa0SWilly Tarreau CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; 474*b4844fa0SWilly Tarreau CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break; 475*b4844fa0SWilly Tarreau CASE_TEST(poll_fault); EXPECT_SYSER(1, poll((void *)1, 1, 0), -1, EFAULT); break; 476*b4844fa0SWilly Tarreau CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break; 477*b4844fa0SWilly Tarreau CASE_TEST(sched_yield); EXPECT_SYSZR(1, sched_yield()); break; 478*b4844fa0SWilly Tarreau CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break; 479*b4844fa0SWilly Tarreau CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break; 480*b4844fa0SWilly Tarreau CASE_TEST(select_fault); EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break; 481*b4844fa0SWilly Tarreau CASE_TEST(stat_blah); EXPECT_SYSER(1, stat("/proc/self/blah", &stat_buf), -1, ENOENT); break; 482*b4844fa0SWilly Tarreau CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break; 483*b4844fa0SWilly Tarreau CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break; 484*b4844fa0SWilly Tarreau CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break; 485*b4844fa0SWilly Tarreau CASE_TEST(unlink_blah); EXPECT_SYSER(1, unlink("/proc/self/blah"), -1, ENOENT); break; 486*b4844fa0SWilly Tarreau CASE_TEST(wait_child); EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break; 487*b4844fa0SWilly Tarreau CASE_TEST(waitpid_min); EXPECT_SYSER(1, waitpid(INT_MIN, &tmp, WNOHANG), -1, ESRCH); break; 488*b4844fa0SWilly Tarreau CASE_TEST(waitpid_child); EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break; 489*b4844fa0SWilly Tarreau CASE_TEST(write_badf); EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break; 490*b4844fa0SWilly Tarreau CASE_TEST(write_zero); EXPECT_SYSZR(1, write(1, &tmp, 0)); break; 491*b4844fa0SWilly Tarreau case __LINE__: 492*b4844fa0SWilly Tarreau return ret; /* must be last */ 493*b4844fa0SWilly Tarreau /* note: do not set any defaults so as to permit holes above */ 494*b4844fa0SWilly Tarreau } 495*b4844fa0SWilly Tarreau } 496*b4844fa0SWilly Tarreau return ret; 497*b4844fa0SWilly Tarreau } 498*b4844fa0SWilly Tarreau 499*b4844fa0SWilly Tarreau 50023da7bc9SWilly Tarreau /* This is the definition of known test names, with their functions */ 50123da7bc9SWilly Tarreau static struct test test_names[] = { 50223da7bc9SWilly Tarreau /* add new tests here */ 503*b4844fa0SWilly Tarreau { .name = "syscall", .func = run_syscall }, 50423da7bc9SWilly Tarreau { 0 } 50523da7bc9SWilly Tarreau }; 50623da7bc9SWilly Tarreau 507362aecb2SWilly Tarreau int main(int argc, char **argv, char **envp) 508362aecb2SWilly Tarreau { 509362aecb2SWilly Tarreau int min = 0; 510362aecb2SWilly Tarreau int max = __INT_MAX__; 511362aecb2SWilly Tarreau int ret = 0; 51223da7bc9SWilly Tarreau int err; 51323da7bc9SWilly Tarreau int idx; 51423da7bc9SWilly Tarreau char *test; 515362aecb2SWilly Tarreau 516362aecb2SWilly Tarreau environ = envp; 517362aecb2SWilly Tarreau 51823da7bc9SWilly Tarreau /* the definition of a series of tests comes from either argv[1] or the 51923da7bc9SWilly Tarreau * "NOLIBC_TEST" environment variable. It's made of a comma-delimited 52023da7bc9SWilly Tarreau * series of test names and optional ranges: 52123da7bc9SWilly Tarreau * syscall:5-15[:.*],stdlib:8-10 52223da7bc9SWilly Tarreau */ 52323da7bc9SWilly Tarreau test = argv[1]; 52423da7bc9SWilly Tarreau if (!test) 52523da7bc9SWilly Tarreau test = getenv("NOLIBC_TEST"); 52623da7bc9SWilly Tarreau 52723da7bc9SWilly Tarreau if (test) { 52823da7bc9SWilly Tarreau char *comma, *colon, *dash, *value; 52923da7bc9SWilly Tarreau 53023da7bc9SWilly Tarreau do { 53123da7bc9SWilly Tarreau comma = strchr(test, ','); 53223da7bc9SWilly Tarreau if (comma) 53323da7bc9SWilly Tarreau *(comma++) = '\0'; 53423da7bc9SWilly Tarreau 53523da7bc9SWilly Tarreau colon = strchr(test, ':'); 53623da7bc9SWilly Tarreau if (colon) 53723da7bc9SWilly Tarreau *(colon++) = '\0'; 53823da7bc9SWilly Tarreau 53923da7bc9SWilly Tarreau for (idx = 0; test_names[idx].name; idx++) { 54023da7bc9SWilly Tarreau if (strcmp(test, test_names[idx].name) == 0) 54123da7bc9SWilly Tarreau break; 54223da7bc9SWilly Tarreau } 54323da7bc9SWilly Tarreau 54423da7bc9SWilly Tarreau if (test_names[idx].name) { 54523da7bc9SWilly Tarreau /* The test was named, it will be called at least 54623da7bc9SWilly Tarreau * once. We may have an optional range at <colon> 54723da7bc9SWilly Tarreau * here, which defaults to the full range. 54823da7bc9SWilly Tarreau */ 54923da7bc9SWilly Tarreau do { 55023da7bc9SWilly Tarreau min = 0; max = __INT_MAX__; 55123da7bc9SWilly Tarreau value = colon; 55223da7bc9SWilly Tarreau if (value && *value) { 55323da7bc9SWilly Tarreau colon = strchr(value, ':'); 55423da7bc9SWilly Tarreau if (colon) 55523da7bc9SWilly Tarreau *(colon++) = '\0'; 55623da7bc9SWilly Tarreau 55723da7bc9SWilly Tarreau dash = strchr(value, '-'); 55823da7bc9SWilly Tarreau if (dash) 55923da7bc9SWilly Tarreau *(dash++) = '\0'; 56023da7bc9SWilly Tarreau 56123da7bc9SWilly Tarreau /* support :val: :min-max: :min-: :-max: */ 56223da7bc9SWilly Tarreau if (*value) 56323da7bc9SWilly Tarreau min = atoi(value); 56423da7bc9SWilly Tarreau if (!dash) 56523da7bc9SWilly Tarreau max = min; 56623da7bc9SWilly Tarreau else if (*dash) 56723da7bc9SWilly Tarreau max = atoi(dash); 56823da7bc9SWilly Tarreau 56923da7bc9SWilly Tarreau value = colon; 57023da7bc9SWilly Tarreau } 57123da7bc9SWilly Tarreau 57223da7bc9SWilly Tarreau /* now's time to call the test */ 57323da7bc9SWilly Tarreau printf("Running test '%s'\n", test_names[idx].name); 57423da7bc9SWilly Tarreau err = test_names[idx].func(min, max); 57523da7bc9SWilly Tarreau ret += err; 57623da7bc9SWilly Tarreau printf("Errors during this test: %d\n\n", err); 57723da7bc9SWilly Tarreau } while (colon && *colon); 57823da7bc9SWilly Tarreau } else 57923da7bc9SWilly Tarreau printf("Ignoring unknown test name '%s'\n", test); 58023da7bc9SWilly Tarreau 58123da7bc9SWilly Tarreau test = comma; 58223da7bc9SWilly Tarreau } while (test && *test); 58323da7bc9SWilly Tarreau } else { 58423da7bc9SWilly Tarreau /* no test mentioned, run everything */ 58523da7bc9SWilly Tarreau for (idx = 0; test_names[idx].name; idx++) { 58623da7bc9SWilly Tarreau printf("Running test '%s'\n", test_names[idx].name); 58723da7bc9SWilly Tarreau err = test_names[idx].func(min, max); 58823da7bc9SWilly Tarreau ret += err; 58923da7bc9SWilly Tarreau printf("Errors during this test: %d\n\n", err); 59023da7bc9SWilly Tarreau } 59123da7bc9SWilly Tarreau } 59223da7bc9SWilly Tarreau 593362aecb2SWilly Tarreau printf("Total number of errors: %d\n", ret); 594362aecb2SWilly Tarreau printf("Exiting with status %d\n", !!ret); 595362aecb2SWilly Tarreau return !!ret; 596362aecb2SWilly Tarreau } 597