1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "TestHarness.h"
41 #include "nsIThread.h"
42 #include "nsIRunnable.h"
43 #include "nsThreadUtils.h"
47 #include "nsIPipe.h" // new implementation
48 #include "nsAutoLock.h"
51 /** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */
52 nsresult
TP_NewPipe2(nsIAsyncInputStream
** input
,
53 nsIAsyncOutputStream
** output
,
54 PRBool nonBlockingInput
,
55 PRBool nonBlockingOutput
,
57 PRUint32 segmentCount
,
58 nsIMemory
* segmentAlloc
)
60 nsCOMPtr
<nsIPipe
> pipe
= do_CreateInstance("@mozilla.org/pipe;1");
62 return NS_ERROR_OUT_OF_MEMORY
;
64 nsresult rv
= pipe
->Init(nonBlockingInput
,
73 pipe
->GetInputStream(input
);
74 pipe
->GetOutputStream(output
);
78 /** NS_NewPipe reimplemented, because it's not exported by XPCOM */
79 #define TP_DEFAULT_SEGMENT_SIZE 4096
80 nsresult
TP_NewPipe(nsIInputStream
**pipeIn
,
81 nsIOutputStream
**pipeOut
,
82 PRUint32 segmentSize
= 0,
84 PRBool nonBlockingInput
= PR_FALSE
,
85 PRBool nonBlockingOutput
= PR_FALSE
,
86 nsIMemory
*segmentAlloc
= nsnull
);
87 nsresult
TP_NewPipe(nsIInputStream
**pipeIn
,
88 nsIOutputStream
**pipeOut
,
91 PRBool nonBlockingInput
,
92 PRBool nonBlockingOutput
,
93 nsIMemory
*segmentAlloc
)
96 segmentSize
= TP_DEFAULT_SEGMENT_SIZE
;
98 // Handle maxSize of PR_UINT32_MAX as a special case
99 PRUint32 segmentCount
;
100 if (maxSize
== PR_UINT32_MAX
)
101 segmentCount
= PR_UINT32_MAX
;
103 segmentCount
= maxSize
/ segmentSize
;
105 nsIAsyncInputStream
*in
;
106 nsIAsyncOutputStream
*out
;
107 nsresult rv
= TP_NewPipe2(&in
, &out
, nonBlockingInput
, nonBlockingOutput
,
108 segmentSize
, segmentCount
, segmentAlloc
);
109 if (NS_FAILED(rv
)) return rv
;
118 #define ITERATIONS 33333
119 char kTestPattern
[] = "My hovercraft is full of eels.\n";
121 PRBool gTrace
= PR_FALSE
;
124 WriteAll(nsIOutputStream
*os
, const char *buf
, PRUint32 bufLen
, PRUint32
*lenWritten
)
130 nsresult rv
= os
->Write(p
, bufLen
, &n
);
131 if (NS_FAILED(rv
)) return rv
;
139 class nsReceiver
: public nsIRunnable
{
147 PRIntervalTime start
= PR_IntervalNow();
149 rv
= mIn
->Read(buf
, 100, &count
);
151 printf("read failed\n");
155 // printf("EOF count = %d\n", mCount);
161 printf("read: %s\n", buf
);
165 PRIntervalTime end
= PR_IntervalNow();
166 printf("read %d bytes, time = %dms\n", mCount
,
167 PR_IntervalToMilliseconds(end
- start
));
171 nsReceiver(nsIInputStream
* in
) : mIn(in
), mCount(0) {
174 PRUint32
GetBytesRead() { return mCount
; }
177 nsCOMPtr
<nsIInputStream
> mIn
;
181 NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver
, nsIRunnable
)
184 TestPipe(nsIInputStream
* in
, nsIOutputStream
* out
)
186 nsCOMPtr
<nsReceiver
> receiver
= new nsReceiver(in
);
188 return NS_ERROR_OUT_OF_MEMORY
;
192 nsCOMPtr
<nsIThread
> thread
;
193 rv
= NS_NewThread(getter_AddRefs(thread
), receiver
);
194 if (NS_FAILED(rv
)) return rv
;
197 PRIntervalTime start
= PR_IntervalNow();
198 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
200 char *buf
= PR_smprintf("%d %s", i
, kTestPattern
);
201 PRUint32 len
= strlen(buf
);
202 rv
= WriteAll(out
, buf
, len
, &writeCount
);
205 for (PRUint32 j
= 0; j
< writeCount
; j
++) {
206 putc(buf
[j
], stdout
);
210 PR_smprintf_free(buf
);
211 if (NS_FAILED(rv
)) return rv
;
215 if (NS_FAILED(rv
)) return rv
;
217 PRIntervalTime end
= PR_IntervalNow();
221 printf("wrote %d bytes, time = %dms\n", total
,
222 PR_IntervalToMilliseconds(end
- start
));
223 NS_ASSERTION(receiver
->GetBytesRead() == total
, "didn't read everything");
228 ////////////////////////////////////////////////////////////////////////////////
230 class nsShortReader
: public nsIRunnable
{
241 // printf("calling Read\n");
242 rv
= mIn
->Read(buf
, 100, &count
);
244 printf("read failed\n");
252 // For next |printf()| call and possible others elsewhere.
255 printf("read %d bytes: %s\n", count
, buf
);
261 printf("read %d bytes\n", total
);
265 nsShortReader(nsIInputStream
* in
) : mIn(in
), mReceived(0) {
268 void Received(PRUint32 count
) {
269 nsAutoCMonitor
mon(this);
274 PRUint32
WaitForReceipt(const PRUint32 aWriteCount
) {
275 nsAutoCMonitor
mon(this);
276 PRUint32 result
= mReceived
;
278 while (result
< aWriteCount
) {
281 NS_ASSERTION(mReceived
> result
, "failed to receive");
290 nsCOMPtr
<nsIInputStream
> mIn
;
294 NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader
, nsIRunnable
)
297 TestShortWrites(nsIInputStream
* in
, nsIOutputStream
* out
)
299 nsCOMPtr
<nsShortReader
> receiver
= new nsShortReader(in
);
301 return NS_ERROR_OUT_OF_MEMORY
;
305 nsCOMPtr
<nsIThread
> thread
;
306 rv
= NS_NewThread(getter_AddRefs(thread
), receiver
);
307 if (NS_FAILED(rv
)) return rv
;
310 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
312 char* buf
= PR_smprintf("%d %s", i
, kTestPattern
);
313 PRUint32 len
= strlen(buf
);
314 len
= len
* rand() / RAND_MAX
;
315 len
= PR_MAX(1, len
);
316 rv
= WriteAll(out
, buf
, len
, &writeCount
);
317 if (NS_FAILED(rv
)) return rv
;
318 NS_ASSERTION(writeCount
== len
, "didn't write enough");
322 printf("wrote %d bytes: %s\n", writeCount
, buf
);
323 PR_smprintf_free(buf
);
324 //printf("calling Flush\n");
326 //printf("calling WaitForReceipt\n");
327 const PRUint32 received
= receiver
->WaitForReceipt(writeCount
);
328 NS_ASSERTION(received
== writeCount
, "received wrong amount");
331 if (NS_FAILED(rv
)) return rv
;
335 printf("wrote %d bytes\n", total
);
340 ////////////////////////////////////////////////////////////////////////////////
342 class nsPump
: public nsIRunnable
351 rv
= mOut
->WriteFrom(mIn
, ~0U, &count
);
353 printf("Write failed\n");
357 printf("EOF count = %d\n", mCount
);
362 printf("Wrote: %d\n", count
);
370 nsPump(nsIInputStream
* in
,
371 nsIOutputStream
* out
)
372 : mIn(in
), mOut(out
), mCount(0) {
376 nsCOMPtr
<nsIInputStream
> mIn
;
377 nsCOMPtr
<nsIOutputStream
> mOut
;
381 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPump
,
388 printf("TestChainedPipes\n");
390 nsCOMPtr
<nsIInputStream
> in1
;
391 nsCOMPtr
<nsIOutputStream
> out1
;
392 rv
= TP_NewPipe(getter_AddRefs(in1
), getter_AddRefs(out1
), 20, 1999);
393 if (NS_FAILED(rv
)) return rv
;
395 nsCOMPtr
<nsIInputStream
> in2
;
396 nsCOMPtr
<nsIOutputStream
> out2
;
397 rv
= TP_NewPipe(getter_AddRefs(in2
), getter_AddRefs(out2
), 200, 401);
398 if (NS_FAILED(rv
)) return rv
;
400 nsCOMPtr
<nsPump
> pump
= new nsPump(in1
, out2
);
401 if (pump
== nsnull
) return NS_ERROR_OUT_OF_MEMORY
;
403 nsCOMPtr
<nsIThread
> thread
;
404 rv
= NS_NewThread(getter_AddRefs(thread
), pump
);
405 if (NS_FAILED(rv
)) return rv
;
407 nsCOMPtr
<nsReceiver
> receiver
= new nsReceiver(in2
);
408 if (receiver
== nsnull
) return NS_ERROR_OUT_OF_MEMORY
;
410 nsCOMPtr
<nsIThread
> receiverThread
;
411 rv
= NS_NewThread(getter_AddRefs(receiverThread
), receiver
);
412 if (NS_FAILED(rv
)) return rv
;
415 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
417 char* buf
= PR_smprintf("%d %s", i
, kTestPattern
);
418 PRUint32 len
= strlen(buf
);
419 len
= len
* rand() / RAND_MAX
;
420 len
= PR_MAX(1, len
);
421 rv
= WriteAll(out1
, buf
, len
, &writeCount
);
422 if (NS_FAILED(rv
)) return rv
;
423 NS_ASSERTION(writeCount
== len
, "didn't write enough");
427 printf("wrote %d bytes: %s\n", writeCount
, buf
);
429 PR_smprintf_free(buf
);
431 printf("wrote total of %d bytes\n", total
);
433 if (NS_FAILED(rv
)) return rv
;
436 receiverThread
->Shutdown();
441 ////////////////////////////////////////////////////////////////////////////////
444 RunTests(PRUint32 segSize
, PRUint32 segCount
)
447 nsCOMPtr
<nsIInputStream
> in
;
448 nsCOMPtr
<nsIOutputStream
> out
;
449 PRUint32 bufSize
= segSize
* segCount
;
450 printf("Testing New Pipes: segment size %d buffer size %d\n", segSize
, bufSize
);
452 printf("Testing long writes...\n");
453 rv
= TP_NewPipe(getter_AddRefs(in
), getter_AddRefs(out
), segSize
, bufSize
);
454 NS_ASSERTION(NS_SUCCEEDED(rv
), "TP_NewPipe failed");
455 rv
= TestPipe(in
, out
);
456 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestPipe failed");
458 printf("Testing short writes...\n");
459 rv
= TP_NewPipe(getter_AddRefs(in
), getter_AddRefs(out
), segSize
, bufSize
);
460 NS_ASSERTION(NS_SUCCEEDED(rv
), "TP_NewPipe failed");
461 rv
= TestShortWrites(in
, out
);
462 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestPipe failed");
465 ////////////////////////////////////////////////////////////////////////////////
467 #if !defined(MOZ_ENABLE_LIBXUL) && defined(DEBUG)
469 TestSegmentedBuffer();
473 main(int argc
, char* argv
[])
477 nsCOMPtr
<nsIServiceManager
> servMgr
;
478 rv
= NS_InitXPCOM2(getter_AddRefs(servMgr
), NULL
, NULL
);
479 if (NS_FAILED(rv
)) return rv
;
481 if (argc
> 1 && nsCRT::strcmp(argv
[1], "-trace") == 0)
484 #if !defined(MOZ_ENABLE_LIBXUL) && defined(DEBUG)
485 printf("Testing segmented buffer...\n");
486 TestSegmentedBuffer();
489 rv
= TestChainedPipes();
490 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestChainedPipes failed");
495 rv
= NS_ShutdownXPCOM( NULL
);
496 NS_ASSERTION(NS_SUCCEEDED(rv
), "NS_ShutdownXPCOM failed");
501 ////////////////////////////////////////////////////////////////////////////////