Back to index

lightning-sunbird  0.9+nobinonly
accept.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /***********************************************************************
00039 **  1996 - Netscape Communications Corporation
00040 **
00041 ** Name: accept.c
00042 **
00043 ** Description: Run accept() sucessful connection tests.
00044 **
00045 ** Modification History:
00046 ** 04-Jun-97 AGarcia - Reconvert test file to return a 0 for PASS and a 1 for FAIL
00047 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode 
00048 **             The debug mode will print all of the printfs associated with this test.
00049 **             The regress mode will be the default mode. Since the regress tool limits
00050 **           the output to a one line status:PASS or FAIL,all of the printf statements
00051 **             have been handled with an if (debug_mode) statement.
00052 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
00053 **            recognize the return code from tha main program.
00054 ** 12-June-97 Revert to return code 0 and 1.
00055 ***********************************************************************/
00056 
00057 /***********************************************************************
00058 ** Includes
00059 ***********************************************************************/
00060 
00061 #include "nspr.h"
00062 #include "prpriv.h"
00063 
00064 #include <stdlib.h>
00065 #include <string.h>
00066 
00067 #include "plgetopt.h"
00068 #include "plerror.h"
00069 
00070 #define BASE_PORT 10000
00071 
00072 #define CLIENT_DATA        128
00073 
00074 #define ACCEPT_NORMAL        0x1
00075 #define ACCEPT_FAST        0x2
00076 #define ACCEPT_READ        0x3
00077 #define ACCEPT_READ_FAST    0x4
00078 #define ACCEPT_READ_FAST_CB    0x5
00079 
00080 #define CLIENT_NORMAL        0x1
00081 #define CLIENT_TIMEOUT_ACCEPT    0x2
00082 #define CLIENT_TIMEOUT_SEND    0x3
00083 
00084 #define SERVER_MAX_BIND_COUNT        100
00085 
00086 #if defined(XP_MAC) || defined(XP_OS2)
00087 #define TIMEOUTSECS 10
00088 #else
00089 #define TIMEOUTSECS 2
00090 #endif
00091 PRIntervalTime timeoutTime;
00092 
00093 static PRInt32 count = 1;
00094 static PRFileDesc *output;
00095 static PRNetAddr serverAddr;
00096 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
00097 static PRInt32 clientCommand;
00098 static PRInt32 iterations;
00099 static PRStatus rv;
00100 static PRFileDesc *listenSock;
00101 static PRFileDesc *clientSock = NULL;
00102 static PRNetAddr listenAddr;
00103 static PRNetAddr clientAddr;
00104 static PRThread *clientThread;
00105 static PRNetAddr *raddr;
00106 static char buf[4096 + 2*sizeof(PRNetAddr) + 32];
00107 static PRInt32 status;
00108 static PRInt32 bytesRead;
00109 
00110 PRIntn failed_already=0;
00111 PRIntn debug_mode;
00112 
00113 void Test_Assert(const char *msg, const char *file, PRIntn line)
00114 {
00115     failed_already=1;
00116     if (debug_mode) {
00117         PR_fprintf(output,  "@%s:%d ", file, line);
00118         PR_fprintf(output, msg);
00119     }
00120 }  /* Test_Assert */
00121 
00122 #define TEST_ASSERT(expr) \
00123     if (!(expr)) Test_Assert(#expr, __FILE__, __LINE__)
00124 
00125 #ifdef WINNT
00126 #define CALLBACK_MAGIC 0x12345678
00127 
00128 void timeout_callback(void *magic)
00129 {
00130     TEST_ASSERT(magic == (void *)CALLBACK_MAGIC);
00131     if (debug_mode)
00132         PR_fprintf(output, "timeout callback called okay\n");
00133 }
00134 #endif
00135 
00136 
00137 static void PR_CALLBACK
00138 ClientThread(void *_action)
00139 {
00140     PRInt32 action = * (PRInt32 *) _action;
00141     PRInt32 iterations = count;
00142     PRFileDesc *sock = NULL;
00143 
00144     serverAddr.inet.family = PR_AF_INET;
00145     serverAddr.inet.port = listenAddr.inet.port;
00146     serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
00147 
00148     for (; iterations--;) {
00149         PRInt32 rv;
00150         char buf[CLIENT_DATA];
00151 
00152         memset(buf, 0xaf, sizeof(buf)); /* initialize with arbitrary data */
00153         sock = PR_NewTCPSocket();
00154         if (!sock) {
00155             if (!debug_mode)
00156                 failed_already=1;
00157             else    
00158                 PR_fprintf(output, "client: unable to create socket\n");
00159             return;
00160         }
00161 
00162         if (action != CLIENT_TIMEOUT_ACCEPT) {
00163 
00164             if ((rv = PR_Connect(sock, &serverAddr,
00165                 timeoutTime)) < 0) {
00166                 if (!debug_mode)
00167                     failed_already=1;
00168                 else    
00169                     PR_fprintf(output, 
00170                         "client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
00171                         iterations, rv, PR_GetError(), PR_GetOSError());
00172                 goto ErrorExit;
00173             }
00174 
00175             if (action != CLIENT_TIMEOUT_SEND) {
00176                 if ((rv = PR_Send(sock, buf, CLIENT_DATA,
00177                     0, timeoutTime))< 0) {
00178                     if (!debug_mode)
00179                         failed_already=1;
00180                     else    
00181                         PR_fprintf(output, 
00182                             "client: unable to send to server (%d, %ld, %ld)\n",
00183                             CLIENT_DATA, rv, PR_GetError());
00184                      goto ErrorExit;
00185                 }
00186             } else {
00187                 PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
00188             }
00189         } else {
00190             PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
00191         }
00192         if (debug_mode)
00193             PR_fprintf(output, ".");
00194         PR_Close(sock);
00195               sock = NULL;
00196     }
00197     if (debug_mode)
00198         PR_fprintf(output, "\n");
00199 
00200 ErrorExit:
00201        if (sock != NULL)
00202         PR_Close(sock);
00203 }
00204 
00205 
00206 static void 
00207 RunTest(PRInt32 acceptType, PRInt32 clientAction)
00208 {
00209 int i;
00210 
00211     /* First bind to the socket */
00212     listenSock = PR_NewTCPSocket();
00213     if (!listenSock) {
00214         failed_already=1;
00215         if (debug_mode)
00216             PR_fprintf(output, "unable to create listen socket\n");
00217         return;
00218     }
00219        memset(&listenAddr, 0 , sizeof(listenAddr));
00220     listenAddr.inet.family = PR_AF_INET;
00221     listenAddr.inet.port = PR_htons(BASE_PORT);
00222     listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
00223     /*
00224      * try a few times to bind server's address, if addresses are in
00225      * use
00226      */
00227     i = 0;
00228     while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) {
00229         if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
00230             listenAddr.inet.port += 2;
00231             if (i++ < SERVER_MAX_BIND_COUNT)
00232                 continue;
00233         }
00234         failed_already=1;
00235         if (debug_mode)
00236               PR_fprintf(output,"accept: ERROR - PR_Bind failed\n");
00237               return;
00238     }
00239 
00240 
00241     rv = PR_Listen(listenSock, 100);
00242     if (rv == PR_FAILURE) {
00243         failed_already=1;
00244         if (debug_mode)
00245             PR_fprintf(output, "unable to listen\n");
00246         return;
00247     }
00248 
00249     clientCommand = clientAction;
00250     clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread,
00251         (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope,
00252         PR_JOINABLE_THREAD, 0);
00253     if (!clientThread) {
00254         failed_already=1;
00255         if (debug_mode)
00256             PR_fprintf(output, "error creating client thread\n");
00257         return;
00258     }
00259 
00260     iterations = count;
00261     for (;iterations--;) {
00262         switch (acceptType) {
00263         case ACCEPT_NORMAL:
00264             clientSock = PR_Accept(listenSock, &clientAddr,
00265                 timeoutTime);
00266             switch(clientAction) {
00267             case CLIENT_TIMEOUT_ACCEPT:
00268                 TEST_ASSERT(clientSock == 0);
00269                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00270                 break;
00271             case CLIENT_NORMAL:
00272                 TEST_ASSERT(clientSock);
00273                 bytesRead = PR_Recv(clientSock,
00274                     buf,  CLIENT_DATA,  0,  timeoutTime);
00275                 TEST_ASSERT(bytesRead == CLIENT_DATA);
00276                 break;
00277             case CLIENT_TIMEOUT_SEND:
00278                 TEST_ASSERT(clientSock);
00279                 bytesRead = PR_Recv(clientSock,
00280                     buf,  CLIENT_DATA,  0,  timeoutTime);
00281                 TEST_ASSERT(bytesRead == -1);
00282                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00283                 break;
00284             }
00285             break;
00286         case ACCEPT_READ:
00287             status = PR_AcceptRead(listenSock, &clientSock,
00288                 &raddr, buf, CLIENT_DATA, timeoutTime);
00289             switch(clientAction) {
00290             case CLIENT_TIMEOUT_ACCEPT:
00291                 /* Invalid test case */
00292                 TEST_ASSERT(0);
00293                 break;
00294             case CLIENT_NORMAL:
00295                 TEST_ASSERT(clientSock);
00296                 TEST_ASSERT(status == CLIENT_DATA);
00297                 break;
00298             case CLIENT_TIMEOUT_SEND:
00299                 TEST_ASSERT(status == -1);
00300                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00301                 break;
00302             }
00303             break;
00304 #ifdef WINNT
00305         case ACCEPT_FAST:
00306             clientSock = PR_NTFast_Accept(listenSock,
00307                 &clientAddr, timeoutTime);
00308             switch(clientAction) {
00309             case CLIENT_TIMEOUT_ACCEPT:
00310                 TEST_ASSERT(clientSock == 0);
00311                 if (debug_mode)
00312                     PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError());
00313                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00314                 break;
00315             case CLIENT_NORMAL:
00316                 TEST_ASSERT(clientSock);
00317                 bytesRead = PR_Recv(clientSock,
00318                     buf,  CLIENT_DATA,  0,  timeoutTime);
00319                 TEST_ASSERT(bytesRead == CLIENT_DATA);
00320                 break;
00321             case CLIENT_TIMEOUT_SEND:
00322                 TEST_ASSERT(clientSock);
00323                 bytesRead = PR_Recv(clientSock,
00324                     buf,  CLIENT_DATA,  0,  timeoutTime);
00325                 TEST_ASSERT(bytesRead == -1);
00326                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00327                 break;
00328             }
00329             break;
00330             break;
00331         case ACCEPT_READ_FAST:
00332             status = PR_NTFast_AcceptRead(listenSock,
00333                 &clientSock, &raddr, buf, 4096, timeoutTime);
00334             switch(clientAction) {
00335             case CLIENT_TIMEOUT_ACCEPT:
00336                 /* Invalid test case */
00337                 TEST_ASSERT(0);
00338                 break;
00339             case CLIENT_NORMAL:
00340                 TEST_ASSERT(clientSock);
00341                 TEST_ASSERT(status == CLIENT_DATA);
00342                 break;
00343             case CLIENT_TIMEOUT_SEND:
00344                 TEST_ASSERT(clientSock == NULL);
00345                 TEST_ASSERT(status == -1);
00346                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00347                 break;
00348             }
00349             break;
00350         case ACCEPT_READ_FAST_CB:
00351             status = PR_NTFast_AcceptRead_WithTimeoutCallback(
00352                 listenSock, &clientSock, &raddr, buf, 4096,
00353                 timeoutTime, timeout_callback, (void *)CALLBACK_MAGIC);
00354             switch(clientAction) {
00355             case CLIENT_TIMEOUT_ACCEPT:
00356                 /* Invalid test case */
00357                 TEST_ASSERT(0);
00358                 break;
00359             case CLIENT_NORMAL:
00360                 TEST_ASSERT(clientSock);
00361                 TEST_ASSERT(status == CLIENT_DATA);
00362                 break;
00363             case CLIENT_TIMEOUT_SEND:
00364                 if (debug_mode)
00365                     PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
00366                 TEST_ASSERT(clientSock == NULL);
00367                 TEST_ASSERT(status == -1);
00368                 TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
00369                 break;
00370             }
00371             break;
00372 #endif
00373         }
00374         if (clientSock != NULL) {
00375             PR_Close(clientSock);
00376             clientSock = NULL;
00377         }
00378     }
00379     PR_Close(listenSock);
00380 
00381     PR_JoinThread(clientThread);
00382 }
00383 
00384 
00385 void AcceptUpdatedTest(void)
00386 { 
00387     RunTest(ACCEPT_NORMAL, CLIENT_NORMAL); 
00388 }
00389 void AcceptNotUpdatedTest(void)
00390 { 
00391     RunTest(ACCEPT_FAST, CLIENT_NORMAL); 
00392 }
00393 void AcceptReadTest(void)
00394 { 
00395     RunTest(ACCEPT_READ, CLIENT_NORMAL); 
00396 }
00397 void AcceptReadNotUpdatedTest(void)
00398 { 
00399     RunTest(ACCEPT_READ_FAST, CLIENT_NORMAL); 
00400 }
00401 void AcceptReadCallbackTest(void)
00402 { 
00403     RunTest(ACCEPT_READ_FAST_CB, CLIENT_NORMAL); 
00404 }
00405 
00406 void TimeoutAcceptUpdatedTest(void)
00407 { 
00408     RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_ACCEPT); 
00409 }
00410 void TimeoutAcceptNotUpdatedTest(void)
00411 { 
00412     RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_ACCEPT); 
00413 }
00414 void TimeoutAcceptReadCallbackTest(void)
00415 { 
00416     RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_ACCEPT); 
00417 }
00418 
00419 void TimeoutReadUpdatedTest(void)
00420 { 
00421     RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_SEND); 
00422 }
00423 void TimeoutReadNotUpdatedTest(void)
00424 { 
00425     RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_SEND); 
00426 }
00427 void TimeoutReadReadTest(void)
00428 { 
00429     RunTest(ACCEPT_READ, CLIENT_TIMEOUT_SEND); 
00430 }
00431 void TimeoutReadReadNotUpdatedTest(void)
00432 { 
00433     RunTest(ACCEPT_READ_FAST, CLIENT_TIMEOUT_SEND); 
00434 }
00435 void TimeoutReadReadCallbackTest(void)
00436 { 
00437     RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_SEND); 
00438 }
00439 
00440 /************************************************************************/
00441 
00442 static void Measure(void (*func)(void), const char *msg)
00443 {
00444     PRIntervalTime start, stop;
00445     double d;
00446 
00447     start = PR_IntervalNow();
00448     (*func)();
00449     stop = PR_IntervalNow();
00450 
00451     d = (double)PR_IntervalToMicroseconds(stop - start);
00452     if (debug_mode)
00453         PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count);
00454 
00455 }
00456 
00457 int main(int argc, char **argv)
00458 {
00459 
00460     /* The command line argument: -d is used to determine if the test is being run
00461     in debug mode. The regress tool requires only one line output:PASS or FAIL.
00462     All of the printfs associated with this test has been handled with a if (debug_mode)
00463     test.
00464     Usage: test_name [-d] [-c n]
00465     */
00466     PLOptStatus os;
00467     PLOptState *opt = PL_CreateOptState(argc, argv, "Gdc:");
00468     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00469     {
00470         if (PL_OPT_BAD == os) continue;
00471         switch (opt->option)
00472         {
00473         case 'G':  /* global threads */
00474             thread_scope = PR_GLOBAL_THREAD;
00475             break;
00476         case 'd':  /* debug mode */
00477             debug_mode = 1;
00478             break;
00479         case 'c':  /* loop counter */
00480             count = atoi(opt->value);
00481             break;
00482         default:
00483             break;
00484         }
00485     }
00486     PL_DestroyOptState(opt);
00487 
00488     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
00489     output = PR_STDERR;
00490     PR_STDIO_INIT();
00491 
00492 #ifdef XP_MAC
00493     SetupMacPrintfLog("accept.log");
00494     debug_mode = 1;
00495 #endif
00496 
00497     timeoutTime = PR_SecondsToInterval(TIMEOUTSECS);
00498     if (debug_mode)
00499         PR_fprintf(output, "\nRun accept() sucessful connection tests\n");
00500 
00501     Measure(AcceptUpdatedTest, "PR_Accept()");
00502     Measure(AcceptReadTest, "PR_AcceptRead()");
00503 #ifdef WINNT
00504     Measure(AcceptNotUpdatedTest, "PR_NTFast_Accept()");
00505     Measure(AcceptReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
00506     Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
00507 #endif
00508     if (debug_mode)
00509         PR_fprintf(output, "\nRun accept() timeout in the accept tests\n");
00510 #ifdef WINNT
00511     Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
00512 #endif
00513     Measure(TimeoutReadUpdatedTest, "PR_Accept()");
00514     if (debug_mode)
00515         PR_fprintf(output, "\nRun accept() timeout in the read tests\n");
00516     Measure(TimeoutReadReadTest, "PR_AcceptRead()");
00517 #ifdef WINNT
00518     Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
00519     Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
00520     Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
00521 #endif
00522     PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS");
00523     return failed_already;
00524 }