diff -r 000000000000 -r 6474c204b198 netwerk/test/TestMCTransport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netwerk/test/TestMCTransport.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 + +#include "nsIServiceManager.h" +#include "nsIEventQueueService.h" +#include "nsIOutputStream.h" +#include "nsIStreamListener.h" +#include "nsITransport.h" +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "nsCOMPtr.h" +#include "plstr.h" +#include "prprf.h" +#include + +#ifndef USE_CREATE_INSTANCE +#include "nsICacheService.h" +#include "nsICacheSession.h" +#include "nsICacheEntryDescriptor.h" +#include "nsNetCID.h" +static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); +static nsICacheSession *session = nullptr; +static nsICacheEntryDescriptor *desc = nullptr; +#endif + +/** + * This test program exercises the memory cache's nsITransport implementation. + * + * This test program loads a file into the memory cache (using OpenOutputStream), + * and then reads the file back out (using AsyncRead). The data read from the + * memory cache is written to a new file (with .out added as a suffix to the file + * name). + */ + +static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static nsIEventQueue *gEventQ = nullptr; + +class TestListener : public nsIStreamListener +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIREQUESTOBSERVER + + TestListener(char *); + virtual ~TestListener(); + +private: + char *mFilename; + FILE *mFile; +}; + +NS_IMPL_ISUPPORTS(TestListener, + nsIStreamListener, + nsIRequestObserver) + +TestListener::TestListener(char *filename) + : mFilename(filename) + , mFile(nullptr) +{ +} + +TestListener::~TestListener() +{ +} + +NS_IMETHODIMP +TestListener::OnStartRequest(nsIRequest *req, nsISupports *ctx) +{ + printf("OnStartRequest\n"); + + mFile = fopen(mFilename, "w"); + if (!mFile) + return NS_ERROR_FAILURE; + + return NS_OK; +} + +NS_IMETHODIMP +TestListener::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) +{ + printf("OnStopRequest: status=%x\n", status); + + if (mFile) + fclose(mFile); + + return NS_OK; +} + +NS_IMETHODIMP +TestListener::OnDataAvailable(nsIRequest *req, nsISupports *ctx, + nsIInputStream *is, + uint64_t offset, uint32_t count) +{ + printf("OnDataAvailable: offset=%llu count=%u\n", offset, count); + + if (!mFile) return NS_ERROR_FAILURE; + + char buf[128]; + nsresult rv; + uint32_t nread = 0; + + while (count) { + uint32_t amount = std::min(count, sizeof(buf)); + + rv = is->Read(buf, amount, &nread); + if (NS_FAILED(rv)) return rv; + + fwrite(buf, nread, 1, mFile); + count -= nread; + } + return NS_OK; +} + +nsresult TestMCTransport(const char *filename) +{ + nsresult rv = NS_OK; + nsCOMPtr transport; + +#ifdef USE_CREATE_INSTANCE + transport = do_CreateInstance( + "@mozilla.org/network/memory-cache-transport;1", &rv); + if (NS_FAILED(rv)) + return rv; +#else + nsCOMPtr serv(do_GetService(kCacheServiceCID, &rv)); + if (NS_FAILED(rv)) return rv; + + rv = serv->CreateSession("TestMCTransport", + nsICache::STORE_IN_MEMORY, true, + &session); + if (NS_FAILED(rv)) return rv; + + rv = session->OpenCacheEntry(nsDependentCString(filename), + nsICache::ACCESS_READ_WRITE, + nsICache::BLOCKING, + &desc); + if (NS_FAILED(rv)) return rv; + + rv = desc->MarkValid(); + if (NS_FAILED(rv)) return rv; + + rv = desc->GetTransport(getter_AddRefs(transport)); + if (NS_FAILED(rv)) return rv; +#endif + + nsCOMPtr os; + rv = transport->OpenOutputStream(0, (uint32_t) -1, 0, getter_AddRefs(os)); + if (NS_FAILED(rv)) return rv; + + char *out = PR_smprintf("%s.out", filename); + nsCOMPtr listener = new TestListener(out); + if (!listener) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr req; + rv = transport->AsyncRead(listener, nullptr, 0, (uint32_t) -1, 0, getter_AddRefs(req)); + if (NS_FAILED(rv)) return rv; + + FILE *file = fopen(filename, "r"); + if (!file) + return NS_ERROR_FILE_NOT_FOUND; + + char buf[256]; + uint32_t count, total=0; + + while ((count = fread(buf, 1, sizeof(buf), file)) > 0) { + printf("writing %u bytes\n", count); + total += count; + rv = os->Write(buf, count, &count); + if (NS_FAILED(rv)) return rv; + + // process an event + PLEvent *event = nullptr; + gEventQ->GetEvent(&event); + if (event) gEventQ->HandleEvent(event); + } + + printf("wrote %u bytes\n", total); + + return rv; +} + +int main(int argc, char **argv) +{ + nsresult rv; + + if (argc < 2) { + printf("usage: %s filename\n", argv[0]); + return -1; + } + + nsCOMPtr eqs = + do_GetService(kEventQueueServiceCID, &rv); + if (NS_FAILED(rv)) { + printf("failed to create event queue service: rv=%x\n", rv); + return -1; + } + + rv = eqs->CreateMonitoredThreadEventQueue(); + if (NS_FAILED(rv)) { + printf("failed to create monitored event queue: rv=%x\n", rv); + return -1; + } + + rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); + if (NS_FAILED(rv)) { + printf("failed to get thread event queue: %x\n", rv); + return -1; + } + + rv = TestMCTransport(argv[1]); + printf("TestMCTransport returned %x\n", rv); + + gEventQ->ProcessPendingEvents(); + +#ifndef USE_CREATE_INSTANCE + NS_IF_RELEASE(desc); + NS_IF_RELEASE(session); +#endif + return 0; +}