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
39int ipc_helper(int listen_after_write);
40int ipc_helper_heavy_traffic_deadlock_bug(void);
41int ipc_helper_tcp_connection(void);
42int ipc_helper_closed_handle(void);
43int ipc_send_recv_helper(void);
44int ipc_helper_bind_twice(void);
45int ipc_helper_send_zero(void);
46int stdio_over_pipes_helper(void);
47void spawn_stdin_stdout(void);
48int spawn_tcp_server_helper(void);
49
50static int maybe_run_test(int argc, char **argv);
51
52
53int main(int argc, char **argv) {
54 if (platform_init(argc, argv))
55 return EXIT_FAILURE;
56
57 argv = uv_setup_args(argc, argv);
58
59 switch (argc) {
60 case 1: return run_tests(0);
61 case 2: return maybe_run_test(argc, argv);
62 case 3: return run_test_part(argv[1], argv[2]);
63 case 4: return maybe_run_test(argc, argv);
64 default:
65 fprintf(stderr, "Too many arguments.\n");
66 fflush(stderr);
67 return EXIT_FAILURE;
68 }
69
70#ifndef __SUNPRO_C
71 return EXIT_SUCCESS;
72#endif
73}
74
75
76static int maybe_run_test(int argc, char **argv) {
77 if (strcmp(argv[1], "--list") == 0) {
78 print_tests(stdout);
79 return 0;
80 }
81
82 if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
83 return ipc_helper(0);
84 }
85
86 if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
87 return ipc_helper(1);
88 }
89
90 if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
91 return ipc_helper_heavy_traffic_deadlock_bug();
92 }
93
94 if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
95 return ipc_send_recv_helper();
96 }
97
98 if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
99 return ipc_helper_tcp_connection();
100 }
101
102 if (strcmp(argv[1], "ipc_helper_closed_handle") == 0) {
103 return ipc_helper_closed_handle();
104 }
105
106 if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
107 return ipc_helper_bind_twice();
108 }
109
110 if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
111 return ipc_helper_send_zero();
112 }
113
114 if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
115 return stdio_over_pipes_helper();
116 }
117
118 if (strcmp(argv[1], "spawn_helper1") == 0) {
119 notify_parent_process();
120 return 1;
121 }
122
123 if (strcmp(argv[1], "spawn_helper2") == 0) {
124 notify_parent_process();
125 printf("hello world\n");
126 return 1;
127 }
128
129 if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
130 notify_parent_process();
131 return spawn_tcp_server_helper();
132 }
133
134 if (strcmp(argv[1], "spawn_helper3") == 0) {
135 char buffer[256];
136 notify_parent_process();
137 ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
138 buffer[sizeof(buffer) - 1] = '\0';
139 fputs(buffer, stdout);
140 return 1;
141 }
142
143 if (strcmp(argv[1], "spawn_helper4") == 0) {
144 notify_parent_process();
145 /* Never surrender, never return! */
146 while (1) uv_sleep(10000);
147 }
148
149 if (strcmp(argv[1], "spawn_helper5") == 0) {
150 const char out[] = "fourth stdio!\n";
151 notify_parent_process();
152 {
153#ifdef _WIN32
154 DWORD bytes;
155 WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
156#else
157 ssize_t r;
158
159 do
160 r = write(3, out, sizeof(out) - 1);
161 while (r == -1 && errno == EINTR);
162
163 fsync(3);
164#endif
165 }
166 return 1;
167 }
168
169 if (strcmp(argv[1], "spawn_helper6") == 0) {
170 int r;
171
172 notify_parent_process();
173
174 r = fprintf(stdout, "hello world\n");
175 ASSERT(r > 0);
176
177 r = fprintf(stderr, "hello errworld\n");
178 ASSERT(r > 0);
179
180 return 1;
181 }
182
183 if (strcmp(argv[1], "spawn_helper7") == 0) {
184 int r;
185 char *test;
186
187 notify_parent_process();
188
189 /* Test if the test value from the parent is still set */
190 test = getenv("ENV_TEST");
191 ASSERT(test != NULL);
192
193 r = fprintf(stdout, "%s", test);
194 ASSERT(r > 0);
195
196 return 1;
197 }
198
199#ifndef _WIN32
200 if (strcmp(argv[1], "spawn_helper8") == 0) {
201 int fd;
202
203 notify_parent_process();
204 ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
205 ASSERT(fd > 2);
206 ASSERT(-1 == write(fd, "x", 1));
207
208 return 1;
209 }
210#endif /* !_WIN32 */
211
212 if (strcmp(argv[1], "spawn_helper9") == 0) {
213 notify_parent_process();
214 spawn_stdin_stdout();
215 return 1;
216 }
217
218#ifndef _WIN32
219 if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
220 uv_uid_t uid = atoi(argv[2]);
221 uv_gid_t gid = atoi(argv[3]);
222
223 ASSERT(uid == getuid());
224 ASSERT(gid == getgid());
225 notify_parent_process();
226
227 return 1;
228 }
229#endif /* !_WIN32 */
230
231 return run_test(argv[1], 0, 1);
232}
233