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 */
init()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
main(int argc,char ** argv)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
maybe_run_test(int argc,char ** argv)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