Bug 1825055 [wpt PR 39247] - Add support for allowing elements with display:contents...
[gecko.git] / nsprpub / pr / tests / prselect.c
blob2a81100e8757020758a37559ca248dd78dbfbc5d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /***********************************************************************
7 ** 1997 - Netscape Communications Corporation
8 **
9 ** Name: prselect_err.c
11 ** Description: tests PR_Select with sockets Error condition functions.
13 ** Modification History:
14 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
15 ** The debug mode will print all of the printfs associated with this test.
16 ** The regress mode will be the default mode. Since the regress tool limits
17 ** the output to a one line status:PASS or FAIL,all of the printf statements
18 ** have been handled with an if (debug_mode) statement.
19 ***********************************************************************/
21 /***********************************************************************
22 ** Includes
23 ***********************************************************************/
24 /* Used to get the command line option */
25 #include "plgetopt.h"
26 #include "prttools.h"
29 #include "prinit.h"
30 #include "prio.h"
31 #include "prlog.h"
32 #include "prprf.h"
33 #include "prerror.h"
34 #include "prnetdb.h"
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
40 /***********************************************************************
41 ** PRIVATE FUNCTION: Test_Result
42 ** DESCRIPTION: Used in conjunction with the regress tool, prints out the
43 ** status of the test case.
44 ** INPUTS: PASS/FAIL
45 ** OUTPUTS: None
46 ** RETURN: None
47 ** SIDE EFFECTS:
49 ** RESTRICTIONS:
50 ** None
51 ** MEMORY: NA
52 ** ALGORITHM: Determine what the status is and print accordingly.
54 ***********************************************************************/
57 static Test_Result (int result)
59 if (result == PASS) {
60 printf ("PASS\n");
62 else {
63 printf ("FAIL\n");
67 static void
68 clientThreadFunc(void *arg)
70 PRUint16 port = (PRUint16) arg;
71 PRFileDesc *sock;
72 PRNetAddr addr;
73 char buf[128];
74 int i;
76 addr.inet.family = AF_INET;
77 addr.inet.port = PR_htons(port);
78 addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
79 PR_snprintf(buf, sizeof(buf), "%hu", port);
81 for (i = 0; i < 5; i++) {
82 sock = PR_NewTCPSocket();
83 PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
84 PR_Write(sock, buf, sizeof(buf));
85 PR_Close(sock);
89 int main(int argc, char **argv)
91 PRFileDesc *listenSock1, *listenSock2;
92 PRFileDesc *badFD;
93 PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
94 PRIntn nfds;
95 PRUint16 listenPort1, listenPort2;
96 PRNetAddr addr;
97 PR_fd_set readFdSet;
98 char buf[128];
99 PRThread *clientThread;
100 PRInt32 retVal;
101 PRIntn i, j;
103 /* The command line argument: -d is used to determine if the test is being run
104 in debug mode. The regress tool requires only one line output:PASS or FAIL.
105 All of the printfs associated with this test has been handled with a if (debug_mode)
106 test.
107 Usage: test_name -d
109 PLOptStatus os;
110 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
111 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
113 if (PL_OPT_BAD == os) {
114 continue;
116 switch (opt->option)
118 case 'd': /* debug mode */
119 debug_mode = 1;
120 break;
121 default:
122 break;
125 PL_DestroyOptState(opt);
127 /* main test */
129 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
130 PR_STDIO_INIT();
132 if (debug_mode) {
133 printf("This program tests PR_Select with sockets. Timeout, error\n");
134 printf("reporting, and normal operation are tested.\n\n");
137 /* Create two listening sockets */
138 if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
139 fprintf(stderr, "Can't create a new TCP socket\n");
140 if (!debug_mode) {
141 Test_Result(FAIL);
143 exit(1);
145 addr.inet.family = AF_INET;
146 addr.inet.ip = PR_htonl(INADDR_ANY);
147 addr.inet.port = PR_htons(0);
148 if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
149 fprintf(stderr, "Can't bind socket\n");
150 if (!debug_mode) {
151 Test_Result(FAIL);
153 exit(1);
155 if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
156 fprintf(stderr, "PR_GetSockName failed\n");
157 if (!debug_mode) {
158 Test_Result(FAIL);
160 exit(1);
162 listenPort1 = PR_ntohs(addr.inet.port);
163 if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
164 fprintf(stderr, "Can't listen on a socket\n");
165 if (!debug_mode) {
166 Test_Result(FAIL);
168 exit(1);
171 if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
172 fprintf(stderr, "Can't create a new TCP socket\n");
173 if (!debug_mode) {
174 Test_Result(FAIL);
176 exit(1);
178 addr.inet.family = AF_INET;
179 addr.inet.ip = PR_htonl(INADDR_ANY);
180 addr.inet.port = PR_htons(0);
181 if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
182 fprintf(stderr, "Can't bind socket\n");
183 if (!debug_mode) {
184 Test_Result(FAIL);
186 exit(1);
188 if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
189 fprintf(stderr, "PR_GetSockName failed\n");
190 if (!debug_mode) {
191 Test_Result(FAIL);
193 exit(1);
195 listenPort2 = PR_ntohs(addr.inet.port);
196 if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
197 fprintf(stderr, "Can't listen on a socket\n");
198 if (!debug_mode) {
199 Test_Result(FAIL);
201 exit(1);
203 PR_snprintf(buf, sizeof(buf),
204 "The server thread is listening on ports %hu and %hu\n\n",
205 listenPort1, listenPort2);
206 printf("%s", buf);
208 /* Set up the fd set */
209 PR_FD_ZERO(&readFdSet);
210 PR_FD_SET(listenSock1, &readFdSet);
211 PR_FD_SET(listenSock2, &readFdSet);
213 /* Testing timeout */
214 if (debug_mode) {
215 printf("PR_Select should time out in 5 seconds\n");
217 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
218 PR_SecondsToInterval(5));
219 if (retVal != 0) {
220 PR_snprintf(buf, sizeof(buf),
221 "PR_Select should time out and return 0, but it returns %ld\n",
222 retVal);
223 fprintf(stderr, "%s", buf);
224 if (retVal == -1) {
225 fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
226 PR_GetOSError());
227 if (!debug_mode) {
228 Test_Result(FAIL);
231 exit(1);
233 if (debug_mode) {
234 printf("PR_Select timed out. Test passed.\n\n");
236 else {
237 Test_Result(PASS);
240 /* Testing bad fd */
241 printf("PR_Select should detect a bad file descriptor\n");
242 if ((badFD = PR_NewTCPSocket()) == NULL) {
243 fprintf(stderr, "Can't create a TCP socket\n");
244 exit(1);
247 PR_FD_SET(listenSock1, &readFdSet);
248 PR_FD_SET(listenSock2, &readFdSet);
249 PR_FD_SET(badFD, &readFdSet);
250 PR_Close(badFD); /* make the fd bad */
251 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
252 PR_INTERVAL_NO_TIMEOUT);
253 if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) {
254 fprintf(stderr, "Failed to detect the bad fd: "
255 "PR_Select returns %d\n", retVal);
256 if (retVal == -1) {
257 fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
258 PR_GetOSError());
260 exit(1);
262 printf("PR_Select detected a bad fd. Test passed.\n\n");
263 PR_FD_CLR(badFD, &readFdSet);
265 clientThread = PR_CreateThread(PR_USER_THREAD,
266 clientThreadFunc, (void *) listenPort1,
267 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
268 PR_UNJOINABLE_THREAD, 0);
269 if (clientThread == NULL) {
270 fprintf(stderr, "can't create thread\n");
271 exit(1);
274 clientThread = PR_CreateThread(PR_USER_THREAD,
275 clientThreadFunc, (void *) listenPort2,
276 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
277 PR_UNJOINABLE_THREAD, 0);
278 if (clientThread == NULL) {
279 fprintf(stderr, "can't create thread\n");
280 exit(1);
283 printf("Two client threads are created. Each of them will\n");
284 printf("send data to one of the two ports the server is listening on.\n");
285 printf("The data they send is the port number. Each of them send\n");
286 printf("the data five times, so you should see ten lines below,\n");
287 printf("interleaved in an arbitrary order.\n");
289 /* set up the fd array */
290 fds = fds0;
291 other_fds = fds1;
292 fds[0] = listenSock1;
293 fds[1] = listenSock2;
294 nfds = 2;
295 PR_FD_SET(listenSock1, &readFdSet);
296 PR_FD_SET(listenSock2, &readFdSet);
298 /* 20 events total */
299 i = 0;
300 while (i < 20) {
301 PRFileDesc **tmp;
302 int nextIndex;
303 int nEvents = 0;
305 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
306 PR_INTERVAL_NO_TIMEOUT);
307 PR_ASSERT(retVal != 0); /* no timeout */
308 if (retVal == -1) {
309 fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
310 PR_GetOSError());
311 exit(1);
314 nextIndex = 2;
315 /* the two listening sockets */
316 for (j = 0; j < 2; j++) {
317 other_fds[j] = fds[j];
318 if (PR_FD_ISSET(fds[j], &readFdSet)) {
319 PRFileDesc *sock;
321 nEvents++;
322 sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
323 if (sock == NULL) {
324 fprintf(stderr, "PR_Accept() failed\n");
325 exit(1);
327 other_fds[nextIndex] = sock;
328 PR_FD_SET(sock, &readFdSet);
329 nextIndex++;
331 PR_FD_SET(fds[j], &readFdSet);
334 for (j = 2; j < nfds; j++) {
335 if (PR_FD_ISSET(fds[j], &readFdSet)) {
336 PRInt32 nBytes;
338 PR_FD_CLR(fds[j], &readFdSet);
339 nEvents++;
340 nBytes = PR_Read(fds[j], buf, sizeof(buf));
341 if (nBytes == -1) {
342 fprintf(stderr, "PR_Read() failed\n");
343 exit(1);
345 /* Just to be safe */
346 buf[127] = '\0';
347 PR_Close(fds[j]);
348 printf("The server received \"%s\" from a client\n", buf);
349 } else {
350 PR_FD_SET(fds[j], &readFdSet);
351 other_fds[nextIndex] = fds[j];
352 nextIndex++;
356 PR_ASSERT(retVal == nEvents);
357 /* swap */
358 tmp = fds;
359 fds = other_fds;
360 other_fds = tmp;
361 nfds = nextIndex;
362 i += nEvents;
365 printf("All tests finished\n");
366 PR_Cleanup();
367 return 0;