michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIEventQueueService.h" michael@0: #include "nsIOutputStream.h" michael@0: #include "nsIStreamListener.h" michael@0: #include "nsITransport.h" michael@0: #include "nsIInputStream.h" michael@0: #include "nsIOutputStream.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "plstr.h" michael@0: #include "prprf.h" michael@0: #include michael@0: michael@0: #ifndef USE_CREATE_INSTANCE michael@0: #include "nsICacheService.h" michael@0: #include "nsICacheSession.h" michael@0: #include "nsICacheEntryDescriptor.h" michael@0: #include "nsNetCID.h" michael@0: static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); michael@0: static nsICacheSession *session = nullptr; michael@0: static nsICacheEntryDescriptor *desc = nullptr; michael@0: #endif michael@0: michael@0: /** michael@0: * This test program exercises the memory cache's nsITransport implementation. michael@0: * michael@0: * This test program loads a file into the memory cache (using OpenOutputStream), michael@0: * and then reads the file back out (using AsyncRead). The data read from the michael@0: * memory cache is written to a new file (with .out added as a suffix to the file michael@0: * name). michael@0: */ michael@0: michael@0: static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); michael@0: static nsIEventQueue *gEventQ = nullptr; michael@0: michael@0: class TestListener : public nsIStreamListener michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSISTREAMLISTENER michael@0: NS_DECL_NSIREQUESTOBSERVER michael@0: michael@0: TestListener(char *); michael@0: virtual ~TestListener(); michael@0: michael@0: private: michael@0: char *mFilename; michael@0: FILE *mFile; michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(TestListener, michael@0: nsIStreamListener, michael@0: nsIRequestObserver) michael@0: michael@0: TestListener::TestListener(char *filename) michael@0: : mFilename(filename) michael@0: , mFile(nullptr) michael@0: { michael@0: } michael@0: michael@0: TestListener::~TestListener() michael@0: { michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TestListener::OnStartRequest(nsIRequest *req, nsISupports *ctx) michael@0: { michael@0: printf("OnStartRequest\n"); michael@0: michael@0: mFile = fopen(mFilename, "w"); michael@0: if (!mFile) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TestListener::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) michael@0: { michael@0: printf("OnStopRequest: status=%x\n", status); michael@0: michael@0: if (mFile) michael@0: fclose(mFile); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TestListener::OnDataAvailable(nsIRequest *req, nsISupports *ctx, michael@0: nsIInputStream *is, michael@0: uint64_t offset, uint32_t count) michael@0: { michael@0: printf("OnDataAvailable: offset=%llu count=%u\n", offset, count); michael@0: michael@0: if (!mFile) return NS_ERROR_FAILURE; michael@0: michael@0: char buf[128]; michael@0: nsresult rv; michael@0: uint32_t nread = 0; michael@0: michael@0: while (count) { michael@0: uint32_t amount = std::min(count, sizeof(buf)); michael@0: michael@0: rv = is->Read(buf, amount, &nread); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: fwrite(buf, nread, 1, mFile); michael@0: count -= nread; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult TestMCTransport(const char *filename) michael@0: { michael@0: nsresult rv = NS_OK; michael@0: nsCOMPtr transport; michael@0: michael@0: #ifdef USE_CREATE_INSTANCE michael@0: transport = do_CreateInstance( michael@0: "@mozilla.org/network/memory-cache-transport;1", &rv); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: #else michael@0: nsCOMPtr serv(do_GetService(kCacheServiceCID, &rv)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = serv->CreateSession("TestMCTransport", michael@0: nsICache::STORE_IN_MEMORY, true, michael@0: &session); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = session->OpenCacheEntry(nsDependentCString(filename), michael@0: nsICache::ACCESS_READ_WRITE, michael@0: nsICache::BLOCKING, michael@0: &desc); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = desc->MarkValid(); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = desc->GetTransport(getter_AddRefs(transport)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: #endif michael@0: michael@0: nsCOMPtr os; michael@0: rv = transport->OpenOutputStream(0, (uint32_t) -1, 0, getter_AddRefs(os)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: char *out = PR_smprintf("%s.out", filename); michael@0: nsCOMPtr listener = new TestListener(out); michael@0: if (!listener) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: nsCOMPtr req; michael@0: rv = transport->AsyncRead(listener, nullptr, 0, (uint32_t) -1, 0, getter_AddRefs(req)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: FILE *file = fopen(filename, "r"); michael@0: if (!file) michael@0: return NS_ERROR_FILE_NOT_FOUND; michael@0: michael@0: char buf[256]; michael@0: uint32_t count, total=0; michael@0: michael@0: while ((count = fread(buf, 1, sizeof(buf), file)) > 0) { michael@0: printf("writing %u bytes\n", count); michael@0: total += count; michael@0: rv = os->Write(buf, count, &count); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: // process an event michael@0: PLEvent *event = nullptr; michael@0: gEventQ->GetEvent(&event); michael@0: if (event) gEventQ->HandleEvent(event); michael@0: } michael@0: michael@0: printf("wrote %u bytes\n", total); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: nsresult rv; michael@0: michael@0: if (argc < 2) { michael@0: printf("usage: %s filename\n", argv[0]); michael@0: return -1; michael@0: } michael@0: michael@0: nsCOMPtr eqs = michael@0: do_GetService(kEventQueueServiceCID, &rv); michael@0: if (NS_FAILED(rv)) { michael@0: printf("failed to create event queue service: rv=%x\n", rv); michael@0: return -1; michael@0: } michael@0: michael@0: rv = eqs->CreateMonitoredThreadEventQueue(); michael@0: if (NS_FAILED(rv)) { michael@0: printf("failed to create monitored event queue: rv=%x\n", rv); michael@0: return -1; michael@0: } michael@0: michael@0: rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); michael@0: if (NS_FAILED(rv)) { michael@0: printf("failed to get thread event queue: %x\n", rv); michael@0: return -1; michael@0: } michael@0: michael@0: rv = TestMCTransport(argv[1]); michael@0: printf("TestMCTransport returned %x\n", rv); michael@0: michael@0: gEventQ->ProcessPendingEvents(); michael@0: michael@0: #ifndef USE_CREATE_INSTANCE michael@0: NS_IF_RELEASE(desc); michael@0: NS_IF_RELEASE(session); michael@0: #endif michael@0: return 0; michael@0: }