From 5928f4b1813bdfc2f6e62097d7a3e82b0cbde4c8 Mon Sep 17 00:00:00 2001 From: Serge Gautherie Date: Thu, 25 Sep 2008 20:06:13 +0200 Subject: [PATCH] Bug 453137 - 'TestPipes' |TestChainedPipes()| leaks its streams; Av2; r=benjamin --- xpcom/tests/Makefile.in | 2 +- xpcom/tests/TestPipes.cpp | 205 ++++++++++++++++++++++---------------- 2 files changed, 120 insertions(+), 87 deletions(-) diff --git a/xpcom/tests/Makefile.in b/xpcom/tests/Makefile.in index b869b2fb2a5..cc6d5bc00ab 100644 --- a/xpcom/tests/Makefile.in +++ b/xpcom/tests/Makefile.in @@ -77,6 +77,7 @@ CPPSRCS = \ TestVersionComparator.cpp \ TestTextFormatter.cpp \ TestPipe.cpp \ + TestPipes.cpp \ TestRacingServiceManager.cpp \ TestRegistrationOrder.cpp \ TestProxies.cpp \ @@ -94,7 +95,6 @@ CPPSRCS += \ TestCRT.cpp \ TestEncoding.cpp \ TestPermanentAtoms.cpp \ - TestPipes.cpp \ TestThreads.cpp \ TestThreadPool.cpp \ TestXPIDLString.cpp \ diff --git a/xpcom/tests/TestPipes.cpp b/xpcom/tests/TestPipes.cpp index 9df4f7bb862..941ab8ff882 100644 --- a/xpcom/tests/TestPipes.cpp +++ b/xpcom/tests/TestPipes.cpp @@ -36,21 +36,83 @@ * * ***** END LICENSE BLOCK ***** */ +#include "TestHarness.h" + #include "nsIThread.h" #include "nsIRunnable.h" -#include "nsIInputStream.h" -#include "nsIOutputStream.h" -#include "nsIServiceManager.h" #include "nsThreadUtils.h" #include "prprf.h" #include "prinrval.h" -#include "plstr.h" #include "nsCRT.h" -#include "nsCOMPtr.h" -#include #include "nsIPipe.h" // new implementation #include "nsAutoLock.h" -#include // for rand + + +/** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */ +nsresult TP_NewPipe2(nsIAsyncInputStream** input, + nsIAsyncOutputStream** output, + PRBool nonBlockingInput, + PRBool nonBlockingOutput, + PRUint32 segmentSize, + PRUint32 segmentCount, + nsIMemory* segmentAlloc) +{ + nsCOMPtr pipe = do_CreateInstance("@mozilla.org/pipe;1"); + if (!pipe) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = pipe->Init(nonBlockingInput, + nonBlockingOutput, + segmentSize, + segmentCount, + segmentAlloc); + + if (NS_FAILED(rv)) + return rv; + + pipe->GetInputStream(input); + pipe->GetOutputStream(output); + return NS_OK; +} + +/** NS_NewPipe reimplemented, because it's not exported by XPCOM */ +#define TP_DEFAULT_SEGMENT_SIZE 4096 +nsresult TP_NewPipe(nsIInputStream **pipeIn, + nsIOutputStream **pipeOut, + PRUint32 segmentSize = 0, + PRUint32 maxSize = 0, + PRBool nonBlockingInput = PR_FALSE, + PRBool nonBlockingOutput = PR_FALSE, + nsIMemory *segmentAlloc = nsnull); +nsresult TP_NewPipe(nsIInputStream **pipeIn, + nsIOutputStream **pipeOut, + PRUint32 segmentSize, + PRUint32 maxSize, + PRBool nonBlockingInput, + PRBool nonBlockingOutput, + nsIMemory *segmentAlloc) +{ + if (segmentSize == 0) + segmentSize = TP_DEFAULT_SEGMENT_SIZE; + + // Handle maxSize of PR_UINT32_MAX as a special case + PRUint32 segmentCount; + if (maxSize == PR_UINT32_MAX) + segmentCount = PR_UINT32_MAX; + else + segmentCount = maxSize / segmentSize; + + nsIAsyncInputStream *in; + nsIAsyncOutputStream *out; + nsresult rv = TP_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput, + segmentSize, segmentCount, segmentAlloc); + if (NS_FAILED(rv)) return rv; + + *pipeIn = in; + *pipeOut = out; + return NS_OK; +} + #define KEY 0xa7 #define ITERATIONS 33333 @@ -107,18 +169,12 @@ public: } nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) { - NS_ADDREF(in); } PRUint32 GetBytesRead() { return mCount; } -private: - ~nsReceiver() { - NS_RELEASE(mIn); - } - protected: - nsIInputStream* mIn; + nsCOMPtr mIn; PRUint32 mCount; }; @@ -127,13 +183,14 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver, nsIRunnable) nsresult TestPipe(nsIInputStream* in, nsIOutputStream* out) { - nsresult rv; - nsIThread* thread; - nsReceiver* receiver = new nsReceiver(in); - if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(receiver); + nsCOMPtr receiver = new nsReceiver(in); + if (!receiver) + return NS_ERROR_OUT_OF_MEMORY; - rv = NS_NewThread(&thread, receiver); + nsresult rv; + + nsCOMPtr thread; + rv = NS_NewThread(getter_AddRefs(thread), receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -165,9 +222,6 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out) PR_IntervalToMilliseconds(end - start)); NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything"); - NS_RELEASE(thread); - NS_RELEASE(receiver); - return NS_OK; } @@ -209,7 +263,6 @@ public: } nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) { - NS_ADDREF(in); } void Received(PRUint32 count) { @@ -233,13 +286,8 @@ public: return result; } -private: - ~nsShortReader() { - NS_RELEASE(mIn); - } - protected: - nsIInputStream* mIn; + nsCOMPtr mIn; PRUint32 mReceived; }; @@ -248,13 +296,14 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader, nsIRunnable) nsresult TestShortWrites(nsIInputStream* in, nsIOutputStream* out) { - nsresult rv; - nsIThread* thread; - nsShortReader* receiver = new nsShortReader(in); - if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(receiver); + nsCOMPtr receiver = new nsShortReader(in); + if (!receiver) + return NS_ERROR_OUT_OF_MEMORY; - rv = NS_NewThread(&thread, receiver); + nsresult rv; + + nsCOMPtr thread; + rv = NS_NewThread(getter_AddRefs(thread), receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -282,10 +331,8 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out) if (NS_FAILED(rv)) return rv; thread->Shutdown(); - printf("wrote %d bytes\n", total); - NS_RELEASE(thread); - NS_RELEASE(receiver); + printf("wrote %d bytes\n", total); return NS_OK; } @@ -325,9 +372,6 @@ public: : mIn(in), mOut(out), mCount(0) { } -private: - ~nsPump() {} - protected: nsCOMPtr mIn; nsCOMPtr mOut; @@ -343,30 +387,28 @@ TestChainedPipes() nsresult rv; printf("TestChainedPipes\n"); - nsIInputStream* in1; - nsIOutputStream* out1; - rv = NS_NewPipe(&in1, &out1, 20, 1999); + nsCOMPtr in1; + nsCOMPtr out1; + rv = TP_NewPipe(getter_AddRefs(in1), getter_AddRefs(out1), 20, 1999); if (NS_FAILED(rv)) return rv; - nsIInputStream* in2; - nsIOutputStream* out2; - rv = NS_NewPipe(&in2, &out2, 200, 401); + nsCOMPtr in2; + nsCOMPtr out2; + rv = TP_NewPipe(getter_AddRefs(in2), getter_AddRefs(out2), 200, 401); if (NS_FAILED(rv)) return rv; - nsIThread* thread; - nsPump* pump = new nsPump(in1, out2); + nsCOMPtr pump = new nsPump(in1, out2); if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(pump); - rv = NS_NewThread(&thread, pump); + nsCOMPtr thread; + rv = NS_NewThread(getter_AddRefs(thread), pump); if (NS_FAILED(rv)) return rv; - nsIThread* receiverThread; - nsReceiver* receiver = new nsReceiver(in2); + nsCOMPtr receiver = new nsReceiver(in2); if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(receiver); - rv = NS_NewThread(&receiverThread, receiver); + nsCOMPtr receiverThread; + rv = NS_NewThread(getter_AddRefs(receiverThread), receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -393,10 +435,6 @@ TestChainedPipes() thread->Shutdown(); receiverThread->Shutdown(); - NS_RELEASE(thread); - NS_RELEASE(pump); - NS_RELEASE(receiverThread); - NS_RELEASE(receiver); return NS_OK; } @@ -406,27 +444,21 @@ void RunTests(PRUint32 segSize, PRUint32 segCount) { nsresult rv; - nsIInputStream* in; - nsIOutputStream* out; - PRUint32 bufSize; - - bufSize = segSize * segCount; + nsCOMPtr in; + nsCOMPtr out; + PRUint32 bufSize = segSize * segCount; printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize); printf("Testing long writes...\n"); - rv = NS_NewPipe(&in, &out, segSize, bufSize); - NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed"); + rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize); + NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed"); rv = TestPipe(in, out); - NS_RELEASE(in); - NS_RELEASE(out); NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed"); printf("Testing short writes...\n"); - rv = NS_NewPipe(&in, &out, segSize, bufSize); - NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed"); + rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize); + NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed"); rv = TestShortWrites(in, out); - NS_RELEASE(in); - NS_RELEASE(out); NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed"); } @@ -439,10 +471,10 @@ TestSearch(const char* delim, PRUint32 segSize) // need at least 2 segments to test boundary conditions: PRUint32 bufDataSize = segSize * 2; PRUint32 bufSize = segSize * 2; - nsIInputStream* in; - nsIOutputStream* out; - rv = NS_NewPipe(&in, &out, segSize, bufSize); - NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed"); + nsCOMPtr in; + nsCOMPtr out; + rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize); + NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed"); out->SetNonBlocking(PR_TRUE); PRUint32 i, j, amt; @@ -476,8 +508,6 @@ TestSearch(const char* delim, PRUint32 segSize) printf("Buffer: %s\nDelim: %s %s offset: %d\n", bufferContents, delim, (found ? "found" : "not found"), offset); } - NS_RELEASE(in); - NS_RELEASE(out); } #endif //////////////////////////////////////////////////////////////////////////////// @@ -491,28 +521,29 @@ int main(int argc, char* argv[]) { nsresult rv; - nsIServiceManager* servMgr; - rv = NS_InitXPCOM2(&servMgr, NULL, NULL); + nsCOMPtr servMgr; + rv = NS_InitXPCOM2(getter_AddRefs(servMgr), NULL, NULL); if (NS_FAILED(rv)) return rv; if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0) gTrace = PR_TRUE; #ifdef DEBUG + printf("Testing segmented buffer...\n"); TestSegmentedBuffer(); #endif #if 0 // obsolete old implementation - rv = NS_NewPipe(&in, &out, 4096 * 4); + nsCOMPtr in; + nsCOMPtr out; + rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), 4096 * 4); if (NS_FAILED(rv)) { - printf("NewPipe failed\n"); + printf("TP_NewPipe failed\n"); return -1; } rv = TestPipe(in, out); - NS_RELEASE(in); - NS_RELEASE(out); if (NS_FAILED(rv)) { printf("TestPipe failed\n"); return -1; @@ -528,9 +559,11 @@ main(int argc, char* argv[]) NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed"); RunTests(16, 1); RunTests(4096, 16); - NS_RELEASE(servMgr); + + servMgr = 0; rv = NS_ShutdownXPCOM( NULL ); NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); + return 0; }