diff options
Diffstat (limited to 'netwerk/test/TestStreamTransport.cpp')
-rw-r--r-- | netwerk/test/TestStreamTransport.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/netwerk/test/TestStreamTransport.cpp b/netwerk/test/TestStreamTransport.cpp new file mode 100644 index 000000000..840c9578d --- /dev/null +++ b/netwerk/test/TestStreamTransport.cpp @@ -0,0 +1,319 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TestCommon.h" +#include "nsIComponentRegistrar.h" +#include "nsIStreamTransportService.h" +#include "nsIAsyncInputStream.h" +#include "nsIProgressEventSink.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIRequest.h" +#include "nsIServiceManager.h" +#include "nsIComponentManager.h" +#include "nsCOMPtr.h" +#include "nsMemory.h" +#include "nsStringAPI.h" +#include "nsIFileStreams.h" +#include "nsIStreamListener.h" +#include "nsIFile.h" +#include "nsNetUtil.h" +#include "nsAutoLock.h" +#include "mozilla/Logging.h" +#include "prenv.h" + +//////////////////////////////////////////////////////////////////////////////// + +// +// set NSPR_LOG_MODULES=Test:5 +// +static PRLogModuleInfo *gTestLog = nullptr; +#define LOG(args) MOZ_LOG(gTestLog, mozilla::LogLevel::Debug, args) + +//////////////////////////////////////////////////////////////////////////////// + +static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID); + +//////////////////////////////////////////////////////////////////////////////// + +#define CHUNK_SIZE 500 + +class MyCopier : public nsIInputStreamCallback + , public nsIOutputStreamCallback +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + + MyCopier() + : mLock(nullptr) + , mInputCondition(NS_OK) + { + } + + virtual ~MyCopier() + { + if (mLock) + nsAutoLock::DestroyLock(mLock); + if (mInput) + mInput->Close(); + if (mOutput) + mOutput->Close(); + } + + // called on any thread + NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *inStr) + { + LOG(("OnInputStreamReady\n")); + nsAutoLock lock(mLock); + NS_ASSERTION(inStr == mInput, "unexpected stream"); + Process_Locked(); + return NS_OK; + } + + // called on any thread + NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *outStr) + { + LOG(("OnOutputStreamReady\n")); + nsAutoLock lock(mLock); + NS_ASSERTION(outStr == mOutput, "unexpected stream"); + Process_Locked(); + return NS_OK; + } + + void Close_Locked() + { + LOG(("Close_Locked\n")); + + mOutput->Close(); + mOutput = 0; + mInput->Close(); + mInput = 0; + + // post done copying event + QuitPumpingEvents(); + } + + void Process_Locked() + { + while (1) { + mInputCondition = NS_OK; // reset + + uint32_t n; + nsresult rv = mOutput->WriteSegments(FillOutputBuffer, this, CHUNK_SIZE, &n); + if (NS_FAILED(rv) || (n == 0)) { + if (rv == NS_BASE_STREAM_WOULD_BLOCK) + mOutput->AsyncWait(this, 0, 0, nullptr); + else if (mInputCondition == NS_BASE_STREAM_WOULD_BLOCK) + mInput->AsyncWait(this, 0, 0, nullptr); + else + Close_Locked(); + break; + } + } + } + + nsresult AsyncCopy(nsITransport *srcTrans, nsITransport *destTrans) + { + mLock = nsAutoLock::NewLock("MyCopier::mLock"); + if (!mLock) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv; + + nsCOMPtr<nsIInputStream> inStr; + rv = srcTrans->OpenInputStream(0, 0, 0, getter_AddRefs(inStr)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIOutputStream> outStr; + rv = destTrans->OpenOutputStream(0, 0, 0, getter_AddRefs(outStr)); + if (NS_FAILED(rv)) return rv; + + mInput = do_QueryInterface(inStr); + mOutput = do_QueryInterface(outStr); + + return mInput->AsyncWait(this, 0, 0, nullptr); + } + + static nsresult FillOutputBuffer(nsIOutputStream *outStr, + void *closure, + char *buffer, + uint32_t offset, + uint32_t count, + uint32_t *countRead) + { + MyCopier *self = (MyCopier *) closure; + + nsresult rv = self->mInput->Read(buffer, count, countRead); + if (NS_FAILED(rv)) + self->mInputCondition = rv; + else if (*countRead == 0) + self->mInputCondition = NS_BASE_STREAM_CLOSED; + + return self->mInputCondition; + } + +protected: + PRLock *mLock; + nsCOMPtr<nsIAsyncInputStream> mInput; + nsCOMPtr<nsIAsyncOutputStream> mOutput; + nsresult mInputCondition; +}; + +NS_IMPL_ISUPPORTS(MyCopier, + nsIInputStreamCallback, + nsIOutputStreamCallback) + +//////////////////////////////////////////////////////////////////////////////// + +/** + * asynchronously copy file. + */ +static nsresult +RunTest(nsIFile *srcFile, nsIFile *destFile) +{ + nsresult rv; + + LOG(("RunTest\n")); + + nsCOMPtr<nsIStreamTransportService> sts = + do_GetService(kStreamTransportServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIInputStream> srcStr; + rv = NS_NewLocalFileInputStream(getter_AddRefs(srcStr), srcFile); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIOutputStream> destStr; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(destStr), destFile); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsITransport> srcTransport; + rv = sts->CreateInputTransport(srcStr, int64_t(-1), int64_t(-1), true, + getter_AddRefs(srcTransport)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsITransport> destTransport; + rv = sts->CreateOutputTransport(destStr, int64_t(-1), int64_t(-1), true, + getter_AddRefs(destTransport)); + if (NS_FAILED(rv)) return rv; + + MyCopier *copier = new MyCopier(); + if (copier == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(copier); + + rv = copier->AsyncCopy(srcTransport, destTransport); + if (NS_FAILED(rv)) return rv; + + PumpEvents(); + + NS_RELEASE(copier); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +static nsresult +RunBlockingTest(nsIFile *srcFile, nsIFile *destFile) +{ + nsresult rv; + + LOG(("RunBlockingTest\n")); + + nsCOMPtr<nsIStreamTransportService> sts = + do_GetService(kStreamTransportServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIInputStream> srcIn; + rv = NS_NewLocalFileInputStream(getter_AddRefs(srcIn), srcFile); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIOutputStream> fileOut; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut), destFile); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsITransport> destTransport; + rv = sts->CreateOutputTransport(fileOut, int64_t(-1), int64_t(-1), + true, getter_AddRefs(destTransport)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIOutputStream> destOut; + rv = destTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 100, 10, getter_AddRefs(destOut)); + if (NS_FAILED(rv)) return rv; + + char buf[120]; + uint32_t n; + for (;;) { + rv = srcIn->Read(buf, sizeof(buf), &n); + if (NS_FAILED(rv) || (n == 0)) return rv; + + rv = destOut->Write(buf, n, &n); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +int +main(int argc, char* argv[]) +{ + if (test_common_init(&argc, &argv) != 0) + return -1; + + nsresult rv; + + if (argc < 2) { + printf("usage: %s <file-to-read>\n", argv[0]); + return -1; + } + char* fileName = argv[1]; + { + nsCOMPtr<nsIServiceManager> servMan; + NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); + NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); + if (registrar) + registrar->AutoRegister(nullptr); + + gTestLog = PR_NewLogModule("Test"); + + nsCOMPtr<nsIFile> srcFile; + rv = NS_NewNativeLocalFile(nsDependentCString(fileName), false, getter_AddRefs(srcFile)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIFile> destFile; + rv = srcFile->Clone(getter_AddRefs(destFile)); + if (NS_FAILED(rv)) return rv; + + nsAutoCString leafName; + rv = destFile->GetNativeLeafName(leafName); + if (NS_FAILED(rv)) return rv; + + nsAutoCString newName(leafName); + newName.AppendLiteral(".1"); + rv = destFile->SetNativeLeafName(newName); + if (NS_FAILED(rv)) return rv; + + rv = RunTest(srcFile, destFile); + NS_ASSERTION(NS_SUCCEEDED(rv), "RunTest failed"); + + newName = leafName; + newName.AppendLiteral(".2"); + rv = destFile->SetNativeLeafName(newName); + if (NS_FAILED(rv)) return rv; + + rv = RunBlockingTest(srcFile, destFile); + NS_ASSERTION(NS_SUCCEEDED(rv), "RunBlockingTest failed"); + + // give background threads a chance to finish whatever work they may + // be doing. + PR_Sleep(PR_SecondsToInterval(1)); + } // this scopes the nsCOMPtrs + // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM + rv = NS_ShutdownXPCOM(nullptr); + NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); + return NS_OK; +} |