1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22#ifndef TASK_H_ 23#define TASK_H_ 24 25#include "uv.h" 26 27#include <stdio.h> 28#include <stddef.h> 29#include <stdlib.h> 30#include <string.h> 31#include <inttypes.h> 32#include <stdint.h> 33 34#if !defined(_WIN32) 35# include <sys/time.h> 36# include <sys/resource.h> /* setrlimit() */ 37#endif 38 39#ifdef __clang__ 40# pragma clang diagnostic ignored "-Wvariadic-macros" 41# pragma clang diagnostic ignored "-Wc99-extensions" 42#endif 43 44#ifdef __GNUC__ 45# pragma GCC diagnostic ignored "-Wvariadic-macros" 46#endif 47 48#define TEST_PORT 9123 49#define TEST_PORT_2 9124 50#define TEST_PORT_3 9125 51 52#ifdef _WIN32 53# define TEST_PIPENAME "\\\\.\\pipe\\uv-test" 54# define TEST_PIPENAME_2 "\\\\.\\pipe\\uv-test2" 55# define TEST_PIPENAME_3 "\\\\.\\pipe\\uv-test3" 56#else 57# define TEST_PIPENAME "/tmp/uv-test-sock" 58# define TEST_PIPENAME_2 "/tmp/uv-test-sock2" 59# define TEST_PIPENAME_3 "/tmp/uv-test-sock3" 60#endif 61 62#ifdef _WIN32 63# include <io.h> 64# ifndef S_IRUSR 65# define S_IRUSR _S_IREAD 66# endif 67# ifndef S_IWUSR 68# define S_IWUSR _S_IWRITE 69# endif 70#endif 71 72#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 73 74#define container_of(ptr, type, member) \ 75 ((type *) ((char *) (ptr) - offsetof(type, member))) 76 77typedef enum { 78 TCP = 0, 79 UDP, 80 PIPE 81} stream_type; 82 83/* Die with fatal error. */ 84#define FATAL(msg) \ 85 do { \ 86 fprintf(stderr, \ 87 "Fatal error in %s on line %d: %s\n", \ 88 __FILE__, \ 89 __LINE__, \ 90 msg); \ 91 fflush(stderr); \ 92 abort(); \ 93 } while (0) 94 95/* Have our own assert, so we are sure it does not get optimized away in 96 * a release build. 97 */ 98#define ASSERT(expr) \ 99 do { \ 100 if (!(expr)) { \ 101 fprintf(stderr, \ 102 "Assertion failed in %s on line %d: %s\n", \ 103 __FILE__, \ 104 __LINE__, \ 105 #expr); \ 106 abort(); \ 107 } \ 108 } while (0) 109 110#define ASSERT_BASE(a, operator, b, type, conv) \ 111 do { \ 112 volatile type eval_a = (type) (a); \ 113 volatile type eval_b = (type) (b); \ 114 if (!(eval_a operator eval_b)) { \ 115 fprintf(stderr, \ 116 "Assertion failed in %s on line %d: `%s %s %s` " \ 117 "(%"conv" %s %"conv")\n", \ 118 __FILE__, \ 119 __LINE__, \ 120 #a, \ 121 #operator, \ 122 #b, \ 123 eval_a, \ 124 #operator, \ 125 eval_b); \ 126 abort(); \ 127 } \ 128 } while (0) 129 130#define ASSERT_BASE_STR(expr, a, operator, b, type, conv) \ 131 do { \ 132 if (!(expr)) { \ 133 fprintf(stderr, \ 134 "Assertion failed in %s on line %d: `%s %s %s` " \ 135 "(%"conv" %s %"conv")\n", \ 136 __FILE__, \ 137 __LINE__, \ 138 #a, \ 139 #operator, \ 140 #b, \ 141 (type)a, \ 142 #operator, \ 143 (type)b); \ 144 abort(); \ 145 } \ 146 } while (0) 147 148#define ASSERT_BASE_LEN(expr, a, operator, b, conv, len) \ 149 do { \ 150 if (!(expr)) { \ 151 fprintf(stderr, \ 152 "Assertion failed in %s on line %d: `%s %s %s` " \ 153 "(%.*"#conv" %s %.*"#conv")\n", \ 154 __FILE__, \ 155 __LINE__, \ 156 #a, \ 157 #operator, \ 158 #b, \ 159 (int)len, \ 160 a, \ 161 #operator, \ 162 (int)len, \ 163 b); \ 164 abort(); \ 165 } \ 166 } while (0) 167 168#define ASSERT_BASE_HEX(expr, a, operator, b, size) \ 169 do { \ 170 if (!(expr)) { \ 171 int i; \ 172 unsigned char* a_ = (unsigned char*)a; \ 173 unsigned char* b_ = (unsigned char*)b; \ 174 fprintf(stderr, \ 175 "Assertion failed in %s on line %d: `%s %s %s` (", \ 176 __FILE__, \ 177 __LINE__, \ 178 #a, \ 179 #operator, \ 180 #b); \ 181 for (i = 0; i < size; ++i) { \ 182 if (i > 0) fprintf(stderr, ":"); \ 183 fprintf(stderr, "%02X", a_[i]); \ 184 } \ 185 fprintf(stderr, " %s ", #operator); \ 186 for (i = 0; i < size; ++i) { \ 187 if (i > 0) fprintf(stderr, ":"); \ 188 fprintf(stderr, "%02X", b_[i]); \ 189 } \ 190 fprintf(stderr, ")\n"); \ 191 abort(); \ 192 } \ 193 } while (0) 194 195#define ASSERT_EQ(a, b) ASSERT_BASE(a, ==, b, int64_t, PRId64) 196#define ASSERT_GE(a, b) ASSERT_BASE(a, >=, b, int64_t, PRId64) 197#define ASSERT_GT(a, b) ASSERT_BASE(a, >, b, int64_t, PRId64) 198#define ASSERT_LE(a, b) ASSERT_BASE(a, <=, b, int64_t, PRId64) 199#define ASSERT_LT(a, b) ASSERT_BASE(a, <, b, int64_t, PRId64) 200#define ASSERT_NE(a, b) ASSERT_BASE(a, !=, b, int64_t, PRId64) 201#define ASSERT_OK(a) ASSERT_BASE(a, ==, 0, int64_t, PRId64) 202 203#define ASSERT_UINT64_EQ(a, b) ASSERT_BASE(a, ==, b, uint64_t, PRIu64) 204#define ASSERT_UINT64_GE(a, b) ASSERT_BASE(a, >=, b, uint64_t, PRIu64) 205#define ASSERT_UINT64_GT(a, b) ASSERT_BASE(a, >, b, uint64_t, PRIu64) 206#define ASSERT_UINT64_LE(a, b) ASSERT_BASE(a, <=, b, uint64_t, PRIu64) 207#define ASSERT_UINT64_LT(a, b) ASSERT_BASE(a, <, b, uint64_t, PRIu64) 208#define ASSERT_UINT64_NE(a, b) ASSERT_BASE(a, !=, b, uint64_t, PRIu64) 209 210#define ASSERT_DOUBLE_EQ(a, b) ASSERT_BASE(a, ==, b, double, "f") 211#define ASSERT_DOUBLE_GE(a, b) ASSERT_BASE(a, >=, b, double, "f") 212#define ASSERT_DOUBLE_GT(a, b) ASSERT_BASE(a, >, b, double, "f") 213#define ASSERT_DOUBLE_LE(a, b) ASSERT_BASE(a, <=, b, double, "f") 214#define ASSERT_DOUBLE_LT(a, b) ASSERT_BASE(a, <, b, double, "f") 215#define ASSERT_DOUBLE_NE(a, b) ASSERT_BASE(a, !=, b, double, "f") 216 217#define ASSERT_STR_EQ(a, b) \ 218 ASSERT_BASE_STR(strcmp(a, b) == 0, a, == , b, char*, "s") 219 220#define ASSERT_STR_NE(a, b) \ 221 ASSERT_BASE_STR(strcmp(a, b) != 0, a, !=, b, char*, "s") 222 223#define ASSERT_MEM_EQ(a, b, size) \ 224 ASSERT_BASE_LEN(memcmp(a, b, size) == 0, a, ==, b, s, size) 225 226#define ASSERT_MEM_NE(a, b, size) \ 227 ASSERT_BASE_LEN(memcmp(a, b, size) != 0, a, !=, b, s, size) 228 229#define ASSERT_MEM_HEX_EQ(a, b, size) \ 230 ASSERT_BASE_HEX(memcmp(a, b, size) == 0, a, ==, b, size) 231 232#define ASSERT_MEM_HEX_NE(a, b, size) \ 233 ASSERT_BASE_HEX(memcmp(a, b, size) != 0, a, !=, b, size) 234 235#define ASSERT_NULL(a) \ 236 ASSERT_BASE(a, ==, NULL, void*, "p") 237 238#define ASSERT_NOT_NULL(a) \ 239 ASSERT_BASE(a, !=, NULL, void*, "p") 240 241#define ASSERT_PTR_EQ(a, b) \ 242 ASSERT_BASE(a, ==, b, void*, "p") 243 244#define ASSERT_PTR_NE(a, b) \ 245 ASSERT_BASE(a, !=, b, void*, "p") 246 247#define ASSERT_PTR_LT(a, b) \ 248 ASSERT_BASE(a, <, b, void*, "p") 249 250/* This macro cleans up the event loop. This is used to avoid valgrind 251 * warnings about memory being "leaked" by the event loop. 252 */ 253#define MAKE_VALGRIND_HAPPY(loop) \ 254 do { \ 255 close_loop(loop); \ 256 ASSERT_EQ(0, uv_loop_close(loop)); \ 257 uv_library_shutdown(); \ 258 } while (0) 259 260/* Just sugar for wrapping the main() for a task or helper. */ 261#define TEST_IMPL(name) \ 262 int run_test_##name(void); \ 263 int run_test_##name(void) 264 265#define BENCHMARK_IMPL(name) \ 266 int run_benchmark_##name(void); \ 267 int run_benchmark_##name(void) 268 269#define HELPER_IMPL(name) \ 270 int run_helper_##name(void); \ 271 int run_helper_##name(void) 272 273/* Format big numbers nicely. */ 274char* fmt(char (*buf)[32], double d); 275 276/* Reserved test exit codes. */ 277enum test_status { 278 TEST_OK = 0, 279 TEST_SKIP = 7 280}; 281 282#define RETURN_OK() \ 283 do { \ 284 return TEST_OK; \ 285 } while (0) 286 287#define RETURN_SKIP(explanation) \ 288 do { \ 289 fprintf(stderr, "%s\n", explanation); \ 290 fflush(stderr); \ 291 return TEST_SKIP; \ 292 } while (0) 293 294#if !defined(_WIN32) 295 296# define TEST_FILE_LIMIT(num) \ 297 do { \ 298 struct rlimit lim; \ 299 lim.rlim_cur = (num); \ 300 lim.rlim_max = lim.rlim_cur; \ 301 if (setrlimit(RLIMIT_NOFILE, &lim)) \ 302 RETURN_SKIP("File descriptor limit too low."); \ 303 } while (0) 304 305#else /* defined(_WIN32) */ 306 307# define TEST_FILE_LIMIT(num) do {} while (0) 308 309#endif 310 311#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900 312extern int snprintf(char*, size_t, const char*, ...); 313#endif 314 315#if defined(__clang__) || \ 316 defined(__GNUC__) || \ 317 defined(__INTEL_COMPILER) 318# define UNUSED __attribute__((unused)) 319#else 320# define UNUSED 321#endif 322 323#if defined(_WIN32) 324#define notify_parent_process() ((void) 0) 325#else 326extern void notify_parent_process(void); 327#endif 328 329/* Fully close a loop */ 330static void close_walk_cb(uv_handle_t* handle, void* arg) { 331 if (!uv_is_closing(handle)) 332 uv_close(handle, NULL); 333} 334 335UNUSED static void close_loop(uv_loop_t* loop) { 336 uv_walk(loop, close_walk_cb, NULL); 337 uv_run(loop, UV_RUN_DEFAULT); 338} 339 340UNUSED static int can_ipv6(void) { 341 uv_interface_address_t* addr; 342 int supported; 343 int count; 344 int i; 345 346 if (uv_interface_addresses(&addr, &count)) 347 return 0; /* Assume no IPv6 support on failure. */ 348 349 supported = 0; 350 for (i = 0; supported == 0 && i < count; i += 1) 351 supported = (AF_INET6 == addr[i].address.address6.sin6_family); 352 353 uv_free_interface_addresses(addr, count); 354 return supported; 355} 356 357#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) 358# define NO_FS_EVENTS "Filesystem watching not supported on this platform." 359#endif 360 361#if defined(__MSYS__) 362# define NO_SEND_HANDLE_ON_PIPE \ 363 "MSYS2 runtime does not support sending handles on pipes." 364#elif defined(__CYGWIN__) 365# define NO_SEND_HANDLE_ON_PIPE \ 366 "Cygwin runtime does not support sending handles on pipes." 367#endif 368 369#if defined(__MSYS__) 370# define NO_SELF_CONNECT \ 371 "MSYS2 runtime hangs on listen+connect in same process." 372#elif defined(__CYGWIN__) 373# define NO_SELF_CONNECT \ 374 "Cygwin runtime hangs on listen+connect in same process." 375#endif 376 377#if !defined(__linux__) && \ 378 !(defined(__FreeBSD__) && __FreeBSD_version >= 1301000) && \ 379 !defined(_WIN32) 380# define NO_CPU_AFFINITY \ 381 "affinity not supported on this platform." 382#endif 383 384#endif /* TASK_H_ */ 385