Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 ** 1996 - Netscape Communications Corporation
8 **
9 ** Name: accept.c
10 **
11 ** Description: Run accept() sucessful connection tests.
12 **
13 ** Modification History:
14 ** 04-Jun-97 AGarcia - Reconvert test file to return a 0 for PASS and a 1 for FAIL
15 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode
16 ** The debug mode will print all of the printfs associated with this test.
17 ** The regress mode will be the default mode. Since the regress tool limits
18 ** the output to a one line status:PASS or FAIL,all of the printf statements
19 ** have been handled with an if (debug_mode) statement.
20 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
21 ** recognize the return code from tha main program.
22 ** 12-June-97 Revert to return code 0 and 1.
23 ***********************************************************************/
25 /***********************************************************************
26 ** Includes
27 ***********************************************************************/
29 #include "nspr.h"
30 #include "prpriv.h"
32 #include <stdlib.h>
33 #include <string.h>
35 #include "plgetopt.h"
36 #include "plerror.h"
38 #define BASE_PORT 10000
40 #define CLIENT_DATA 128
42 #define ACCEPT_NORMAL 0x1
43 #define ACCEPT_FAST 0x2
44 #define ACCEPT_READ 0x3
45 #define ACCEPT_READ_FAST 0x4
46 #define ACCEPT_READ_FAST_CB 0x5
48 #define CLIENT_NORMAL 0x1
49 #define CLIENT_TIMEOUT_ACCEPT 0x2
50 #define CLIENT_TIMEOUT_SEND 0x3
52 #define SERVER_MAX_BIND_COUNT 100
54 #if defined(XP_OS2) || defined(SYMBIAN)
55 #define TIMEOUTSECS 10
56 #else
57 #define TIMEOUTSECS 2
58 #endif
59 PRIntervalTime timeoutTime;
61 static PRInt32 count = 1;
62 static PRFileDesc *output;
63 static PRNetAddr serverAddr;
64 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
65 static PRInt32 clientCommand;
66 static PRInt32 iterations;
67 static PRStatus rv;
68 static PRFileDesc *listenSock;
69 static PRFileDesc *clientSock = NULL;
70 static PRNetAddr listenAddr;
71 static PRNetAddr clientAddr;
72 static PRThread *clientThread;
73 static PRNetAddr *raddr;
74 static char buf[4096 + 2*sizeof(PRNetAddr) + 32];
75 static PRInt32 status;
76 static PRInt32 bytesRead;
78 PRIntn failed_already=0;
79 PRIntn debug_mode;
81 void Test_Assert(const char *msg, const char *file, PRIntn line)
82 {
83 failed_already=1;
84 if (debug_mode) {
85 PR_fprintf(output, "@%s:%d ", file, line);
86 PR_fprintf(output, msg);
87 }
88 } /* Test_Assert */
90 #define TEST_ASSERT(expr) \
91 if (!(expr)) Test_Assert(#expr, __FILE__, __LINE__)
93 #ifdef WINNT
94 #define CALLBACK_MAGIC 0x12345678
96 void timeout_callback(void *magic)
97 {
98 TEST_ASSERT(magic == (void *)CALLBACK_MAGIC);
99 if (debug_mode)
100 PR_fprintf(output, "timeout callback called okay\n");
101 }
102 #endif
105 static void PR_CALLBACK
106 ClientThread(void *_action)
107 {
108 PRInt32 action = * (PRInt32 *) _action;
109 PRInt32 iterations = count;
110 PRFileDesc *sock = NULL;
112 serverAddr.inet.family = PR_AF_INET;
113 serverAddr.inet.port = listenAddr.inet.port;
114 serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
116 for (; iterations--;) {
117 PRInt32 rv;
118 char buf[CLIENT_DATA];
120 memset(buf, 0xaf, sizeof(buf)); /* initialize with arbitrary data */
121 sock = PR_NewTCPSocket();
122 if (!sock) {
123 if (!debug_mode)
124 failed_already=1;
125 else
126 PR_fprintf(output, "client: unable to create socket\n");
127 return;
128 }
130 if (action != CLIENT_TIMEOUT_ACCEPT) {
132 if ((rv = PR_Connect(sock, &serverAddr,
133 timeoutTime)) < 0) {
134 if (!debug_mode)
135 failed_already=1;
136 else
137 PR_fprintf(output,
138 "client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
139 iterations, rv, PR_GetError(), PR_GetOSError());
140 goto ErrorExit;
141 }
143 if (action != CLIENT_TIMEOUT_SEND) {
144 if ((rv = PR_Send(sock, buf, CLIENT_DATA,
145 0, timeoutTime))< 0) {
146 if (!debug_mode)
147 failed_already=1;
148 else
149 PR_fprintf(output,
150 "client: unable to send to server (%d, %ld, %ld)\n",
151 CLIENT_DATA, rv, PR_GetError());
152 goto ErrorExit;
153 }
154 } else {
155 PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
156 }
157 } else {
158 PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
159 }
160 if (debug_mode)
161 PR_fprintf(output, ".");
162 PR_Close(sock);
163 sock = NULL;
164 }
165 if (debug_mode)
166 PR_fprintf(output, "\n");
168 ErrorExit:
169 if (sock != NULL)
170 PR_Close(sock);
171 }
174 static void
175 RunTest(PRInt32 acceptType, PRInt32 clientAction)
176 {
177 int i;
179 /* First bind to the socket */
180 listenSock = PR_NewTCPSocket();
181 if (!listenSock) {
182 failed_already=1;
183 if (debug_mode)
184 PR_fprintf(output, "unable to create listen socket\n");
185 return;
186 }
187 memset(&listenAddr, 0 , sizeof(listenAddr));
188 listenAddr.inet.family = PR_AF_INET;
189 listenAddr.inet.port = PR_htons(BASE_PORT);
190 listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
191 /*
192 * try a few times to bind server's address, if addresses are in
193 * use
194 */
195 i = 0;
196 while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) {
197 if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
198 listenAddr.inet.port += 2;
199 if (i++ < SERVER_MAX_BIND_COUNT)
200 continue;
201 }
202 failed_already=1;
203 if (debug_mode)
204 PR_fprintf(output,"accept: ERROR - PR_Bind failed\n");
205 return;
206 }
209 rv = PR_Listen(listenSock, 100);
210 if (rv == PR_FAILURE) {
211 failed_already=1;
212 if (debug_mode)
213 PR_fprintf(output, "unable to listen\n");
214 return;
215 }
217 clientCommand = clientAction;
218 clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread,
219 (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope,
220 PR_JOINABLE_THREAD, 0);
221 if (!clientThread) {
222 failed_already=1;
223 if (debug_mode)
224 PR_fprintf(output, "error creating client thread\n");
225 return;
226 }
228 iterations = count;
229 for (;iterations--;) {
230 switch (acceptType) {
231 case ACCEPT_NORMAL:
232 clientSock = PR_Accept(listenSock, &clientAddr,
233 timeoutTime);
234 switch(clientAction) {
235 case CLIENT_TIMEOUT_ACCEPT:
236 TEST_ASSERT(clientSock == 0);
237 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
238 break;
239 case CLIENT_NORMAL:
240 TEST_ASSERT(clientSock);
241 bytesRead = PR_Recv(clientSock,
242 buf, CLIENT_DATA, 0, timeoutTime);
243 TEST_ASSERT(bytesRead == CLIENT_DATA);
244 break;
245 case CLIENT_TIMEOUT_SEND:
246 TEST_ASSERT(clientSock);
247 bytesRead = PR_Recv(clientSock,
248 buf, CLIENT_DATA, 0, timeoutTime);
249 TEST_ASSERT(bytesRead == -1);
250 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
251 break;
252 }
253 break;
254 case ACCEPT_READ:
255 status = PR_AcceptRead(listenSock, &clientSock,
256 &raddr, buf, CLIENT_DATA, timeoutTime);
257 switch(clientAction) {
258 case CLIENT_TIMEOUT_ACCEPT:
259 /* Invalid test case */
260 TEST_ASSERT(0);
261 break;
262 case CLIENT_NORMAL:
263 TEST_ASSERT(clientSock);
264 TEST_ASSERT(status == CLIENT_DATA);
265 break;
266 case CLIENT_TIMEOUT_SEND:
267 TEST_ASSERT(status == -1);
268 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
269 break;
270 }
271 break;
272 #ifdef WINNT
273 case ACCEPT_FAST:
274 clientSock = PR_NTFast_Accept(listenSock,
275 &clientAddr, timeoutTime);
276 switch(clientAction) {
277 case CLIENT_TIMEOUT_ACCEPT:
278 TEST_ASSERT(clientSock == 0);
279 if (debug_mode)
280 PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError());
281 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
282 break;
283 case CLIENT_NORMAL:
284 TEST_ASSERT(clientSock);
285 bytesRead = PR_Recv(clientSock,
286 buf, CLIENT_DATA, 0, timeoutTime);
287 TEST_ASSERT(bytesRead == CLIENT_DATA);
288 break;
289 case CLIENT_TIMEOUT_SEND:
290 TEST_ASSERT(clientSock);
291 bytesRead = PR_Recv(clientSock,
292 buf, CLIENT_DATA, 0, timeoutTime);
293 TEST_ASSERT(bytesRead == -1);
294 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
295 break;
296 }
297 break;
298 break;
299 case ACCEPT_READ_FAST:
300 status = PR_NTFast_AcceptRead(listenSock,
301 &clientSock, &raddr, buf, 4096, timeoutTime);
302 switch(clientAction) {
303 case CLIENT_TIMEOUT_ACCEPT:
304 /* Invalid test case */
305 TEST_ASSERT(0);
306 break;
307 case CLIENT_NORMAL:
308 TEST_ASSERT(clientSock);
309 TEST_ASSERT(status == CLIENT_DATA);
310 break;
311 case CLIENT_TIMEOUT_SEND:
312 TEST_ASSERT(clientSock == NULL);
313 TEST_ASSERT(status == -1);
314 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
315 break;
316 }
317 break;
318 case ACCEPT_READ_FAST_CB:
319 status = PR_NTFast_AcceptRead_WithTimeoutCallback(
320 listenSock, &clientSock, &raddr, buf, 4096,
321 timeoutTime, timeout_callback, (void *)CALLBACK_MAGIC);
322 switch(clientAction) {
323 case CLIENT_TIMEOUT_ACCEPT:
324 /* Invalid test case */
325 TEST_ASSERT(0);
326 break;
327 case CLIENT_NORMAL:
328 TEST_ASSERT(clientSock);
329 TEST_ASSERT(status == CLIENT_DATA);
330 break;
331 case CLIENT_TIMEOUT_SEND:
332 if (debug_mode)
333 PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
334 TEST_ASSERT(clientSock == NULL);
335 TEST_ASSERT(status == -1);
336 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
337 break;
338 }
339 break;
340 #endif
341 }
342 if (clientSock != NULL) {
343 PR_Close(clientSock);
344 clientSock = NULL;
345 }
346 }
347 PR_Close(listenSock);
349 PR_JoinThread(clientThread);
350 }
353 void AcceptUpdatedTest(void)
354 {
355 RunTest(ACCEPT_NORMAL, CLIENT_NORMAL);
356 }
357 void AcceptNotUpdatedTest(void)
358 {
359 RunTest(ACCEPT_FAST, CLIENT_NORMAL);
360 }
361 void AcceptReadTest(void)
362 {
363 RunTest(ACCEPT_READ, CLIENT_NORMAL);
364 }
365 void AcceptReadNotUpdatedTest(void)
366 {
367 RunTest(ACCEPT_READ_FAST, CLIENT_NORMAL);
368 }
369 void AcceptReadCallbackTest(void)
370 {
371 RunTest(ACCEPT_READ_FAST_CB, CLIENT_NORMAL);
372 }
374 void TimeoutAcceptUpdatedTest(void)
375 {
376 RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_ACCEPT);
377 }
378 void TimeoutAcceptNotUpdatedTest(void)
379 {
380 RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_ACCEPT);
381 }
382 void TimeoutAcceptReadCallbackTest(void)
383 {
384 RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_ACCEPT);
385 }
387 void TimeoutReadUpdatedTest(void)
388 {
389 RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_SEND);
390 }
391 void TimeoutReadNotUpdatedTest(void)
392 {
393 RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_SEND);
394 }
395 void TimeoutReadReadTest(void)
396 {
397 RunTest(ACCEPT_READ, CLIENT_TIMEOUT_SEND);
398 }
399 void TimeoutReadReadNotUpdatedTest(void)
400 {
401 RunTest(ACCEPT_READ_FAST, CLIENT_TIMEOUT_SEND);
402 }
403 void TimeoutReadReadCallbackTest(void)
404 {
405 RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_SEND);
406 }
408 /************************************************************************/
410 static void Measure(void (*func)(void), const char *msg)
411 {
412 PRIntervalTime start, stop;
413 double d;
415 start = PR_IntervalNow();
416 (*func)();
417 stop = PR_IntervalNow();
419 d = (double)PR_IntervalToMicroseconds(stop - start);
420 if (debug_mode)
421 PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count);
423 }
425 int main(int argc, char **argv)
426 {
428 /* The command line argument: -d is used to determine if the test is being run
429 in debug mode. The regress tool requires only one line output:PASS or FAIL.
430 All of the printfs associated with this test has been handled with a if (debug_mode)
431 test.
432 Usage: test_name [-d] [-c n]
433 */
434 PLOptStatus os;
435 PLOptState *opt = PL_CreateOptState(argc, argv, "Gdc:");
436 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
437 {
438 if (PL_OPT_BAD == os) continue;
439 switch (opt->option)
440 {
441 case 'G': /* global threads */
442 thread_scope = PR_GLOBAL_THREAD;
443 break;
444 case 'd': /* debug mode */
445 debug_mode = 1;
446 break;
447 case 'c': /* loop counter */
448 count = atoi(opt->value);
449 break;
450 default:
451 break;
452 }
453 }
454 PL_DestroyOptState(opt);
456 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
457 output = PR_STDERR;
458 PR_STDIO_INIT();
460 timeoutTime = PR_SecondsToInterval(TIMEOUTSECS);
461 if (debug_mode)
462 PR_fprintf(output, "\nRun accept() sucessful connection tests\n");
464 Measure(AcceptUpdatedTest, "PR_Accept()");
465 Measure(AcceptReadTest, "PR_AcceptRead()");
466 #ifdef WINNT
467 Measure(AcceptNotUpdatedTest, "PR_NTFast_Accept()");
468 Measure(AcceptReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
469 Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
470 #endif
471 if (debug_mode)
472 PR_fprintf(output, "\nRun accept() timeout in the accept tests\n");
473 #ifdef WINNT
474 Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
475 #endif
476 Measure(TimeoutReadUpdatedTest, "PR_Accept()");
477 if (debug_mode)
478 PR_fprintf(output, "\nRun accept() timeout in the read tests\n");
479 Measure(TimeoutReadReadTest, "PR_AcceptRead()");
480 #ifdef WINNT
481 Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
482 Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
483 Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
484 #endif
485 PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS");
486 return failed_already;
487 }