nsprpub/pr/tests/accept.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial