home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / tests / prselect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.3 KB  |  354 lines

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