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