poll_er.c (5902B)
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/. */ 5 6 /*********************************************************************** 7 ** 8 ** Name: prpoll_err.c 9 ** 10 ** Description: This program tests PR_Poll with sockets. 11 ** error reporting operation is tested 12 ** 13 ** Modification History: 14 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 15 ** The debug mode will print all of the printfs associated with this 16 *test. 17 ** The regress mode will be the default mode. Since the regress tool 18 *limits 19 ** the output to a one line status:PASS or FAIL,all of the printf 20 *statements 21 ** have been handled with an if (debug_mode) statement. 22 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been 23 *updated to 24 ** recognize the return code from tha main program. 25 ***********************************************************************/ 26 27 /*********************************************************************** 28 ** Includes 29 ***********************************************************************/ 30 /* Used to get the command line option */ 31 #include "plgetopt.h" 32 33 #include "primpl.h" 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <stdlib.h> 38 39 PRIntn failed_already = 0; 40 PRIntn debug_mode; 41 42 static void ClientThreadFunc(void* arg) { 43 PRFileDesc* badFD = (PRFileDesc*)arg; 44 /* 45 * Make the fd invalid 46 */ 47 #if defined(XP_UNIX) 48 close(PR_FileDesc2NativeHandle(badFD)); 49 #elif defined(WIN32) 50 closesocket(PR_FileDesc2NativeHandle(badFD)); 51 #else 52 # error "Unknown architecture" 53 #endif 54 } 55 56 int main(int argc, char** argv) { 57 PRFileDesc *listenSock1, *listenSock2; 58 PRFileDesc* badFD; 59 PRUint16 listenPort1, listenPort2; 60 PRNetAddr addr; 61 char buf[128]; 62 PRPollDesc pds0[10], pds1[10], *pds, *other_pds; 63 PRIntn npds; 64 PRInt32 retVal; 65 66 /* The command line argument: -d is used to determine if the test is being run 67 in debug mode. The regress tool requires only one line output:PASS or FAIL. 68 All of the printfs associated with this test has been handled with a if 69 (debug_mode) test. Usage: test_name -d 70 */ 71 PLOptStatus os; 72 PLOptState* opt = PL_CreateOptState(argc, argv, "d:"); 73 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 74 if (PL_OPT_BAD == os) { 75 continue; 76 } 77 switch (opt->option) { 78 case 'd': /* debug mode */ 79 debug_mode = 1; 80 break; 81 default: 82 break; 83 } 84 } 85 PL_DestroyOptState(opt); 86 87 /* main test */ 88 89 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 90 91 if (debug_mode) { 92 printf("This program tests PR_Poll with sockets.\n"); 93 printf("error reporting is tested.\n\n"); 94 } 95 96 /* Create two listening sockets */ 97 if ((listenSock1 = PR_NewTCPSocket()) == NULL) { 98 fprintf(stderr, "Can't create a new TCP socket\n"); 99 failed_already = 1; 100 goto exit_now; 101 } 102 addr.inet.family = AF_INET; 103 addr.inet.ip = PR_htonl(INADDR_ANY); 104 addr.inet.port = PR_htons(0); 105 if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { 106 fprintf(stderr, "Can't bind socket\n"); 107 failed_already = 1; 108 goto exit_now; 109 } 110 if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { 111 fprintf(stderr, "PR_GetSockName failed\n"); 112 failed_already = 1; 113 goto exit_now; 114 } 115 listenPort1 = PR_ntohs(addr.inet.port); 116 if (PR_Listen(listenSock1, 5) == PR_FAILURE) { 117 fprintf(stderr, "Can't listen on a socket\n"); 118 failed_already = 1; 119 goto exit_now; 120 } 121 122 if ((listenSock2 = PR_NewTCPSocket()) == NULL) { 123 fprintf(stderr, "Can't create a new TCP socket\n"); 124 failed_already = 1; 125 goto exit_now; 126 } 127 addr.inet.family = AF_INET; 128 addr.inet.ip = PR_htonl(INADDR_ANY); 129 addr.inet.port = PR_htons(0); 130 if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { 131 fprintf(stderr, "Can't bind socket\n"); 132 failed_already = 1; 133 goto exit_now; 134 } 135 if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { 136 fprintf(stderr, "PR_GetSockName failed\n"); 137 failed_already = 1; 138 goto exit_now; 139 } 140 listenPort2 = PR_ntohs(addr.inet.port); 141 if (PR_Listen(listenSock2, 5) == PR_FAILURE) { 142 fprintf(stderr, "Can't listen on a socket\n"); 143 failed_already = 1; 144 goto exit_now; 145 } 146 PR_snprintf(buf, sizeof(buf), 147 "The server thread is listening on ports %hu and %hu\n\n", 148 listenPort1, listenPort2); 149 if (debug_mode) { 150 printf("%s", buf); 151 } 152 153 /* Set up the poll descriptor array */ 154 pds = pds0; 155 other_pds = pds1; 156 memset(pds, 0, sizeof(pds)); 157 pds[0].fd = listenSock1; 158 pds[0].in_flags = PR_POLL_READ; 159 pds[1].fd = listenSock2; 160 pds[1].in_flags = PR_POLL_READ; 161 npds = 2; 162 163 /* Testing bad fd */ 164 if (debug_mode) { 165 printf("PR_Poll should detect a bad file descriptor\n"); 166 } 167 if ((badFD = PR_NewTCPSocket()) == NULL) { 168 fprintf(stderr, "Can't create a TCP socket\n"); 169 goto exit_now; 170 } 171 172 pds[2].fd = badFD; 173 pds[2].in_flags = PR_POLL_READ; 174 npds = 3; 175 176 if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc, badFD, 177 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 178 0) == NULL) { 179 fprintf(stderr, "cannot create thread\n"); 180 exit(1); 181 } 182 183 retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); 184 if (retVal != 1 || (unsigned short)pds[2].out_flags != PR_POLL_NVAL) { 185 fprintf(stderr, 186 "Failed to detect the bad fd: " 187 "PR_Poll returns %d, out_flags is 0x%hx\n", 188 retVal, pds[2].out_flags); 189 failed_already = 1; 190 goto exit_now; 191 } 192 if (debug_mode) { 193 printf("PR_Poll detected the bad fd. Test passed.\n\n"); 194 } 195 PR_Cleanup(); 196 goto exit_now; 197 exit_now: 198 if (failed_already) { 199 return 1; 200 } else { 201 return 0; 202 } 203 }