10e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
20e552da7Schristos *
30e552da7Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos * of this software and associated documentation files (the "Software"), to
50e552da7Schristos * deal in the Software without restriction, including without limitation the
60e552da7Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos * furnished to do so, subject to the following conditions:
90e552da7Schristos *
100e552da7Schristos * The above copyright notice and this permission notice shall be included in
110e552da7Schristos * all copies or substantial portions of the Software.
120e552da7Schristos *
130e552da7Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos * IN THE SOFTWARE.
200e552da7Schristos */
210e552da7Schristos
220e552da7Schristos #include <errno.h>
230e552da7Schristos #include <stdio.h>
240e552da7Schristos #include <string.h>
250e552da7Schristos
260e552da7Schristos #ifdef _WIN32
270e552da7Schristos # include <io.h>
280e552da7Schristos #else
290e552da7Schristos # include <unistd.h>
300e552da7Schristos #endif
310e552da7Schristos
320e552da7Schristos #include "uv.h"
330e552da7Schristos #include "runner.h"
340e552da7Schristos #include "task.h"
350e552da7Schristos
360e552da7Schristos /* Actual tests and helpers are defined in test-list.h */
370e552da7Schristos #include "test-list.h"
380e552da7Schristos
39*5f2f4271Schristos #ifdef __MVS__
40*5f2f4271Schristos #include "zos-base.h"
41*5f2f4271Schristos /* Initialize environment and zoslib */
init()42*5f2f4271Schristos __attribute__((constructor)) void init() {
43*5f2f4271Schristos zoslib_config_t config;
44*5f2f4271Schristos init_zoslib_config(&config);
45*5f2f4271Schristos init_zoslib(config);
46*5f2f4271Schristos }
47*5f2f4271Schristos #endif
48*5f2f4271Schristos
490e552da7Schristos int ipc_helper(int listen_after_write);
500e552da7Schristos int ipc_helper_heavy_traffic_deadlock_bug(void);
510e552da7Schristos int ipc_helper_tcp_connection(void);
520e552da7Schristos int ipc_send_recv_helper(void);
530e552da7Schristos int ipc_helper_bind_twice(void);
540e552da7Schristos int ipc_helper_send_zero(void);
550e552da7Schristos int stdio_over_pipes_helper(void);
560e552da7Schristos void spawn_stdin_stdout(void);
570e552da7Schristos void process_title_big_argv(void);
580e552da7Schristos int spawn_tcp_server_helper(void);
590e552da7Schristos
600e552da7Schristos static int maybe_run_test(int argc, char **argv);
610e552da7Schristos
62*5f2f4271Schristos #ifdef _WIN32
63*5f2f4271Schristos typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE);
64*5f2f4271Schristos #endif
65*5f2f4271Schristos
660e552da7Schristos
main(int argc,char ** argv)670e552da7Schristos int main(int argc, char **argv) {
680e552da7Schristos #ifndef _WIN32
690e552da7Schristos if (0 == geteuid() && NULL == getenv("UV_RUN_AS_ROOT")) {
700e552da7Schristos fprintf(stderr, "The libuv test suite cannot be run as root.\n");
710e552da7Schristos return EXIT_FAILURE;
720e552da7Schristos }
730e552da7Schristos #endif
740e552da7Schristos
750e552da7Schristos platform_init(argc, argv);
760e552da7Schristos argv = uv_setup_args(argc, argv);
770e552da7Schristos
780e552da7Schristos switch (argc) {
790e552da7Schristos case 1: return run_tests(0);
800e552da7Schristos case 2: return maybe_run_test(argc, argv);
810e552da7Schristos case 3: return run_test_part(argv[1], argv[2]);
820e552da7Schristos case 4: return maybe_run_test(argc, argv);
830e552da7Schristos default:
840e552da7Schristos fprintf(stderr, "Too many arguments.\n");
850e552da7Schristos fflush(stderr);
860e552da7Schristos return EXIT_FAILURE;
870e552da7Schristos }
880e552da7Schristos
890e552da7Schristos #ifndef __SUNPRO_C
900e552da7Schristos return EXIT_SUCCESS;
910e552da7Schristos #endif
920e552da7Schristos }
930e552da7Schristos
940e552da7Schristos
maybe_run_test(int argc,char ** argv)950e552da7Schristos static int maybe_run_test(int argc, char **argv) {
960e552da7Schristos if (strcmp(argv[1], "--list") == 0) {
970e552da7Schristos print_tests(stdout);
980e552da7Schristos return 0;
990e552da7Schristos }
1000e552da7Schristos
1010e552da7Schristos if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
1020e552da7Schristos return ipc_helper(0);
1030e552da7Schristos }
1040e552da7Schristos
1050e552da7Schristos if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
1060e552da7Schristos return ipc_helper(1);
1070e552da7Schristos }
1080e552da7Schristos
1090e552da7Schristos if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
1100e552da7Schristos return ipc_helper_heavy_traffic_deadlock_bug();
1110e552da7Schristos }
1120e552da7Schristos
1130e552da7Schristos if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
1140e552da7Schristos return ipc_send_recv_helper();
1150e552da7Schristos }
1160e552da7Schristos
1170e552da7Schristos if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
1180e552da7Schristos return ipc_helper_tcp_connection();
1190e552da7Schristos }
1200e552da7Schristos
1210e552da7Schristos if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
1220e552da7Schristos return ipc_helper_bind_twice();
1230e552da7Schristos }
1240e552da7Schristos
1250e552da7Schristos if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
1260e552da7Schristos return ipc_helper_send_zero();
1270e552da7Schristos }
1280e552da7Schristos
1290e552da7Schristos if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
1300e552da7Schristos return stdio_over_pipes_helper();
1310e552da7Schristos }
1320e552da7Schristos
1330e552da7Schristos if (strcmp(argv[1], "spawn_helper1") == 0) {
1340e552da7Schristos notify_parent_process();
1350e552da7Schristos return 1;
1360e552da7Schristos }
1370e552da7Schristos
1380e552da7Schristos if (strcmp(argv[1], "spawn_helper2") == 0) {
1390e552da7Schristos notify_parent_process();
1400e552da7Schristos printf("hello world\n");
1410e552da7Schristos return 1;
1420e552da7Schristos }
1430e552da7Schristos
1440e552da7Schristos if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
1450e552da7Schristos notify_parent_process();
1460e552da7Schristos return spawn_tcp_server_helper();
1470e552da7Schristos }
1480e552da7Schristos
1490e552da7Schristos if (strcmp(argv[1], "spawn_helper3") == 0) {
1500e552da7Schristos char buffer[256];
1510e552da7Schristos notify_parent_process();
1520e552da7Schristos ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
1530e552da7Schristos buffer[sizeof(buffer) - 1] = '\0';
1540e552da7Schristos fputs(buffer, stdout);
1550e552da7Schristos return 1;
1560e552da7Schristos }
1570e552da7Schristos
1580e552da7Schristos if (strcmp(argv[1], "spawn_helper4") == 0) {
1590e552da7Schristos notify_parent_process();
1600e552da7Schristos /* Never surrender, never return! */
161*5f2f4271Schristos for (;;) uv_sleep(10000);
1620e552da7Schristos }
1630e552da7Schristos
1640e552da7Schristos if (strcmp(argv[1], "spawn_helper5") == 0) {
1650e552da7Schristos const char out[] = "fourth stdio!\n";
1660e552da7Schristos notify_parent_process();
1670e552da7Schristos {
1680e552da7Schristos #ifdef _WIN32
1690e552da7Schristos DWORD bytes;
1700e552da7Schristos WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
1710e552da7Schristos #else
1720e552da7Schristos ssize_t r;
1730e552da7Schristos
1740e552da7Schristos do
1750e552da7Schristos r = write(3, out, sizeof(out) - 1);
1760e552da7Schristos while (r == -1 && errno == EINTR);
1770e552da7Schristos
1780e552da7Schristos fsync(3);
1790e552da7Schristos #endif
1800e552da7Schristos }
1810e552da7Schristos return 1;
1820e552da7Schristos }
1830e552da7Schristos
1840e552da7Schristos if (strcmp(argv[1], "spawn_helper6") == 0) {
1850e552da7Schristos int r;
1860e552da7Schristos
1870e552da7Schristos notify_parent_process();
1880e552da7Schristos
1890e552da7Schristos r = fprintf(stdout, "hello world\n");
1900e552da7Schristos ASSERT(r > 0);
1910e552da7Schristos
1920e552da7Schristos r = fprintf(stderr, "hello errworld\n");
1930e552da7Schristos ASSERT(r > 0);
1940e552da7Schristos
1950e552da7Schristos return 1;
1960e552da7Schristos }
1970e552da7Schristos
1980e552da7Schristos if (strcmp(argv[1], "spawn_helper7") == 0) {
1990e552da7Schristos int r;
2000e552da7Schristos char *test;
2010e552da7Schristos
2020e552da7Schristos notify_parent_process();
2030e552da7Schristos
2040e552da7Schristos /* Test if the test value from the parent is still set */
2050e552da7Schristos test = getenv("ENV_TEST");
206*5f2f4271Schristos ASSERT_NOT_NULL(test);
2070e552da7Schristos
2080e552da7Schristos r = fprintf(stdout, "%s", test);
2090e552da7Schristos ASSERT(r > 0);
2100e552da7Schristos
2110e552da7Schristos return 1;
2120e552da7Schristos }
2130e552da7Schristos
2140e552da7Schristos if (strcmp(argv[1], "spawn_helper8") == 0) {
215*5f2f4271Schristos uv_os_fd_t closed_fd;
216*5f2f4271Schristos uv_os_fd_t open_fd;
217*5f2f4271Schristos #ifdef _WIN32
218*5f2f4271Schristos DWORD flags;
219*5f2f4271Schristos HMODULE kernelbase_module;
220*5f2f4271Schristos sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */
221*5f2f4271Schristos #endif
2220e552da7Schristos notify_parent_process();
223*5f2f4271Schristos ASSERT(sizeof(closed_fd) == read(0, &closed_fd, sizeof(closed_fd)));
224*5f2f4271Schristos ASSERT(sizeof(open_fd) == read(0, &open_fd, sizeof(open_fd)));
225*5f2f4271Schristos #ifdef _WIN32
226*5f2f4271Schristos ASSERT((intptr_t) closed_fd > 0);
227*5f2f4271Schristos ASSERT((intptr_t) open_fd > 0);
228*5f2f4271Schristos ASSERT(0 != GetHandleInformation(open_fd, &flags));
229*5f2f4271Schristos kernelbase_module = GetModuleHandleA("kernelbase.dll");
230*5f2f4271Schristos pCompareObjectHandles = (sCompareObjectHandles)
231*5f2f4271Schristos GetProcAddress(kernelbase_module, "CompareObjectHandles");
232*5f2f4271Schristos ASSERT(pCompareObjectHandles == NULL || !pCompareObjectHandles(open_fd, closed_fd));
2330e552da7Schristos #else
234*5f2f4271Schristos ASSERT(open_fd > 2);
235*5f2f4271Schristos ASSERT(closed_fd > 2);
236*5f2f4271Schristos # if defined(__PASE__) /* On IBMi PASE, write() returns 1 */
237*5f2f4271Schristos ASSERT(1 == write(closed_fd, "x", 1));
238*5f2f4271Schristos # else
239*5f2f4271Schristos ASSERT(-1 == write(closed_fd, "x", 1));
2400e552da7Schristos # endif /* !__PASE__ */
241*5f2f4271Schristos #endif
2420e552da7Schristos return 1;
2430e552da7Schristos }
2440e552da7Schristos
2450e552da7Schristos if (strcmp(argv[1], "spawn_helper9") == 0) {
2460e552da7Schristos notify_parent_process();
2470e552da7Schristos spawn_stdin_stdout();
2480e552da7Schristos return 1;
2490e552da7Schristos }
2500e552da7Schristos
2510e552da7Schristos #ifndef _WIN32
2520e552da7Schristos if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
2530e552da7Schristos uv_uid_t uid = atoi(argv[2]);
2540e552da7Schristos uv_gid_t gid = atoi(argv[3]);
2550e552da7Schristos
2560e552da7Schristos ASSERT(uid == getuid());
2570e552da7Schristos ASSERT(gid == getgid());
2580e552da7Schristos notify_parent_process();
2590e552da7Schristos
2600e552da7Schristos return 1;
2610e552da7Schristos }
2620e552da7Schristos #endif /* !_WIN32 */
2630e552da7Schristos
2640e552da7Schristos if (strcmp(argv[1], "process_title_big_argv_helper") == 0) {
2650e552da7Schristos notify_parent_process();
2660e552da7Schristos process_title_big_argv();
2670e552da7Schristos return 0;
2680e552da7Schristos }
2690e552da7Schristos
2700e552da7Schristos return run_test(argv[1], 0, 1);
2710e552da7Schristos }
272