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
49 #include "mozilla/Monitor.h"
50 using namespace mozilla
;
52 /** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */
53 nsresult
TP_NewPipe2(nsIAsyncInputStream
** input
,
54 nsIAsyncOutputStream
** output
,
55 PRBool nonBlockingInput
,
56 PRBool nonBlockingOutput
,
58 PRUint32 segmentCount
,
59 nsIMemory
* segmentAlloc
)
61 nsCOMPtr
<nsIPipe
> pipe
= do_CreateInstance("@mozilla.org/pipe;1");
63 return NS_ERROR_OUT_OF_MEMORY
;
65 nsresult rv
= pipe
->Init(nonBlockingInput
,
74 pipe
->GetInputStream(input
);
75 pipe
->GetOutputStream(output
);
79 /** NS_NewPipe reimplemented, because it's not exported by XPCOM */
80 #define TP_DEFAULT_SEGMENT_SIZE 4096
81 nsresult
TP_NewPipe(nsIInputStream
**pipeIn
,
82 nsIOutputStream
**pipeOut
,
83 PRUint32 segmentSize
= 0,
85 PRBool nonBlockingInput
= PR_FALSE
,
86 PRBool nonBlockingOutput
= PR_FALSE
,
87 nsIMemory
*segmentAlloc
= nsnull
);
88 nsresult
TP_NewPipe(nsIInputStream
**pipeIn
,
89 nsIOutputStream
**pipeOut
,
92 PRBool nonBlockingInput
,
93 PRBool nonBlockingOutput
,
94 nsIMemory
*segmentAlloc
)
97 segmentSize
= TP_DEFAULT_SEGMENT_SIZE
;
99 // Handle maxSize of PR_UINT32_MAX as a special case
100 PRUint32 segmentCount
;
101 if (maxSize
== PR_UINT32_MAX
)
102 segmentCount
= PR_UINT32_MAX
;
104 segmentCount
= maxSize
/ segmentSize
;
106 nsIAsyncInputStream
*in
;
107 nsIAsyncOutputStream
*out
;
108 nsresult rv
= TP_NewPipe2(&in
, &out
, nonBlockingInput
, nonBlockingOutput
,
109 segmentSize
, segmentCount
, segmentAlloc
);
110 if (NS_FAILED(rv
)) return rv
;
119 #define ITERATIONS 33333
120 char kTestPattern
[] = "My hovercraft is full of eels.\n";
122 PRBool gTrace
= PR_FALSE
;
125 WriteAll(nsIOutputStream
*os
, const char *buf
, PRUint32 bufLen
, PRUint32
*lenWritten
)
131 nsresult rv
= os
->Write(p
, bufLen
, &n
);
132 if (NS_FAILED(rv
)) return rv
;
140 class nsReceiver
: public nsIRunnable
{
148 PRIntervalTime start
= PR_IntervalNow();
150 rv
= mIn
->Read(buf
, 100, &count
);
152 printf("read failed\n");
156 // printf("EOF count = %d\n", mCount);
162 printf("read: %s\n", buf
);
166 PRIntervalTime end
= PR_IntervalNow();
167 printf("read %d bytes, time = %dms\n", mCount
,
168 PR_IntervalToMilliseconds(end
- start
));
172 nsReceiver(nsIInputStream
* in
) : mIn(in
), mCount(0) {
175 PRUint32
GetBytesRead() { return mCount
; }
178 nsCOMPtr
<nsIInputStream
> mIn
;
182 NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver
, nsIRunnable
)
185 TestPipe(nsIInputStream
* in
, nsIOutputStream
* out
)
187 nsCOMPtr
<nsReceiver
> receiver
= new nsReceiver(in
);
189 return NS_ERROR_OUT_OF_MEMORY
;
193 nsCOMPtr
<nsIThread
> thread
;
194 rv
= NS_NewThread(getter_AddRefs(thread
), receiver
);
195 if (NS_FAILED(rv
)) return rv
;
198 PRIntervalTime start
= PR_IntervalNow();
199 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
201 char *buf
= PR_smprintf("%d %s", i
, kTestPattern
);
202 PRUint32 len
= strlen(buf
);
203 rv
= WriteAll(out
, buf
, len
, &writeCount
);
206 for (PRUint32 j
= 0; j
< writeCount
; j
++) {
207 putc(buf
[j
], stdout
);
211 PR_smprintf_free(buf
);
212 if (NS_FAILED(rv
)) return rv
;
216 if (NS_FAILED(rv
)) return rv
;
218 PRIntervalTime end
= PR_IntervalNow();
222 printf("wrote %d bytes, time = %dms\n", total
,
223 PR_IntervalToMilliseconds(end
- start
));
224 NS_ASSERTION(receiver
->GetBytesRead() == total
, "didn't read everything");
229 ////////////////////////////////////////////////////////////////////////////////
231 class nsShortReader
: public nsIRunnable
{
242 // printf("calling Read\n");
243 rv
= mIn
->Read(buf
, 100, &count
);
245 printf("read failed\n");
253 // For next |printf()| call and possible others elsewhere.
256 printf("read %d bytes: %s\n", count
, buf
);
262 printf("read %d bytes\n", total
);
266 nsShortReader(nsIInputStream
* in
) : mIn(in
), mReceived(0) {
267 mMon
= new Monitor("nsShortReader");
270 void Received(PRUint32 count
) {
271 MonitorAutoEnter
mon(*mMon
);
276 PRUint32
WaitForReceipt(const PRUint32 aWriteCount
) {
277 MonitorAutoEnter
mon(*mMon
);
278 PRUint32 result
= mReceived
;
280 while (result
< aWriteCount
) {
283 NS_ASSERTION(mReceived
> result
, "failed to receive");
292 nsCOMPtr
<nsIInputStream
> mIn
;
297 NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader
, nsIRunnable
)
300 TestShortWrites(nsIInputStream
* in
, nsIOutputStream
* out
)
302 nsCOMPtr
<nsShortReader
> receiver
= new nsShortReader(in
);
304 return NS_ERROR_OUT_OF_MEMORY
;
308 nsCOMPtr
<nsIThread
> thread
;
309 rv
= NS_NewThread(getter_AddRefs(thread
), receiver
);
310 if (NS_FAILED(rv
)) return rv
;
313 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
315 char* buf
= PR_smprintf("%d %s", i
, kTestPattern
);
316 PRUint32 len
= strlen(buf
);
317 len
= len
* rand() / RAND_MAX
;
318 len
= PR_MAX(1, len
);
319 rv
= WriteAll(out
, buf
, len
, &writeCount
);
320 if (NS_FAILED(rv
)) return rv
;
321 NS_ASSERTION(writeCount
== len
, "didn't write enough");
325 printf("wrote %d bytes: %s\n", writeCount
, buf
);
326 PR_smprintf_free(buf
);
327 //printf("calling Flush\n");
329 //printf("calling WaitForReceipt\n");
332 const PRUint32 received
=
334 receiver
->WaitForReceipt(writeCount
);
335 NS_ASSERTION(received
== writeCount
, "received wrong amount");
338 if (NS_FAILED(rv
)) return rv
;
342 printf("wrote %d bytes\n", total
);
347 ////////////////////////////////////////////////////////////////////////////////
349 class nsPump
: public nsIRunnable
358 rv
= mOut
->WriteFrom(mIn
, ~0U, &count
);
360 printf("Write failed\n");
364 printf("EOF count = %d\n", mCount
);
369 printf("Wrote: %d\n", count
);
377 nsPump(nsIInputStream
* in
,
378 nsIOutputStream
* out
)
379 : mIn(in
), mOut(out
), mCount(0) {
383 nsCOMPtr
<nsIInputStream
> mIn
;
384 nsCOMPtr
<nsIOutputStream
> mOut
;
388 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPump
,
395 printf("TestChainedPipes\n");
397 nsCOMPtr
<nsIInputStream
> in1
;
398 nsCOMPtr
<nsIOutputStream
> out1
;
399 rv
= TP_NewPipe(getter_AddRefs(in1
), getter_AddRefs(out1
), 20, 1999);
400 if (NS_FAILED(rv
)) return rv
;
402 nsCOMPtr
<nsIInputStream
> in2
;
403 nsCOMPtr
<nsIOutputStream
> out2
;
404 rv
= TP_NewPipe(getter_AddRefs(in2
), getter_AddRefs(out2
), 200, 401);
405 if (NS_FAILED(rv
)) return rv
;
407 nsCOMPtr
<nsPump
> pump
= new nsPump(in1
, out2
);
408 if (pump
== nsnull
) return NS_ERROR_OUT_OF_MEMORY
;
410 nsCOMPtr
<nsIThread
> thread
;
411 rv
= NS_NewThread(getter_AddRefs(thread
), pump
);
412 if (NS_FAILED(rv
)) return rv
;
414 nsCOMPtr
<nsReceiver
> receiver
= new nsReceiver(in2
);
415 if (receiver
== nsnull
) return NS_ERROR_OUT_OF_MEMORY
;
417 nsCOMPtr
<nsIThread
> receiverThread
;
418 rv
= NS_NewThread(getter_AddRefs(receiverThread
), receiver
);
419 if (NS_FAILED(rv
)) return rv
;
422 for (PRUint32 i
= 0; i
< ITERATIONS
; i
++) {
424 char* buf
= PR_smprintf("%d %s", i
, kTestPattern
);
425 PRUint32 len
= strlen(buf
);
426 len
= len
* rand() / RAND_MAX
;
427 len
= PR_MAX(1, len
);
428 rv
= WriteAll(out1
, buf
, len
, &writeCount
);
429 if (NS_FAILED(rv
)) return rv
;
430 NS_ASSERTION(writeCount
== len
, "didn't write enough");
434 printf("wrote %d bytes: %s\n", writeCount
, buf
);
436 PR_smprintf_free(buf
);
438 printf("wrote total of %d bytes\n", total
);
440 if (NS_FAILED(rv
)) return rv
;
443 receiverThread
->Shutdown();
448 ////////////////////////////////////////////////////////////////////////////////
451 RunTests(PRUint32 segSize
, PRUint32 segCount
)
454 nsCOMPtr
<nsIInputStream
> in
;
455 nsCOMPtr
<nsIOutputStream
> out
;
456 PRUint32 bufSize
= segSize
* segCount
;
457 printf("Testing New Pipes: segment size %d buffer size %d\n", segSize
, bufSize
);
459 printf("Testing long writes...\n");
460 rv
= TP_NewPipe(getter_AddRefs(in
), getter_AddRefs(out
), segSize
, bufSize
);
461 NS_ASSERTION(NS_SUCCEEDED(rv
), "TP_NewPipe failed");
462 rv
= TestPipe(in
, out
);
463 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestPipe failed");
465 printf("Testing short writes...\n");
466 rv
= TP_NewPipe(getter_AddRefs(in
), getter_AddRefs(out
), segSize
, bufSize
);
467 NS_ASSERTION(NS_SUCCEEDED(rv
), "TP_NewPipe failed");
468 rv
= TestShortWrites(in
, out
);
469 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestPipe failed");
472 ////////////////////////////////////////////////////////////////////////////////
474 #if !defined(MOZ_ENABLE_LIBXUL) && defined(DEBUG)
476 TestSegmentedBuffer();
480 main(int argc
, char* argv
[])
484 nsCOMPtr
<nsIServiceManager
> servMgr
;
485 rv
= NS_InitXPCOM2(getter_AddRefs(servMgr
), NULL
, NULL
);
486 if (NS_FAILED(rv
)) return rv
;
488 if (argc
> 1 && nsCRT::strcmp(argv
[1], "-trace") == 0)
491 #if !defined(MOZ_ENABLE_LIBXUL) && defined(DEBUG)
492 printf("Testing segmented buffer...\n");
493 TestSegmentedBuffer();
496 rv
= TestChainedPipes();
497 NS_ASSERTION(NS_SUCCEEDED(rv
), "TestChainedPipes failed");
502 rv
= NS_ShutdownXPCOM( NULL
);
503 NS_ASSERTION(NS_SUCCEEDED(rv
), "NS_ShutdownXPCOM failed");
508 ////////////////////////////////////////////////////////////////////////////////