Bug 545892 - Always pass WM_NCPAINT events to the default event procedure. r=bent...
[mozilla-central.git] / xpcom / tests / TestPipes.cpp
blob47c267b05fdc21db303252bc0da19301ab4bbabc
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
13 * License.
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.
22 * Contributor(s):
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"
44 #include "prprf.h"
45 #include "prinrval.h"
46 #include "nsCRT.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,
57 PRUint32 segmentSize,
58 PRUint32 segmentCount,
59 nsIMemory* segmentAlloc)
61 nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
62 if (!pipe)
63 return NS_ERROR_OUT_OF_MEMORY;
65 nsresult rv = pipe->Init(nonBlockingInput,
66 nonBlockingOutput,
67 segmentSize,
68 segmentCount,
69 segmentAlloc);
71 if (NS_FAILED(rv))
72 return rv;
74 pipe->GetInputStream(input);
75 pipe->GetOutputStream(output);
76 return NS_OK;
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,
84 PRUint32 maxSize = 0,
85 PRBool nonBlockingInput = PR_FALSE,
86 PRBool nonBlockingOutput = PR_FALSE,
87 nsIMemory *segmentAlloc = nsnull);
88 nsresult TP_NewPipe(nsIInputStream **pipeIn,
89 nsIOutputStream **pipeOut,
90 PRUint32 segmentSize,
91 PRUint32 maxSize,
92 PRBool nonBlockingInput,
93 PRBool nonBlockingOutput,
94 nsIMemory *segmentAlloc)
96 if (segmentSize == 0)
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;
103 else
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;
112 *pipeIn = in;
113 *pipeOut = out;
114 return NS_OK;
118 #define KEY 0xa7
119 #define ITERATIONS 33333
120 char kTestPattern[] = "My hovercraft is full of eels.\n";
122 PRBool gTrace = PR_FALSE;
124 static nsresult
125 WriteAll(nsIOutputStream *os, const char *buf, PRUint32 bufLen, PRUint32 *lenWritten)
127 const char *p = buf;
128 *lenWritten = 0;
129 while (bufLen) {
130 PRUint32 n;
131 nsresult rv = os->Write(p, bufLen, &n);
132 if (NS_FAILED(rv)) return rv;
133 p += n;
134 bufLen -= n;
135 *lenWritten += n;
137 return NS_OK;
140 class nsReceiver : public nsIRunnable {
141 public:
142 NS_DECL_ISUPPORTS
144 NS_IMETHOD Run() {
145 nsresult rv;
146 char buf[101];
147 PRUint32 count;
148 PRIntervalTime start = PR_IntervalNow();
149 while (PR_TRUE) {
150 rv = mIn->Read(buf, 100, &count);
151 if (NS_FAILED(rv)) {
152 printf("read failed\n");
153 break;
155 if (count == 0) {
156 // printf("EOF count = %d\n", mCount);
157 break;
160 if (gTrace) {
161 buf[count] = '\0';
162 printf("read: %s\n", buf);
164 mCount += count;
166 PRIntervalTime end = PR_IntervalNow();
167 printf("read %d bytes, time = %dms\n", mCount,
168 PR_IntervalToMilliseconds(end - start));
169 return rv;
172 nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
175 PRUint32 GetBytesRead() { return mCount; }
177 protected:
178 nsCOMPtr<nsIInputStream> mIn;
179 PRUint32 mCount;
182 NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver, nsIRunnable)
184 nsresult
185 TestPipe(nsIInputStream* in, nsIOutputStream* out)
187 nsCOMPtr<nsReceiver> receiver = new nsReceiver(in);
188 if (!receiver)
189 return NS_ERROR_OUT_OF_MEMORY;
191 nsresult rv;
193 nsCOMPtr<nsIThread> thread;
194 rv = NS_NewThread(getter_AddRefs(thread), receiver);
195 if (NS_FAILED(rv)) return rv;
197 PRUint32 total = 0;
198 PRIntervalTime start = PR_IntervalNow();
199 for (PRUint32 i = 0; i < ITERATIONS; i++) {
200 PRUint32 writeCount;
201 char *buf = PR_smprintf("%d %s", i, kTestPattern);
202 PRUint32 len = strlen(buf);
203 rv = WriteAll(out, buf, len, &writeCount);
204 if (gTrace) {
205 printf("wrote: ");
206 for (PRUint32 j = 0; j < writeCount; j++) {
207 putc(buf[j], stdout);
209 printf("\n");
211 PR_smprintf_free(buf);
212 if (NS_FAILED(rv)) return rv;
213 total += writeCount;
215 rv = out->Close();
216 if (NS_FAILED(rv)) return rv;
218 PRIntervalTime end = PR_IntervalNow();
220 thread->Shutdown();
222 printf("wrote %d bytes, time = %dms\n", total,
223 PR_IntervalToMilliseconds(end - start));
224 NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
226 return NS_OK;
229 ////////////////////////////////////////////////////////////////////////////////
231 class nsShortReader : public nsIRunnable {
232 public:
233 NS_DECL_ISUPPORTS
235 NS_IMETHOD Run() {
236 nsresult rv;
237 char buf[101];
238 PRUint32 count;
239 PRUint32 total = 0;
240 while (PR_TRUE) {
241 //if (gTrace)
242 // printf("calling Read\n");
243 rv = mIn->Read(buf, 100, &count);
244 if (NS_FAILED(rv)) {
245 printf("read failed\n");
246 break;
248 if (count == 0) {
249 break;
252 if (gTrace) {
253 // For next |printf()| call and possible others elsewhere.
254 buf[count] = '\0';
256 printf("read %d bytes: %s\n", count, buf);
259 Received(count);
260 total += count;
262 printf("read %d bytes\n", total);
263 return rv;
266 nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
267 mMon = new Monitor("nsShortReader");
270 void Received(PRUint32 count) {
271 MonitorAutoEnter mon(*mMon);
272 mReceived += count;
273 mon.Notify();
276 PRUint32 WaitForReceipt(const PRUint32 aWriteCount) {
277 MonitorAutoEnter mon(*mMon);
278 PRUint32 result = mReceived;
280 while (result < aWriteCount) {
281 mon.Wait();
283 NS_ASSERTION(mReceived > result, "failed to receive");
284 result = mReceived;
287 mReceived = 0;
288 return result;
291 protected:
292 nsCOMPtr<nsIInputStream> mIn;
293 PRUint32 mReceived;
294 Monitor* mMon;
297 NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader, nsIRunnable)
299 nsresult
300 TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
302 nsCOMPtr<nsShortReader> receiver = new nsShortReader(in);
303 if (!receiver)
304 return NS_ERROR_OUT_OF_MEMORY;
306 nsresult rv;
308 nsCOMPtr<nsIThread> thread;
309 rv = NS_NewThread(getter_AddRefs(thread), receiver);
310 if (NS_FAILED(rv)) return rv;
312 PRUint32 total = 0;
313 for (PRUint32 i = 0; i < ITERATIONS; i++) {
314 PRUint32 writeCount;
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");
322 total += writeCount;
324 if (gTrace)
325 printf("wrote %d bytes: %s\n", writeCount, buf);
326 PR_smprintf_free(buf);
327 //printf("calling Flush\n");
328 out->Flush();
329 //printf("calling WaitForReceipt\n");
331 #ifdef DEBUG
332 const PRUint32 received =
333 #endif
334 receiver->WaitForReceipt(writeCount);
335 NS_ASSERTION(received == writeCount, "received wrong amount");
337 rv = out->Close();
338 if (NS_FAILED(rv)) return rv;
340 thread->Shutdown();
342 printf("wrote %d bytes\n", total);
344 return NS_OK;
347 ////////////////////////////////////////////////////////////////////////////////
349 class nsPump : public nsIRunnable
351 public:
352 NS_DECL_ISUPPORTS
354 NS_IMETHOD Run() {
355 nsresult rv;
356 PRUint32 count;
357 while (PR_TRUE) {
358 rv = mOut->WriteFrom(mIn, ~0U, &count);
359 if (NS_FAILED(rv)) {
360 printf("Write failed\n");
361 break;
363 if (count == 0) {
364 printf("EOF count = %d\n", mCount);
365 break;
368 if (gTrace) {
369 printf("Wrote: %d\n", count);
371 mCount += count;
373 mOut->Close();
374 return rv;
377 nsPump(nsIInputStream* in,
378 nsIOutputStream* out)
379 : mIn(in), mOut(out), mCount(0) {
382 protected:
383 nsCOMPtr<nsIInputStream> mIn;
384 nsCOMPtr<nsIOutputStream> mOut;
385 PRUint32 mCount;
388 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPump,
389 nsIRunnable)
391 nsresult
392 TestChainedPipes()
394 nsresult rv;
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;
421 PRUint32 total = 0;
422 for (PRUint32 i = 0; i < ITERATIONS; i++) {
423 PRUint32 writeCount;
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");
431 total += writeCount;
433 if (gTrace)
434 printf("wrote %d bytes: %s\n", writeCount, buf);
436 PR_smprintf_free(buf);
438 printf("wrote total of %d bytes\n", total);
439 rv = out1->Close();
440 if (NS_FAILED(rv)) return rv;
442 thread->Shutdown();
443 receiverThread->Shutdown();
445 return NS_OK;
448 ////////////////////////////////////////////////////////////////////////////////
450 void
451 RunTests(PRUint32 segSize, PRUint32 segCount)
453 nsresult rv;
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)
475 extern NS_COM void
476 TestSegmentedBuffer();
477 #endif
480 main(int argc, char* argv[])
482 nsresult rv;
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)
489 gTrace = PR_TRUE;
491 #if !defined(MOZ_ENABLE_LIBXUL) && defined(DEBUG)
492 printf("Testing segmented buffer...\n");
493 TestSegmentedBuffer();
494 #endif
496 rv = TestChainedPipes();
497 NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
498 RunTests(16, 1);
499 RunTests(4096, 16);
501 servMgr = 0;
502 rv = NS_ShutdownXPCOM( NULL );
503 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
505 return 0;
508 ////////////////////////////////////////////////////////////////////////////////