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 platform_init(argc, argv);
69 argv = uv_setup_args(argc, argv);
70
71 switch (argc) {
72 case 1: return run_tests(0);
73 case 2: return maybe_run_test(argc, argv);
74 case 3: return run_test_part(argv[1], argv[2]);
75 case 4: return maybe_run_test(argc, argv);
76 default:
77 fprintf(stderr, "Too many arguments.\n");
78 fflush(stderr);
79 return EXIT_FAILURE;
80 }
81
82 #ifndef __SUNPRO_C
83 return EXIT_SUCCESS;
84 #endif
85 }
86
87
maybe_run_test(int argc,char ** argv)88 static int maybe_run_test(int argc, char **argv) {
89 if (strcmp(argv[1], "--list") == 0) {
90 print_tests(stdout);
91 return 0;
92 }
93
94 if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
95 return ipc_helper(0);
96 }
97
98 if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
99 return ipc_helper(1);
100 }
101
102 if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
103 return ipc_helper_heavy_traffic_deadlock_bug();
104 }
105
106 if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
107 return ipc_send_recv_helper();
108 }
109
110 if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
111 return ipc_helper_tcp_connection();
112 }
113
114 if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
115 return ipc_helper_bind_twice();
116 }
117
118 if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
119 return ipc_helper_send_zero();
120 }
121
122 if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
123 return stdio_over_pipes_helper();
124 }
125
126 if (strcmp(argv[1], "spawn_helper1") == 0) {
127 notify_parent_process();
128 return 1;
129 }
130
131 if (strcmp(argv[1], "spawn_helper2") == 0) {
132 notify_parent_process();
133 printf("hello world\n");
134 return 1;
135 }
136
137 if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
138 notify_parent_process();
139 return spawn_tcp_server_helper();
140 }
141
142 if (strcmp(argv[1], "spawn_helper3") == 0) {
143 char buffer[256];
144 notify_parent_process();
145 ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
146 buffer[sizeof(buffer) - 1] = '\0';
147 fputs(buffer, stdout);
148 return 1;
149 }
150
151 if (strcmp(argv[1], "spawn_helper4") == 0) {
152 notify_parent_process();
153 /* Never surrender, never return! */
154 for (;;) uv_sleep(10000);
155 }
156
157 if (strcmp(argv[1], "spawn_helper5") == 0) {
158 const char out[] = "fourth stdio!\n";
159 notify_parent_process();
160 {
161 #ifdef _WIN32
162 DWORD bytes;
163 WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
164 #else
165 ssize_t r;
166
167 do
168 r = write(3, out, sizeof(out) - 1);
169 while (r == -1 && errno == EINTR);
170
171 fsync(3);
172 #endif
173 }
174 return 1;
175 }
176
177 if (strcmp(argv[1], "spawn_helper6") == 0) {
178 int r;
179
180 notify_parent_process();
181
182 r = fprintf(stdout, "hello world\n");
183 ASSERT(r > 0);
184
185 r = fprintf(stderr, "hello errworld\n");
186 ASSERT(r > 0);
187
188 return 1;
189 }
190
191 if (strcmp(argv[1], "spawn_helper7") == 0) {
192 int r;
193 char *test;
194
195 notify_parent_process();
196
197 /* Test if the test value from the parent is still set */
198 test = getenv("ENV_TEST");
199 ASSERT_NOT_NULL(test);
200
201 r = fprintf(stdout, "%s", test);
202 ASSERT(r > 0);
203
204 return 1;
205 }
206
207 if (strcmp(argv[1], "spawn_helper8") == 0) {
208 uv_os_fd_t closed_fd;
209 uv_os_fd_t open_fd;
210 #ifdef _WIN32
211 DWORD flags;
212 HMODULE kernelbase_module;
213 sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */
214 #endif
215 notify_parent_process();
216 ASSERT(sizeof(closed_fd) == read(0, &closed_fd, sizeof(closed_fd)));
217 ASSERT(sizeof(open_fd) == read(0, &open_fd, sizeof(open_fd)));
218 #ifdef _WIN32
219 ASSERT((intptr_t) closed_fd > 0);
220 ASSERT((intptr_t) open_fd > 0);
221 ASSERT(0 != GetHandleInformation(open_fd, &flags));
222 kernelbase_module = GetModuleHandleA("kernelbase.dll");
223 pCompareObjectHandles = (sCompareObjectHandles)
224 GetProcAddress(kernelbase_module, "CompareObjectHandles");
225 ASSERT(pCompareObjectHandles == NULL || !pCompareObjectHandles(open_fd, closed_fd));
226 #else
227 ASSERT(open_fd > 2);
228 ASSERT(closed_fd > 2);
229 # if defined(__PASE__) /* On IBMi PASE, write() returns 1 */
230 ASSERT(1 == write(closed_fd, "x", 1));
231 # else
232 ASSERT(-1 == write(closed_fd, "x", 1));
233 # endif /* !__PASE__ */
234 #endif
235 return 1;
236 }
237
238 if (strcmp(argv[1], "spawn_helper9") == 0) {
239 notify_parent_process();
240 spawn_stdin_stdout();
241 return 1;
242 }
243
244 #ifndef _WIN32
245 if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
246 uv_uid_t uid = atoi(argv[2]);
247 uv_gid_t gid = atoi(argv[3]);
248
249 ASSERT(uid == getuid());
250 ASSERT(gid == getgid());
251 notify_parent_process();
252
253 return 1;
254 }
255 #endif /* !_WIN32 */
256
257 if (strcmp(argv[1], "process_title_big_argv_helper") == 0) {
258 notify_parent_process();
259 process_title_big_argv();
260 return 0;
261 }
262
263 return run_test(argv[1], 0, 1);
264 }
265