summaryrefslogtreecommitdiffstats
path: root/netwerk/test/TestStreamTransport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/TestStreamTransport.cpp')
-rw-r--r--netwerk/test/TestStreamTransport.cpp319
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;
+}