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

     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 }

mercurial