xpcom/tests/TestPipes.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "TestHarness.h"
michael@0 7
michael@0 8 #include "nsIThread.h"
michael@0 9 #include "nsIRunnable.h"
michael@0 10 #include "nsThreadUtils.h"
michael@0 11 #include "prprf.h"
michael@0 12 #include "prinrval.h"
michael@0 13 #include "nsCRT.h"
michael@0 14 #include "nsIPipe.h" // new implementation
michael@0 15
michael@0 16 #include "mozilla/Monitor.h"
michael@0 17 using namespace mozilla;
michael@0 18
michael@0 19 /** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */
michael@0 20 nsresult TP_NewPipe2(nsIAsyncInputStream** input,
michael@0 21 nsIAsyncOutputStream** output,
michael@0 22 bool nonBlockingInput,
michael@0 23 bool nonBlockingOutput,
michael@0 24 uint32_t segmentSize,
michael@0 25 uint32_t segmentCount,
michael@0 26 nsIMemory* segmentAlloc)
michael@0 27 {
michael@0 28 nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
michael@0 29 if (!pipe)
michael@0 30 return NS_ERROR_OUT_OF_MEMORY;
michael@0 31
michael@0 32 nsresult rv = pipe->Init(nonBlockingInput,
michael@0 33 nonBlockingOutput,
michael@0 34 segmentSize,
michael@0 35 segmentCount,
michael@0 36 segmentAlloc);
michael@0 37
michael@0 38 if (NS_FAILED(rv))
michael@0 39 return rv;
michael@0 40
michael@0 41 pipe->GetInputStream(input);
michael@0 42 pipe->GetOutputStream(output);
michael@0 43 return NS_OK;
michael@0 44 }
michael@0 45
michael@0 46 /** NS_NewPipe reimplemented, because it's not exported by XPCOM */
michael@0 47 #define TP_DEFAULT_SEGMENT_SIZE 4096
michael@0 48 nsresult TP_NewPipe(nsIInputStream **pipeIn,
michael@0 49 nsIOutputStream **pipeOut,
michael@0 50 uint32_t segmentSize = 0,
michael@0 51 uint32_t maxSize = 0,
michael@0 52 bool nonBlockingInput = false,
michael@0 53 bool nonBlockingOutput = false,
michael@0 54 nsIMemory *segmentAlloc = nullptr);
michael@0 55 nsresult TP_NewPipe(nsIInputStream **pipeIn,
michael@0 56 nsIOutputStream **pipeOut,
michael@0 57 uint32_t segmentSize,
michael@0 58 uint32_t maxSize,
michael@0 59 bool nonBlockingInput,
michael@0 60 bool nonBlockingOutput,
michael@0 61 nsIMemory *segmentAlloc)
michael@0 62 {
michael@0 63 if (segmentSize == 0)
michael@0 64 segmentSize = TP_DEFAULT_SEGMENT_SIZE;
michael@0 65
michael@0 66 // Handle maxSize of UINT32_MAX as a special case
michael@0 67 uint32_t segmentCount;
michael@0 68 if (maxSize == UINT32_MAX)
michael@0 69 segmentCount = UINT32_MAX;
michael@0 70 else
michael@0 71 segmentCount = maxSize / segmentSize;
michael@0 72
michael@0 73 nsIAsyncInputStream *in;
michael@0 74 nsIAsyncOutputStream *out;
michael@0 75 nsresult rv = TP_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput,
michael@0 76 segmentSize, segmentCount, segmentAlloc);
michael@0 77 if (NS_FAILED(rv)) return rv;
michael@0 78
michael@0 79 *pipeIn = in;
michael@0 80 *pipeOut = out;
michael@0 81 return NS_OK;
michael@0 82 }
michael@0 83
michael@0 84
michael@0 85 #define KEY 0xa7
michael@0 86 #define ITERATIONS 33333
michael@0 87 char kTestPattern[] = "My hovercraft is full of eels.\n";
michael@0 88
michael@0 89 bool gTrace = false;
michael@0 90
michael@0 91 static nsresult
michael@0 92 WriteAll(nsIOutputStream *os, const char *buf, uint32_t bufLen, uint32_t *lenWritten)
michael@0 93 {
michael@0 94 const char *p = buf;
michael@0 95 *lenWritten = 0;
michael@0 96 while (bufLen) {
michael@0 97 uint32_t n;
michael@0 98 nsresult rv = os->Write(p, bufLen, &n);
michael@0 99 if (NS_FAILED(rv)) return rv;
michael@0 100 p += n;
michael@0 101 bufLen -= n;
michael@0 102 *lenWritten += n;
michael@0 103 }
michael@0 104 return NS_OK;
michael@0 105 }
michael@0 106
michael@0 107 class nsReceiver : public nsIRunnable {
michael@0 108 public:
michael@0 109 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 110
michael@0 111 NS_IMETHOD Run() {
michael@0 112 nsresult rv;
michael@0 113 char buf[101];
michael@0 114 uint32_t count;
michael@0 115 PRIntervalTime start = PR_IntervalNow();
michael@0 116 while (true) {
michael@0 117 rv = mIn->Read(buf, 100, &count);
michael@0 118 if (NS_FAILED(rv)) {
michael@0 119 printf("read failed\n");
michael@0 120 break;
michael@0 121 }
michael@0 122 if (count == 0) {
michael@0 123 // printf("EOF count = %d\n", mCount);
michael@0 124 break;
michael@0 125 }
michael@0 126
michael@0 127 if (gTrace) {
michael@0 128 buf[count] = '\0';
michael@0 129 printf("read: %s\n", buf);
michael@0 130 }
michael@0 131 mCount += count;
michael@0 132 }
michael@0 133 PRIntervalTime end = PR_IntervalNow();
michael@0 134 printf("read %d bytes, time = %dms\n", mCount,
michael@0 135 PR_IntervalToMilliseconds(end - start));
michael@0 136 return rv;
michael@0 137 }
michael@0 138
michael@0 139 nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
michael@0 140 }
michael@0 141
michael@0 142 uint32_t GetBytesRead() { return mCount; }
michael@0 143
michael@0 144 protected:
michael@0 145 nsCOMPtr<nsIInputStream> mIn;
michael@0 146 uint32_t mCount;
michael@0 147 };
michael@0 148
michael@0 149 NS_IMPL_ISUPPORTS(nsReceiver, nsIRunnable)
michael@0 150
michael@0 151 nsresult
michael@0 152 TestPipe(nsIInputStream* in, nsIOutputStream* out)
michael@0 153 {
michael@0 154 nsCOMPtr<nsReceiver> receiver = new nsReceiver(in);
michael@0 155 if (!receiver)
michael@0 156 return NS_ERROR_OUT_OF_MEMORY;
michael@0 157
michael@0 158 nsresult rv;
michael@0 159
michael@0 160 nsCOMPtr<nsIThread> thread;
michael@0 161 rv = NS_NewThread(getter_AddRefs(thread), receiver);
michael@0 162 if (NS_FAILED(rv)) return rv;
michael@0 163
michael@0 164 uint32_t total = 0;
michael@0 165 PRIntervalTime start = PR_IntervalNow();
michael@0 166 for (uint32_t i = 0; i < ITERATIONS; i++) {
michael@0 167 uint32_t writeCount;
michael@0 168 char *buf = PR_smprintf("%d %s", i, kTestPattern);
michael@0 169 uint32_t len = strlen(buf);
michael@0 170 rv = WriteAll(out, buf, len, &writeCount);
michael@0 171 if (gTrace) {
michael@0 172 printf("wrote: ");
michael@0 173 for (uint32_t j = 0; j < writeCount; j++) {
michael@0 174 putc(buf[j], stdout);
michael@0 175 }
michael@0 176 printf("\n");
michael@0 177 }
michael@0 178 PR_smprintf_free(buf);
michael@0 179 if (NS_FAILED(rv)) return rv;
michael@0 180 total += writeCount;
michael@0 181 }
michael@0 182 rv = out->Close();
michael@0 183 if (NS_FAILED(rv)) return rv;
michael@0 184
michael@0 185 PRIntervalTime end = PR_IntervalNow();
michael@0 186
michael@0 187 thread->Shutdown();
michael@0 188
michael@0 189 printf("wrote %d bytes, time = %dms\n", total,
michael@0 190 PR_IntervalToMilliseconds(end - start));
michael@0 191 NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
michael@0 192
michael@0 193 return NS_OK;
michael@0 194 }
michael@0 195
michael@0 196 ////////////////////////////////////////////////////////////////////////////////
michael@0 197
michael@0 198 class nsShortReader : public nsIRunnable {
michael@0 199 public:
michael@0 200 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 201
michael@0 202 NS_IMETHOD Run() {
michael@0 203 nsresult rv;
michael@0 204 char buf[101];
michael@0 205 uint32_t count;
michael@0 206 uint32_t total = 0;
michael@0 207 while (true) {
michael@0 208 //if (gTrace)
michael@0 209 // printf("calling Read\n");
michael@0 210 rv = mIn->Read(buf, 100, &count);
michael@0 211 if (NS_FAILED(rv)) {
michael@0 212 printf("read failed\n");
michael@0 213 break;
michael@0 214 }
michael@0 215 if (count == 0) {
michael@0 216 break;
michael@0 217 }
michael@0 218
michael@0 219 if (gTrace) {
michael@0 220 // For next |printf()| call and possible others elsewhere.
michael@0 221 buf[count] = '\0';
michael@0 222
michael@0 223 printf("read %d bytes: %s\n", count, buf);
michael@0 224 }
michael@0 225
michael@0 226 Received(count);
michael@0 227 total += count;
michael@0 228 }
michael@0 229 printf("read %d bytes\n", total);
michael@0 230 return rv;
michael@0 231 }
michael@0 232
michael@0 233 nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
michael@0 234 mMon = new Monitor("nsShortReader");
michael@0 235 }
michael@0 236
michael@0 237 void Received(uint32_t count) {
michael@0 238 MonitorAutoEnter mon(*mMon);
michael@0 239 mReceived += count;
michael@0 240 mon.Notify();
michael@0 241 }
michael@0 242
michael@0 243 uint32_t WaitForReceipt(const uint32_t aWriteCount) {
michael@0 244 MonitorAutoEnter mon(*mMon);
michael@0 245 uint32_t result = mReceived;
michael@0 246
michael@0 247 while (result < aWriteCount) {
michael@0 248 mon.Wait();
michael@0 249
michael@0 250 NS_ASSERTION(mReceived > result, "failed to receive");
michael@0 251 result = mReceived;
michael@0 252 }
michael@0 253
michael@0 254 mReceived = 0;
michael@0 255 return result;
michael@0 256 }
michael@0 257
michael@0 258 protected:
michael@0 259 nsCOMPtr<nsIInputStream> mIn;
michael@0 260 uint32_t mReceived;
michael@0 261 Monitor* mMon;
michael@0 262 };
michael@0 263
michael@0 264 NS_IMPL_ISUPPORTS(nsShortReader, nsIRunnable)
michael@0 265
michael@0 266 nsresult
michael@0 267 TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
michael@0 268 {
michael@0 269 nsCOMPtr<nsShortReader> receiver = new nsShortReader(in);
michael@0 270 if (!receiver)
michael@0 271 return NS_ERROR_OUT_OF_MEMORY;
michael@0 272
michael@0 273 nsresult rv;
michael@0 274
michael@0 275 nsCOMPtr<nsIThread> thread;
michael@0 276 rv = NS_NewThread(getter_AddRefs(thread), receiver);
michael@0 277 if (NS_FAILED(rv)) return rv;
michael@0 278
michael@0 279 uint32_t total = 0;
michael@0 280 for (uint32_t i = 0; i < ITERATIONS; i++) {
michael@0 281 uint32_t writeCount;
michael@0 282 char* buf = PR_smprintf("%d %s", i, kTestPattern);
michael@0 283 uint32_t len = strlen(buf);
michael@0 284 len = len * rand() / RAND_MAX;
michael@0 285 len = XPCOM_MAX(1, len);
michael@0 286 rv = WriteAll(out, buf, len, &writeCount);
michael@0 287 if (NS_FAILED(rv)) return rv;
michael@0 288 NS_ASSERTION(writeCount == len, "didn't write enough");
michael@0 289 total += writeCount;
michael@0 290
michael@0 291 if (gTrace)
michael@0 292 printf("wrote %d bytes: %s\n", writeCount, buf);
michael@0 293 PR_smprintf_free(buf);
michael@0 294 //printf("calling Flush\n");
michael@0 295 out->Flush();
michael@0 296 //printf("calling WaitForReceipt\n");
michael@0 297
michael@0 298 #ifdef DEBUG
michael@0 299 const uint32_t received =
michael@0 300 #endif
michael@0 301 receiver->WaitForReceipt(writeCount);
michael@0 302 NS_ASSERTION(received == writeCount, "received wrong amount");
michael@0 303 }
michael@0 304 rv = out->Close();
michael@0 305 if (NS_FAILED(rv)) return rv;
michael@0 306
michael@0 307 thread->Shutdown();
michael@0 308
michael@0 309 printf("wrote %d bytes\n", total);
michael@0 310
michael@0 311 return NS_OK;
michael@0 312 }
michael@0 313
michael@0 314 ////////////////////////////////////////////////////////////////////////////////
michael@0 315
michael@0 316 class nsPump : public nsIRunnable
michael@0 317 {
michael@0 318 public:
michael@0 319 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 320
michael@0 321 NS_IMETHOD Run() {
michael@0 322 nsresult rv;
michael@0 323 uint32_t count;
michael@0 324 while (true) {
michael@0 325 rv = mOut->WriteFrom(mIn, ~0U, &count);
michael@0 326 if (NS_FAILED(rv)) {
michael@0 327 printf("Write failed\n");
michael@0 328 break;
michael@0 329 }
michael@0 330 if (count == 0) {
michael@0 331 printf("EOF count = %d\n", mCount);
michael@0 332 break;
michael@0 333 }
michael@0 334
michael@0 335 if (gTrace) {
michael@0 336 printf("Wrote: %d\n", count);
michael@0 337 }
michael@0 338 mCount += count;
michael@0 339 }
michael@0 340 mOut->Close();
michael@0 341 return rv;
michael@0 342 }
michael@0 343
michael@0 344 nsPump(nsIInputStream* in,
michael@0 345 nsIOutputStream* out)
michael@0 346 : mIn(in), mOut(out), mCount(0) {
michael@0 347 }
michael@0 348
michael@0 349 protected:
michael@0 350 nsCOMPtr<nsIInputStream> mIn;
michael@0 351 nsCOMPtr<nsIOutputStream> mOut;
michael@0 352 uint32_t mCount;
michael@0 353 };
michael@0 354
michael@0 355 NS_IMPL_ISUPPORTS(nsPump, nsIRunnable)
michael@0 356
michael@0 357 nsresult
michael@0 358 TestChainedPipes()
michael@0 359 {
michael@0 360 nsresult rv;
michael@0 361 printf("TestChainedPipes\n");
michael@0 362
michael@0 363 nsCOMPtr<nsIInputStream> in1;
michael@0 364 nsCOMPtr<nsIOutputStream> out1;
michael@0 365 rv = TP_NewPipe(getter_AddRefs(in1), getter_AddRefs(out1), 20, 1999);
michael@0 366 if (NS_FAILED(rv)) return rv;
michael@0 367
michael@0 368 nsCOMPtr<nsIInputStream> in2;
michael@0 369 nsCOMPtr<nsIOutputStream> out2;
michael@0 370 rv = TP_NewPipe(getter_AddRefs(in2), getter_AddRefs(out2), 200, 401);
michael@0 371 if (NS_FAILED(rv)) return rv;
michael@0 372
michael@0 373 nsCOMPtr<nsPump> pump = new nsPump(in1, out2);
michael@0 374 if (pump == nullptr) return NS_ERROR_OUT_OF_MEMORY;
michael@0 375
michael@0 376 nsCOMPtr<nsIThread> thread;
michael@0 377 rv = NS_NewThread(getter_AddRefs(thread), pump);
michael@0 378 if (NS_FAILED(rv)) return rv;
michael@0 379
michael@0 380 nsCOMPtr<nsReceiver> receiver = new nsReceiver(in2);
michael@0 381 if (receiver == nullptr) return NS_ERROR_OUT_OF_MEMORY;
michael@0 382
michael@0 383 nsCOMPtr<nsIThread> receiverThread;
michael@0 384 rv = NS_NewThread(getter_AddRefs(receiverThread), receiver);
michael@0 385 if (NS_FAILED(rv)) return rv;
michael@0 386
michael@0 387 uint32_t total = 0;
michael@0 388 for (uint32_t i = 0; i < ITERATIONS; i++) {
michael@0 389 uint32_t writeCount;
michael@0 390 char* buf = PR_smprintf("%d %s", i, kTestPattern);
michael@0 391 uint32_t len = strlen(buf);
michael@0 392 len = len * rand() / RAND_MAX;
michael@0 393 len = XPCOM_MAX(1, len);
michael@0 394 rv = WriteAll(out1, buf, len, &writeCount);
michael@0 395 if (NS_FAILED(rv)) return rv;
michael@0 396 NS_ASSERTION(writeCount == len, "didn't write enough");
michael@0 397 total += writeCount;
michael@0 398
michael@0 399 if (gTrace)
michael@0 400 printf("wrote %d bytes: %s\n", writeCount, buf);
michael@0 401
michael@0 402 PR_smprintf_free(buf);
michael@0 403 }
michael@0 404 printf("wrote total of %d bytes\n", total);
michael@0 405 rv = out1->Close();
michael@0 406 if (NS_FAILED(rv)) return rv;
michael@0 407
michael@0 408 thread->Shutdown();
michael@0 409 receiverThread->Shutdown();
michael@0 410
michael@0 411 return NS_OK;
michael@0 412 }
michael@0 413
michael@0 414 ////////////////////////////////////////////////////////////////////////////////
michael@0 415
michael@0 416 void
michael@0 417 RunTests(uint32_t segSize, uint32_t segCount)
michael@0 418 {
michael@0 419 nsresult rv;
michael@0 420 nsCOMPtr<nsIInputStream> in;
michael@0 421 nsCOMPtr<nsIOutputStream> out;
michael@0 422 uint32_t bufSize = segSize * segCount;
michael@0 423 printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize);
michael@0 424
michael@0 425 printf("Testing long writes...\n");
michael@0 426 rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
michael@0 427 NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed");
michael@0 428 rv = TestPipe(in, out);
michael@0 429 NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
michael@0 430
michael@0 431 printf("Testing short writes...\n");
michael@0 432 rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
michael@0 433 NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed");
michael@0 434 rv = TestShortWrites(in, out);
michael@0 435 NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
michael@0 436 }
michael@0 437
michael@0 438 ////////////////////////////////////////////////////////////////////////////////
michael@0 439
michael@0 440 #if 0
michael@0 441 extern void
michael@0 442 TestSegmentedBuffer();
michael@0 443 #endif
michael@0 444
michael@0 445 int
michael@0 446 main(int argc, char* argv[])
michael@0 447 {
michael@0 448 nsresult rv;
michael@0 449
michael@0 450 nsCOMPtr<nsIServiceManager> servMgr;
michael@0 451 rv = NS_InitXPCOM2(getter_AddRefs(servMgr), nullptr, nullptr);
michael@0 452 if (NS_FAILED(rv)) return rv;
michael@0 453
michael@0 454 if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0)
michael@0 455 gTrace = true;
michael@0 456
michael@0 457 rv = TestChainedPipes();
michael@0 458 NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
michael@0 459 RunTests(16, 1);
michael@0 460 RunTests(4096, 16);
michael@0 461
michael@0 462 servMgr = 0;
michael@0 463 rv = NS_ShutdownXPCOM(nullptr);
michael@0 464 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
michael@0 465
michael@0 466 return 0;
michael@0 467 }
michael@0 468
michael@0 469 ////////////////////////////////////////////////////////////////////////////////

mercurial