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 #include <errno.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #ifdef _WIN32 27 # include <io.h> 28 #else 29 # include <unistd.h> 30 #endif 31 32 #include "uv.h" 33 #include "runner.h" 34 #include "task.h" 35 36 /* Actual tests and helpers are defined in test-list.h */ 37 #include "test-list.h" 38 39 #ifdef __MVS__ 40 #include "zos-base.h" 41 /* Initialize environment and zoslib */ 42 __attribute__((constructor)) void init() { 43 zoslib_config_t config; 44 init_zoslib_config(&config); 45 init_zoslib(config); 46 } 47 #endif 48 49 int ipc_helper(int listen_after_write); 50 int ipc_helper_heavy_traffic_deadlock_bug(void); 51 int ipc_helper_tcp_connection(void); 52 int ipc_send_recv_helper(void); 53 int ipc_helper_bind_twice(void); 54 int ipc_helper_send_zero(void); 55 int stdio_over_pipes_helper(void); 56 void spawn_stdin_stdout(void); 57 void process_title_big_argv(void); 58 int spawn_tcp_server_helper(void); 59 60 static int maybe_run_test(int argc, char **argv); 61 62 #ifdef _WIN32 63 typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE); 64 #endif 65 66 67 int main(int argc, char **argv) { 68 #ifndef _WIN32 69 if (0 == geteuid() && NULL == getenv("UV_RUN_AS_ROOT")) { 70 fprintf(stderr, "The libuv test suite cannot be run as root.\n"); 71 return EXIT_FAILURE; 72 } 73 #endif 74 75 platform_init(argc, argv); 76 argv = uv_setup_args(argc, argv); 77 78 switch (argc) { 79 case 1: return run_tests(0); 80 case 2: return maybe_run_test(argc, argv); 81 case 3: return run_test_part(argv[1], argv[2]); 82 case 4: return maybe_run_test(argc, argv); 83 default: 84 fprintf(stderr, "Too many arguments.\n"); 85 fflush(stderr); 86 return EXIT_FAILURE; 87 } 88 89 #ifndef __SUNPRO_C 90 return EXIT_SUCCESS; 91 #endif 92 } 93 94 95 static int maybe_run_test(int argc, char **argv) { 96 if (strcmp(argv[1], "--list") == 0) { 97 print_tests(stdout); 98 return 0; 99 } 100 101 if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) { 102 return ipc_helper(0); 103 } 104 105 if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) { 106 return ipc_helper(1); 107 } 108 109 if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) { 110 return ipc_helper_heavy_traffic_deadlock_bug(); 111 } 112 113 if (strcmp(argv[1], "ipc_send_recv_helper") == 0) { 114 return ipc_send_recv_helper(); 115 } 116 117 if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) { 118 return ipc_helper_tcp_connection(); 119 } 120 121 if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) { 122 return ipc_helper_bind_twice(); 123 } 124 125 if (strcmp(argv[1], "ipc_helper_send_zero") == 0) { 126 return ipc_helper_send_zero(); 127 } 128 129 if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) { 130 return stdio_over_pipes_helper(); 131 } 132 133 if (strcmp(argv[1], "spawn_helper1") == 0) { 134 notify_parent_process(); 135 return 1; 136 } 137 138 if (strcmp(argv[1], "spawn_helper2") == 0) { 139 notify_parent_process(); 140 printf("hello world\n"); 141 return 1; 142 } 143 144 if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) { 145 notify_parent_process(); 146 return spawn_tcp_server_helper(); 147 } 148 149 if (strcmp(argv[1], "spawn_helper3") == 0) { 150 char buffer[256]; 151 notify_parent_process(); 152 ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin)); 153 buffer[sizeof(buffer) - 1] = '\0'; 154 fputs(buffer, stdout); 155 return 1; 156 } 157 158 if (strcmp(argv[1], "spawn_helper4") == 0) { 159 notify_parent_process(); 160 /* Never surrender, never return! */ 161 for (;;) uv_sleep(10000); 162 } 163 164 if (strcmp(argv[1], "spawn_helper5") == 0) { 165 const char out[] = "fourth stdio!\n"; 166 notify_parent_process(); 167 { 168 #ifdef _WIN32 169 DWORD bytes; 170 WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL); 171 #else 172 ssize_t r; 173 174 do 175 r = write(3, out, sizeof(out) - 1); 176 while (r == -1 && errno == EINTR); 177 178 fsync(3); 179 #endif 180 } 181 return 1; 182 } 183 184 if (strcmp(argv[1], "spawn_helper6") == 0) { 185 int r; 186 187 notify_parent_process(); 188 189 r = fprintf(stdout, "hello world\n"); 190 ASSERT(r > 0); 191 192 r = fprintf(stderr, "hello errworld\n"); 193 ASSERT(r > 0); 194 195 return 1; 196 } 197 198 if (strcmp(argv[1], "spawn_helper7") == 0) { 199 int r; 200 char *test; 201 202 notify_parent_process(); 203 204 /* Test if the test value from the parent is still set */ 205 test = getenv("ENV_TEST"); 206 ASSERT_NOT_NULL(test); 207 208 r = fprintf(stdout, "%s", test); 209 ASSERT(r > 0); 210 211 return 1; 212 } 213 214 if (strcmp(argv[1], "spawn_helper8") == 0) { 215 uv_os_fd_t closed_fd; 216 uv_os_fd_t open_fd; 217 #ifdef _WIN32 218 DWORD flags; 219 HMODULE kernelbase_module; 220 sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */ 221 #endif 222 notify_parent_process(); 223 ASSERT(sizeof(closed_fd) == read(0, &closed_fd, sizeof(closed_fd))); 224 ASSERT(sizeof(open_fd) == read(0, &open_fd, sizeof(open_fd))); 225 #ifdef _WIN32 226 ASSERT((intptr_t) closed_fd > 0); 227 ASSERT((intptr_t) open_fd > 0); 228 ASSERT(0 != GetHandleInformation(open_fd, &flags)); 229 kernelbase_module = GetModuleHandleA("kernelbase.dll"); 230 pCompareObjectHandles = (sCompareObjectHandles) 231 GetProcAddress(kernelbase_module, "CompareObjectHandles"); 232 ASSERT(pCompareObjectHandles == NULL || !pCompareObjectHandles(open_fd, closed_fd)); 233 #else 234 ASSERT(open_fd > 2); 235 ASSERT(closed_fd > 2); 236 # if defined(__PASE__) /* On IBMi PASE, write() returns 1 */ 237 ASSERT(1 == write(closed_fd, "x", 1)); 238 # else 239 ASSERT(-1 == write(closed_fd, "x", 1)); 240 # endif /* !__PASE__ */ 241 #endif 242 return 1; 243 } 244 245 if (strcmp(argv[1], "spawn_helper9") == 0) { 246 notify_parent_process(); 247 spawn_stdin_stdout(); 248 return 1; 249 } 250 251 #ifndef _WIN32 252 if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) { 253 uv_uid_t uid = atoi(argv[2]); 254 uv_gid_t gid = atoi(argv[3]); 255 256 ASSERT(uid == getuid()); 257 ASSERT(gid == getgid()); 258 notify_parent_process(); 259 260 return 1; 261 } 262 #endif /* !_WIN32 */ 263 264 if (strcmp(argv[1], "process_title_big_argv_helper") == 0) { 265 notify_parent_process(); 266 process_title_big_argv(); 267 return 0; 268 } 269 270 return run_test(argv[1], 0, 1); 271 } 272