~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/tests/ntioto.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 Mozilla Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/MPL/
 
7
 * 
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 * 
 
13
 * The Original Code is the Netscape Portable Runtime (NSPR).
 
14
 * 
 
15
 * The Initial Developer of the Original Code is Netscape
 
16
 * Communications Corporation.  Portions created by Netscape are 
 
17
 * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
 
18
 * Rights Reserved.
 
19
 * 
 
20
 * Contributor(s):
 
21
 * 
 
22
 * Alternatively, the contents of this file may be used under the
 
23
 * terms of the GNU General Public License Version 2 or later (the
 
24
 * "GPL"), in which case the provisions of the GPL are applicable 
 
25
 * instead of those above.  If you wish to allow use of your 
 
26
 * version of this file only under the terms of the GPL and not to
 
27
 * allow others to use your version of this file under the MPL,
 
28
 * indicate your decision by deleting the provisions above and
 
29
 * replace them with the notice and other provisions required by
 
30
 * the GPL.  If you do not delete the provisions above, a recipient
 
31
 * may use your version of this file under either the MPL or the
 
32
 * GPL.
 
33
 */
 
34
 
 
35
/*
 
36
** File: ntioto.c
 
37
** Description: 
 
38
** This test, ntioto.c, was designed to reproduce a bug reported by NES
 
39
** on WindowsNT (fibers implementation). NSPR was asserting in ntio.c
 
40
** after PR_AcceptRead() had timed out. I/O performed subsequent to the
 
41
** call to PR_AcceptRead() could complete on a CPU other than the one
 
42
** on which it was started. The assert in ntio.c detected this, then
 
43
** asserted.
 
44
**
 
45
** Design:
 
46
** This test will fail with an assert in ntio.c if the problem it was
 
47
** designed to catch occurs. It returns 0 otherwise.
 
48
** 
 
49
** The main() thread initializes and tears things down. A file is
 
50
** opened for writing; this file will be written to by AcceptThread()
 
51
** and JitterThread().  Main() creates a socket for reading, listens
 
52
** and binds the socket.
 
53
** 
 
54
** ConnectThread() connects to the socket created by main, then polls
 
55
** the "state" variable. When state is AllDone, ConnectThread() exits.
 
56
**
 
57
** AcceptThread() calls PR_AcceptRead() on the socket. He fully expects
 
58
** it to time out. After the timeout, AccpetThread() interacts with
 
59
** JitterThread() via a common condition variable and the state
 
60
** variable. The two threads ping-pong back and forth, each thread
 
61
** writes the the file opened by main. This should provoke the
 
62
** condition reported by NES (if we didn't fix it).
 
63
**
 
64
** The failure is not solid. It may fail within a few ping-pongs between
 
65
** AcceptThread() and JitterThread() or may take a while. The default
 
66
** iteration count, jitter, is set by DEFAULT_JITTER. This may be
 
67
** modified at the command line with the -j option.
 
68
** 
 
69
*/
 
70
 
 
71
#include <plgetopt.h> 
 
72
#include <nspr.h> 
 
73
#include <stdio.h>
 
74
#include <stdlib.h>
 
75
#include <string.h>
 
76
 
 
77
/*
 
78
** Test harness infrastructure
 
79
*/
 
80
PRLogModuleInfo *lm;
 
81
PRLogModuleLevel msgLevel = PR_LOG_NONE;
 
82
PRIntn  debug = 0;
 
83
PRIntn  verbose = 0;
 
84
PRUint32  failed_already = 0;
 
85
/* end Test harness infrastructure */
 
86
 
 
87
/* JITTER_DEFAULT: the number of times AcceptThread() and JitterThread() ping-pong */
 
88
#define JITTER_DEFAULT  100000
 
89
#define BASE_PORT 9867
 
90
 
 
91
PRIntervalTime timeout;
 
92
PRNetAddr   listenAddr;
 
93
PRFileDesc  *listenSock;
 
94
PRLock      *ml;
 
95
PRCondVar   *cv;
 
96
volatile enum  {
 
97
    RunJitter,
 
98
    RunAcceptRead,
 
99
    AllDone
 
100
} state = RunAcceptRead;
 
101
PRFileDesc  *file1;
 
102
PRIntn  iCounter = 0;
 
103
PRIntn  jitter = JITTER_DEFAULT;
 
104
PRBool  resume = PR_FALSE;
 
105
 
 
106
/*
 
107
** Emit help text for this test
 
108
*/
 
109
static void Help( void )
 
110
{
 
111
    printf("Template: Help(): display your help message(s) here");
 
112
    exit(1);
 
113
} /* end Help() */
 
114
 
 
115
 
 
116
/*
 
117
** static computation of PR_AcceptRead() buffer size.
 
118
*/
 
119
#define ACCEPT_READ_DATASIZE 10
 
120
#define ACCEPT_READ_BUFSIZE (PR_ACCEPT_READ_BUF_OVERHEAD + ACCEPT_READ_DATASIZE)
 
121
 
 
122
static void AcceptThread(void *arg)
 
123
{
 
124
    PRIntn bytesRead;
 
125
    char dataBuf[ACCEPT_READ_BUFSIZE];
 
126
    PRFileDesc  *arSock;
 
127
    PRNetAddr   *arAddr;
 
128
 
 
129
    bytesRead = PR_AcceptRead( listenSock, 
 
130
        &arSock,
 
131
        &arAddr,
 
132
        dataBuf,
 
133
        ACCEPT_READ_DATASIZE,
 
134
        PR_SecondsToInterval(1));
 
135
 
 
136
    if ( bytesRead == -1 && PR_GetError() == PR_IO_TIMEOUT_ERROR )
 
137
        if ( debug ) printf("AcceptRead timed out\n");
 
138
    else
 
139
        if ( debug ) printf("Oops! read: %d, error: %d\n", bytesRead, PR_GetError());
 
140
 
 
141
    while( state != AllDone )  {
 
142
        PR_Lock( ml );
 
143
        while( state != RunAcceptRead )
 
144
            PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT );
 
145
        if ( ++iCounter >= jitter )
 
146
            state = AllDone;
 
147
        else
 
148
            state = RunJitter;
 
149
        if ( verbose ) printf(".");
 
150
        PR_NotifyCondVar( cv );
 
151
        PR_Unlock( ml );
 
152
        PR_Write( file1, ".", 1 );
 
153
    }
 
154
 
 
155
    return;
 
156
} /* end AcceptThread() */
 
157
 
 
158
static void JitterThread(void *arg)
 
159
{
 
160
    while( state != AllDone )  {
 
161
        PR_Lock( ml );
 
162
        while( state != RunJitter && state != AllDone )
 
163
            PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT );
 
164
        if ( state != AllDone)
 
165
            state = RunAcceptRead;
 
166
        if ( verbose ) printf("+");
 
167
        PR_NotifyCondVar( cv );
 
168
        PR_Unlock( ml );
 
169
        PR_Write( file1, "+", 1 );
 
170
    }
 
171
    return;
 
172
} /* end Goofy() */
 
173
 
 
174
static void ConnectThread( void *arg )
 
175
{
 
176
    PRStatus    rv;
 
177
    PRFileDesc  *clientSock;
 
178
    PRNetAddr   serverAddress;
 
179
    clientSock = PR_NewTCPSocket();
 
180
 
 
181
    PR_ASSERT(clientSock);
 
182
 
 
183
    if ( resume ) {
 
184
        if ( debug ) printf("pausing 3 seconds before connect\n");
 
185
        PR_Sleep( PR_SecondsToInterval(3));
 
186
    }
 
187
 
 
188
    memset(&serverAddress, 0, sizeof(serverAddress));
 
189
    rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddress);
 
190
    PR_ASSERT( PR_SUCCESS == rv );
 
191
    rv = PR_Connect( clientSock, 
 
192
        &serverAddress, 
 
193
        PR_SecondsToInterval(1));
 
194
    PR_ASSERT( PR_SUCCESS == rv );
 
195
 
 
196
    /* that's all we do. ... Wait for the acceptread() to timeout */
 
197
    while( state != AllDone )
 
198
        PR_Sleep( PR_SecondsToInterval(1));
 
199
    return;
 
200
} /* end ConnectThread() */
 
201
 
 
202
 
 
203
PRIntn main(PRIntn argc, char *argv[])
 
204
{
 
205
    PRThread *tJitter;
 
206
    PRThread *tAccept;
 
207
    PRThread *tConnect;
 
208
    PRStatus rv;
 
209
    /* This test if valid for WinNT only! */
 
210
 
 
211
#if !defined(WINNT)
 
212
    return 0;
 
213
#endif
 
214
 
 
215
    {
 
216
        /*
 
217
        ** Get command line options
 
218
        */
 
219
        PLOptStatus os;
 
220
        PLOptState *opt = PL_CreateOptState(argc, argv, "hdrvj:");
 
221
 
 
222
            while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
 
223
        {
 
224
                    if (PL_OPT_BAD == os) continue;
 
225
            switch (opt->option)
 
226
            {
 
227
            case 'd':  /* debug */
 
228
                debug = 1;
 
229
                            msgLevel = PR_LOG_ERROR;
 
230
                break;
 
231
            case 'v':  /* verbose mode */
 
232
                verbose = 1;
 
233
                            msgLevel = PR_LOG_DEBUG;
 
234
                break;
 
235
            case 'j':
 
236
                jitter = atoi(opt->value);
 
237
                if ( jitter == 0)
 
238
                    jitter = JITTER_DEFAULT;
 
239
                break;
 
240
            case 'r':
 
241
                resume = PR_TRUE;
 
242
                break;
 
243
            case 'h':  /* help message */
 
244
                            Help();
 
245
                break;
 
246
             default:
 
247
                break;
 
248
            }
 
249
        }
 
250
            PL_DestroyOptState(opt);
 
251
    }
 
252
 
 
253
    lm = PR_NewLogModule("Test");       /* Initialize logging */
 
254
 
 
255
    /* set concurrency */
 
256
    PR_SetConcurrency( 4 );
 
257
 
 
258
    /* setup thread synchronization mechanics */
 
259
    ml = PR_NewLock();
 
260
    cv = PR_NewCondVar( ml );
 
261
 
 
262
    /* setup a tcp socket */
 
263
    memset(&listenAddr, 0, sizeof(listenAddr));
 
264
    rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr);
 
265
    PR_ASSERT( PR_SUCCESS == rv );
 
266
 
 
267
    listenSock = PR_NewTCPSocket();
 
268
    PR_ASSERT( listenSock );
 
269
 
 
270
    rv = PR_Bind( listenSock, &listenAddr);
 
271
    PR_ASSERT( PR_SUCCESS == rv );
 
272
 
 
273
    rv = PR_Listen( listenSock, 5 );
 
274
    PR_ASSERT( PR_SUCCESS == rv );
 
275
 
 
276
    /* open a file for writing, provoke bug */
 
277
    file1 = PR_Open("xxxTestFile", PR_CREATE_FILE | PR_RDWR, 666);
 
278
 
 
279
    /* create Connect thread */
 
280
    tConnect = PR_CreateThread(
 
281
        PR_USER_THREAD, ConnectThread, NULL,
 
282
        PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
 
283
        PR_JOINABLE_THREAD, 0 );
 
284
    PR_ASSERT( tConnect );
 
285
 
 
286
    /* create jitter off thread */
 
287
    tJitter = PR_CreateThread(
 
288
        PR_USER_THREAD, JitterThread, NULL,
 
289
        PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
 
290
        PR_JOINABLE_THREAD, 0 );
 
291
    PR_ASSERT( tJitter );
 
292
 
 
293
    /* create acceptread thread */
 
294
    tAccept = PR_CreateThread(
 
295
        PR_USER_THREAD, AcceptThread, NULL,
 
296
        PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
 
297
        PR_JOINABLE_THREAD, 0 );
 
298
    PR_ASSERT( tAccept );
 
299
 
 
300
    /* wait for all threads to quit, then terminate gracefully */
 
301
    PR_JoinThread( tConnect );
 
302
    PR_JoinThread( tAccept );
 
303
    PR_JoinThread( tJitter );
 
304
    PR_Close( listenSock );
 
305
    PR_DestroyCondVar(cv);
 
306
    PR_DestroyLock(ml);
 
307
    PR_Close( file1 );
 
308
    PR_Delete( "xxxTestFile");
 
309
 
 
310
    /* test return and exit */
 
311
    if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
 
312
    return( (failed_already == PR_TRUE )? 1 : 0 );
 
313
}  /* main() */
 
314
/* end ntioto.c */