VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/prselect.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/***********************************************************************
39** 1997 - Netscape Communications Corporation
40**
41** Name: prselect_err.c
42**
43** Description: tests PR_Select with sockets Error condition functions.
44**
45** Modification History:
46** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
47** The debug mode will print all of the printfs associated with this test.
48** The regress mode will be the default mode. Since the regress tool limits
49** the output to a one line status:PASS or FAIL,all of the printf statements
50** have been handled with an if (debug_mode) statement.
51***********************************************************************/
52
53/***********************************************************************
54** Includes
55***********************************************************************/
56/* Used to get the command line option */
57#include "plgetopt.h"
58#include "prttools.h"
59
60
61#include "prinit.h"
62#include "prio.h"
63#include "prlog.h"
64#include "prprf.h"
65#include "prerror.h"
66#include "prnetdb.h"
67
68#include <stdio.h>
69#include <string.h>
70#include <stdlib.h>
71
72/***********************************************************************
73** PRIVATE FUNCTION: Test_Result
74** DESCRIPTION: Used in conjunction with the regress tool, prints out the
75** status of the test case.
76** INPUTS: PASS/FAIL
77** OUTPUTS: None
78** RETURN: None
79** SIDE EFFECTS:
80**
81** RESTRICTIONS:
82** None
83** MEMORY: NA
84** ALGORITHM: Determine what the status is and print accordingly.
85**
86***********************************************************************/
87
88
89static Test_Result (int result)
90{
91 if (result == PASS)
92 printf ("PASS\n");
93 else
94 printf ("FAIL\n");
95}
96
97static void
98clientThreadFunc(void *arg)
99{
100 PRUint16 port = (PRUint16) arg;
101 PRFileDesc *sock;
102 PRNetAddr addr;
103 char buf[128];
104 int i;
105
106 addr.inet.family = AF_INET;
107 addr.inet.port = PR_htons(port);
108 addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
109 PR_snprintf(buf, sizeof(buf), "%hu", port);
110
111 for (i = 0; i < 5; i++) {
112 sock = PR_NewTCPSocket();
113 PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
114 PR_Write(sock, buf, sizeof(buf));
115 PR_Close(sock);
116 }
117}
118
119int main(int argc, char **argv)
120{
121 PRFileDesc *listenSock1, *listenSock2;
122 PRFileDesc *badFD;
123 PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
124 PRIntn nfds;
125 PRUint16 listenPort1, listenPort2;
126 PRNetAddr addr;
127 PR_fd_set readFdSet;
128 char buf[128];
129 PRThread *clientThread;
130 PRInt32 retVal;
131 PRIntn i, j;
132
133 /* The command line argument: -d is used to determine if the test is being run
134 in debug mode. The regress tool requires only one line output:PASS or FAIL.
135 All of the printfs associated with this test has been handled with a if (debug_mode)
136 test.
137 Usage: test_name -d
138 */
139 PLOptStatus os;
140 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
141 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
142 {
143 if (PL_OPT_BAD == os) continue;
144 switch (opt->option)
145 {
146 case 'd': /* debug mode */
147 debug_mode = 1;
148 break;
149 default:
150 break;
151 }
152 }
153 PL_DestroyOptState(opt);
154
155 /* main test */
156
157 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
158 PR_STDIO_INIT();
159
160 if (debug_mode) {
161 printf("This program tests PR_Select with sockets. Timeout, error\n");
162 printf("reporting, and normal operation are tested.\n\n");
163 }
164
165 /* Create two listening sockets */
166 if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
167 fprintf(stderr, "Can't create a new TCP socket\n");
168 if (!debug_mode) Test_Result(FAIL);
169 exit(1);
170 }
171 addr.inet.family = AF_INET;
172 addr.inet.ip = PR_htonl(INADDR_ANY);
173 addr.inet.port = PR_htons(0);
174 if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
175 fprintf(stderr, "Can't bind socket\n");
176 if (!debug_mode) Test_Result(FAIL);
177 exit(1);
178 }
179 if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
180 fprintf(stderr, "PR_GetSockName failed\n");
181 if (!debug_mode) Test_Result(FAIL);
182 exit(1);
183 }
184 listenPort1 = PR_ntohs(addr.inet.port);
185 if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
186 fprintf(stderr, "Can't listen on a socket\n");
187 if (!debug_mode) Test_Result(FAIL);
188 exit(1);
189 }
190
191 if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
192 fprintf(stderr, "Can't create a new TCP socket\n");
193 if (!debug_mode) Test_Result(FAIL);
194 exit(1);
195 }
196 addr.inet.family = AF_INET;
197 addr.inet.ip = PR_htonl(INADDR_ANY);
198 addr.inet.port = PR_htons(0);
199 if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
200 fprintf(stderr, "Can't bind socket\n");
201 if (!debug_mode) Test_Result(FAIL);
202 exit(1);
203 }
204 if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
205 fprintf(stderr, "PR_GetSockName failed\n");
206 if (!debug_mode) Test_Result(FAIL);
207 exit(1);
208 }
209 listenPort2 = PR_ntohs(addr.inet.port);
210 if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
211 fprintf(stderr, "Can't listen on a socket\n");
212 if (!debug_mode) Test_Result(FAIL);
213 exit(1);
214 }
215 PR_snprintf(buf, sizeof(buf),
216 "The server thread is listening on ports %hu and %hu\n\n",
217 listenPort1, listenPort2);
218 printf("%s", buf);
219
220 /* Set up the fd set */
221 PR_FD_ZERO(&readFdSet);
222 PR_FD_SET(listenSock1, &readFdSet);
223 PR_FD_SET(listenSock2, &readFdSet);
224
225 /* Testing timeout */
226 if (debug_mode) printf("PR_Select should time out in 5 seconds\n");
227 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
228 PR_SecondsToInterval(5));
229 if (retVal != 0) {
230 PR_snprintf(buf, sizeof(buf),
231 "PR_Select should time out and return 0, but it returns %ld\n",
232 retVal);
233 fprintf(stderr, "%s", buf);
234 if (retVal == -1) {
235 fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
236 PR_GetOSError());
237 if (!debug_mode) Test_Result(FAIL);
238 }
239 exit(1);
240 }
241 if (debug_mode) printf("PR_Select timed out. Test passed.\n\n");
242 else Test_Result(PASS);
243
244 /* Testing bad fd */
245 printf("PR_Select should detect a bad file descriptor\n");
246 if ((badFD = PR_NewTCPSocket()) == NULL) {
247 fprintf(stderr, "Can't create a TCP socket\n");
248 exit(1);
249 }
250
251 PR_FD_SET(listenSock1, &readFdSet);
252 PR_FD_SET(listenSock2, &readFdSet);
253 PR_FD_SET(badFD, &readFdSet);
254 PR_Close(badFD); /* make the fd bad */
255 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
256 PR_INTERVAL_NO_TIMEOUT);
257 if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) {
258 fprintf(stderr, "Failed to detect the bad fd: "
259 "PR_Select returns %d\n", retVal);
260 if (retVal == -1) {
261 fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
262 PR_GetOSError());
263 }
264 exit(1);
265 }
266 printf("PR_Select detected a bad fd. Test passed.\n\n");
267 PR_FD_CLR(badFD, &readFdSet);
268
269 clientThread = PR_CreateThread(PR_USER_THREAD,
270 clientThreadFunc, (void *) listenPort1,
271 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
272 PR_UNJOINABLE_THREAD, 0);
273 if (clientThread == NULL) {
274 fprintf(stderr, "can't create thread\n");
275 exit(1);
276 }
277
278 clientThread = PR_CreateThread(PR_USER_THREAD,
279 clientThreadFunc, (void *) listenPort2,
280 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
281 PR_UNJOINABLE_THREAD, 0);
282 if (clientThread == NULL) {
283 fprintf(stderr, "can't create thread\n");
284 exit(1);
285 }
286
287 printf("Two client threads are created. Each of them will\n");
288 printf("send data to one of the two ports the server is listening on.\n");
289 printf("The data they send is the port number. Each of them send\n");
290 printf("the data five times, so you should see ten lines below,\n");
291 printf("interleaved in an arbitrary order.\n");
292
293 /* set up the fd array */
294 fds = fds0;
295 other_fds = fds1;
296 fds[0] = listenSock1;
297 fds[1] = listenSock2;
298 nfds = 2;
299 PR_FD_SET(listenSock1, &readFdSet);
300 PR_FD_SET(listenSock2, &readFdSet);
301
302 /* 20 events total */
303 i = 0;
304 while (i < 20) {
305 PRFileDesc **tmp;
306 int nextIndex;
307 int nEvents = 0;
308
309 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
310 PR_INTERVAL_NO_TIMEOUT);
311 PR_ASSERT(retVal != 0); /* no timeout */
312 if (retVal == -1) {
313 fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
314 PR_GetOSError());
315 exit(1);
316 }
317
318 nextIndex = 2;
319 /* the two listening sockets */
320 for (j = 0; j < 2; j++) {
321 other_fds[j] = fds[j];
322 if (PR_FD_ISSET(fds[j], &readFdSet)) {
323 PRFileDesc *sock;
324
325 nEvents++;
326 sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
327 if (sock == NULL) {
328 fprintf(stderr, "PR_Accept() failed\n");
329 exit(1);
330 }
331 other_fds[nextIndex] = sock;
332 PR_FD_SET(sock, &readFdSet);
333 nextIndex++;
334 }
335 PR_FD_SET(fds[j], &readFdSet);
336 }
337
338 for (j = 2; j < nfds; j++) {
339 if (PR_FD_ISSET(fds[j], &readFdSet)) {
340 PRInt32 nBytes;
341
342 PR_FD_CLR(fds[j], &readFdSet);
343 nEvents++;
344 nBytes = PR_Read(fds[j], buf, sizeof(buf));
345 if (nBytes == -1) {
346 fprintf(stderr, "PR_Read() failed\n");
347 exit(1);
348 }
349 /* Just to be safe */
350 buf[127] = '\0';
351 PR_Close(fds[j]);
352 printf("The server received \"%s\" from a client\n", buf);
353 } else {
354 PR_FD_SET(fds[j], &readFdSet);
355 other_fds[nextIndex] = fds[j];
356 nextIndex++;
357 }
358 }
359
360 PR_ASSERT(retVal == nEvents);
361 /* swap */
362 tmp = fds;
363 fds = other_fds;
364 other_fds = tmp;
365 nfds = nextIndex;
366 i += nEvents;
367 }
368
369 printf("All tests finished\n");
370 PR_Cleanup();
371 return 0;
372}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette