Upload Tizen:Base source
[toolchains/nspr.git] / mozilla / nsprpub / pr / tests / io_timeout.c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is the Netscape Portable Runtime (NSPR).
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 1998-2000
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37
38 /*
39 ** Test socket IO timeouts
40 **
41 **
42 **
43 **
44 ** Modification History:
45 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
46 **               The debug mode will print all of the printfs associated with this test.
47 **                       The regress mode will be the default mode. Since the regress tool limits
48 **           the output to a one line status:PASS or FAIL,all of the printf statements
49 **                       have been handled with an if (debug_mode) statement. 
50 ***********************************************************************/
51 /***********************************************************************
52 ** Includes
53 ***********************************************************************/
54 /* Used to get the command line option */
55 #include "plgetopt.h"
56
57 #include <stdio.h>
58 #include "nspr.h"
59
60 #define NUM_THREADS 1
61 #define BASE_PORT   8000
62 #define DEFAULT_ACCEPT_TIMEOUT 2
63
64 typedef struct threadInfo {
65     PRInt16 id;
66     PRInt16 accept_timeout;
67     PRLock *dead_lock;
68     PRCondVar *dead_cv;
69     PRInt32   *alive;
70 } threadInfo;
71
72 PRIntn failed_already = 0;
73 PRIntn debug_mode = 0;
74
75 #define LOCAL_SCOPE_STRING                      "LOCAL scope"
76 #define GLOBAL_SCOPE_STRING                     "GLOBAL scope"
77 #define GLOBAL_BOUND_SCOPE_STRING       "GLOBAL_BOUND scope"
78
79 void 
80 thread_main(void *_info)
81 {
82     threadInfo *info = (threadInfo *)_info;
83     PRNetAddr listenAddr;
84     PRNetAddr clientAddr;
85     PRFileDesc *listenSock = NULL;
86     PRFileDesc *clientSock;
87     PRStatus rv;
88         PRThreadScope tscope;
89         char *scope_str;
90
91  
92         if (debug_mode)
93         printf("thread %d is alive\n", info->id);
94         tscope = PR_GetThreadScope(PR_GetCurrentThread());
95
96         switch(tscope) {
97                 case PR_LOCAL_THREAD:
98                         scope_str = LOCAL_SCOPE_STRING;
99                         break;
100                 case PR_GLOBAL_THREAD:
101                         scope_str = GLOBAL_SCOPE_STRING;
102                         break;
103                 case PR_GLOBAL_BOUND_THREAD:
104                         scope_str = GLOBAL_BOUND_SCOPE_STRING;
105                         break;
106                 default:
107                         PR_ASSERT(!"Invalid thread scope");
108                         break;
109         }
110         printf("thread id %d, scope %s\n", info->id, scope_str);
111
112     listenSock = PR_NewTCPSocket();
113     if (!listenSock) {
114                 if (debug_mode)
115                 printf("unable to create listen socket\n");
116                 failed_already=1;
117         goto dead;
118     }
119   
120     listenAddr.inet.family = PR_AF_INET;
121     listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
122     listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
123     rv = PR_Bind(listenSock, &listenAddr);
124     if (rv == PR_FAILURE) {
125                 if (debug_mode)
126                 printf("unable to bind\n");
127                 failed_already=1;
128         goto dead;
129     }
130
131     rv = PR_Listen(listenSock, 4);
132     if (rv == PR_FAILURE) {
133                 if (debug_mode)
134                 printf("unable to listen\n");
135                 failed_already=1;
136         goto dead;
137     }
138
139         if (debug_mode)
140         printf("thread %d going into accept for %d seconds\n", 
141                 info->id, info->accept_timeout + info->id);
142
143     clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id));
144
145     if (clientSock == NULL) {
146         if (PR_GetError() == PR_IO_TIMEOUT_ERROR) {
147                         if (debug_mode) {       
148                 printf("PR_Accept() timeout worked!\n"); 
149                                 printf("TEST PASSED! PR_Accept() returned error %d\n",
150                                                         PR_IO_TIMEOUT_ERROR);
151                         }
152         } else {
153                         if (debug_mode)
154                 printf("TEST FAILED! PR_Accept() returned error %d\n",
155                                                                                                                 PR_GetError());
156                         failed_already=1;
157                 }
158     } else {
159                 if (debug_mode)
160                 printf ("TEST FAILED! PR_Accept() succeeded?\n");
161                 failed_already=1;
162                 PR_Close(clientSock);
163     }
164
165 dead:
166     if (listenSock) {
167                 PR_Close(listenSock);
168     }
169     PR_Lock(info->dead_lock);
170     (*info->alive)--;
171     PR_NotifyCondVar(info->dead_cv);
172     PR_Unlock(info->dead_lock);
173
174         if (debug_mode)
175         printf("thread %d is dead\n", info->id);
176
177     PR_Free(info);
178 }
179
180 void
181 thread_test(PRThreadScope scope, PRInt32 num_threads)
182 {
183     PRInt32 index;
184     PRThread *thr;
185     PRLock *dead_lock;
186     PRCondVar *dead_cv;
187     PRInt32 alive;
188
189         if (debug_mode)
190         printf("IO Timeout test started with %d threads\n", num_threads);
191
192     dead_lock = PR_NewLock();
193     dead_cv = PR_NewCondVar(dead_lock);
194     alive = num_threads;
195     
196     for (index = 0; index < num_threads; index++) {
197         threadInfo *info = (threadInfo *)PR_Malloc(sizeof(threadInfo));
198
199         info->id = index;
200         info->dead_lock = dead_lock;
201         info->dead_cv = dead_cv;
202         info->alive = &alive;
203         info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
204         
205         thr = PR_CreateThread( PR_USER_THREAD,
206                                thread_main,
207                                (void *)info,
208                                PR_PRIORITY_NORMAL,
209                                scope,
210                                PR_UNJOINABLE_THREAD,
211                                0);
212
213         if (!thr) {
214                 printf("Failed to create thread, error = %d(%d)\n",
215                                                                                         PR_GetError(), PR_GetOSError());
216                         failed_already=1;
217
218             PR_Lock(dead_lock);
219             alive--;
220             PR_Unlock(dead_lock);
221         }
222     }
223
224     PR_Lock(dead_lock);
225     while(alive) {
226                 if (debug_mode)
227                 printf("main loop awake; alive = %d\n", alive);
228         PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
229     }
230     PR_Unlock(dead_lock);
231
232     PR_DestroyCondVar(dead_cv);
233     PR_DestroyLock(dead_lock);
234 }
235
236 int main(int argc, char **argv)
237 {
238     PRInt32 num_threads = 0;
239
240         /* The command line argument: -d is used to determine if the test is being run
241         in debug mode. The regress tool requires only one line output:PASS or FAIL.
242         All of the printfs associated with this test has been handled with a if (debug_mode)
243         test.
244         Usage: test_name [-d] [-t <threads>]
245         */
246         PLOptStatus os;
247         PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
248         while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
249     {
250                 if (PL_OPT_BAD == os) continue;
251         switch (opt->option)
252         {
253         case 'd':  /* debug mode */
254                         debug_mode = 1;
255             break;
256         case 't':  /* threads to involve */
257                         num_threads = atoi(opt->value);
258             break;
259          default:
260             break;
261         }
262     }
263         PL_DestroyOptState(opt);
264
265  /* main test */
266         
267     if (0 == num_threads)
268         num_threads = NUM_THREADS;
269
270     PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
271     PR_STDIO_INIT();
272
273     printf("test with global bound thread\n");
274     thread_test(PR_GLOBAL_BOUND_THREAD, num_threads);
275
276     printf("test with local thread\n");
277     thread_test(PR_LOCAL_THREAD, num_threads);
278
279     printf("test with global thread\n");
280     thread_test(PR_GLOBAL_THREAD, num_threads);
281
282     PR_Cleanup();
283
284         if (failed_already)
285                 return 1;
286         else
287         return 0;
288 }