Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
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/. */
7 /*
8 ** name io_timeoutu.c
9 ** Description: Test socket IO timeouts (user level)
10 **
11 ** Modification History:
12 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
13 ** The debug mode will print all of the printfs associated with this test.
14 ** The regress mode will be the default mode. Since the regress tool limits
15 ** the output to a one line status:PASS or FAIL,all of the printf statements
16 ** have been handled with an if (debug_mode) statement.
17 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
18 ** recognize the return code from tha main program.
19 ***********************************************************************/
20 /***********************************************************************
21 ** Includes
22 ***********************************************************************/
23 /* Used to get the command line option */
24 #include "plgetopt.h"
26 #include <stdio.h>
27 #include "nspr.h"
29 #define NUM_THREADS 1
30 #define BASE_PORT 8000
31 #define DEFAULT_ACCEPT_TIMEOUT 2
33 typedef struct threadInfo {
34 PRInt16 id;
35 PRInt16 accept_timeout;
36 PRLock *dead_lock;
37 PRCondVar *dead_cv;
38 PRInt32 *alive;
39 } threadInfo;
40 PRIntn failed_already=0;
41 PRIntn debug_mode;
43 void
44 thread_main(void *_info)
45 {
46 threadInfo *info = (threadInfo *)_info;
47 PRNetAddr listenAddr;
48 PRNetAddr clientAddr;
49 PRFileDesc *listenSock = NULL;
50 PRFileDesc *clientSock;
51 PRStatus rv;
53 if (debug_mode) printf("thread %d is alive\n", info->id);
55 listenSock = PR_NewTCPSocket();
56 if (!listenSock) {
57 if (debug_mode) printf("unable to create listen socket\n");
58 goto dead;
59 }
61 listenAddr.inet.family = AF_INET;
62 listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
63 listenAddr.inet.ip = PR_htonl(INADDR_ANY);
64 rv = PR_Bind(listenSock, &listenAddr);
65 if (rv == PR_FAILURE) {
66 if (debug_mode) printf("unable to bind\n");
67 goto dead;
68 }
70 rv = PR_Listen(listenSock, 4);
71 if (rv == PR_FAILURE) {
72 if (debug_mode) printf("unable to listen\n");
73 goto dead;
74 }
76 if (debug_mode) printf("thread %d going into accept for %d seconds\n",
77 info->id, info->accept_timeout + info->id);
79 clientSock = PR_Accept(
80 listenSock, &clientAddr, PR_SecondsToInterval(
81 info->accept_timeout + info->id));
83 if (clientSock == NULL) {
84 if (PR_GetError() == PR_IO_TIMEOUT_ERROR)
85 if (debug_mode) {
86 printf("PR_Accept() timeout worked!\n");
87 printf("TEST FAILED! PR_Accept() returned error %d\n",
88 }
89 PR_GetError());
90 else failed_already=1;
91 } else {
92 if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n");
93 else failed_already=1;
94 PR_Close(clientSock);
95 }
97 dead:
98 if (listenSock) {
99 PR_Close(listenSock);
100 }
101 PR_Lock(info->dead_lock);
102 (*info->alive)--;
103 PR_NotifyCondVar(info->dead_cv);
104 PR_Unlock(info->dead_lock);
106 if (debug_mode) printf("thread %d is dead\n", info->id);
107 }
109 void
110 thread_test(PRInt32 scope, PRInt32 num_threads)
111 {
112 PRInt32 index;
113 PRThread *thr;
114 PRLock *dead_lock;
115 PRCondVar *dead_cv;
116 PRInt32 alive;
118 if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads);
120 dead_lock = PR_NewLock();
121 dead_cv = PR_NewCondVar(dead_lock);
122 alive = num_threads;
124 for (index = 0; index < num_threads; index++) {
125 threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo));
127 info->id = index;
128 info->dead_lock = dead_lock;
129 info->dead_cv = dead_cv;
130 info->alive = &alive;
131 info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
133 thr = PR_CreateThread( PR_USER_THREAD,
134 thread_main,
135 (void *)info,
136 PR_PRIORITY_NORMAL,
137 scope,
138 PR_UNJOINABLE_THREAD,
139 0);
141 if (!thr) {
142 PR_Lock(dead_lock);
143 alive--;
144 PR_Unlock(dead_lock);
145 }
146 }
148 PR_Lock(dead_lock);
149 while(alive) {
150 if (debug_mode) printf("main loop awake; alive = %d\n", alive);
151 PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
152 }
153 PR_Unlock(dead_lock);
154 }
156 int main(int argc, char **argv)
157 {
158 PRInt32 num_threads;
160 /* The command line argument: -d is used to determine if the test is being run
161 in debug mode. The regress tool requires only one line output:PASS or FAIL.
162 All of the printfs associated with this test has been handled with a if (debug_mode)
163 test.
164 Usage: test_name -d
165 */
166 PLOptStatus os;
167 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
168 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
169 {
170 if (PL_OPT_BAD == os) continue;
171 switch (opt->option)
172 {
173 case 'd': /* debug mode */
174 debug_mode = 1;
175 break;
176 default:
177 break;
178 }
179 }
180 PL_DestroyOptState(opt);
182 /* main test */
184 if (argc > 2)
185 num_threads = atoi(argv[2]);
186 else
187 num_threads = NUM_THREADS;
189 PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
190 PR_STDIO_INIT();
192 if (debug_mode) printf("user level test\n");
193 thread_test(PR_LOCAL_THREAD, num_threads);
195 PR_Cleanup();
196 if(failed_already)
197 return 1;
198 else
199 return 0;
202 }