summaryrefslogtreecommitdiffstats
path: root/netwerk/streamconv/test
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/streamconv/test')
-rw-r--r--netwerk/streamconv/test/Converters.cpp140
-rw-r--r--netwerk/streamconv/test/Converters.h52
-rw-r--r--netwerk/streamconv/test/TestStreamConv.cpp261
-rw-r--r--netwerk/streamconv/test/moz.build22
4 files changed, 475 insertions, 0 deletions
diff --git a/netwerk/streamconv/test/Converters.cpp b/netwerk/streamconv/test/Converters.cpp
new file mode 100644
index 000000000..61b114d77
--- /dev/null
+++ b/netwerk/streamconv/test/Converters.cpp
@@ -0,0 +1,140 @@
+#include "Converters.h"
+#include "nsIStringStream.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+
+#include <stdio.h>
+
+//////////////////////////////////////////////////
+// TestConverter
+//////////////////////////////////////////////////
+
+#define NS_TESTCONVERTER_CID \
+{ /* B8A067B0-4450-11d3-A16E-0050041CAF44 */ \
+ 0xb8a067b0, \
+ 0x4450, \
+ 0x11d3, \
+ {0xa1, 0x6e, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+NS_DEFINE_CID(kTestConverterCID, NS_TESTCONVERTER_CID);
+
+NS_IMPL_ISUPPORTS(TestConverter,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+TestConverter::TestConverter() {
+}
+
+// Convert aFromStream (of type aFromType), to _retval (nsIInputStream of type aToType).
+// This Convert method simply converts the stream byte-by-byte, to the first character
+// in the aToType "string".
+NS_IMETHODIMP
+TestConverter::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *ctxt,
+ nsIInputStream **_retval) {
+ char buf[1024+1];
+ uint32_t read;
+ nsresult rv = aFromStream->Read(buf, 1024, &read);
+ if (NS_FAILED(rv) || read == 0) return rv;
+
+ // verify that the data we're converting matches the from type
+ // if it doesn't then we're being handed the wrong data.
+ char fromChar = *aFromType;
+
+ if (fromChar != buf[0]) {
+ printf("We're receiving %c, but are supposed to have %c.\n", buf[0], fromChar);
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // Get the first character
+ char toChar = *aToType;
+
+ for (uint32_t i = 0; i < read; i++)
+ buf[i] = toChar;
+
+ buf[read] = '\0';
+
+ nsCOMPtr<nsIStringInputStream> str
+ (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = str->SetData(buf, read);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ADDREF(*_retval = str);
+ return NS_OK;
+}
+
+/* This method initializes any internal state before the stream converter
+ * begins asynchronous conversion */
+NS_IMETHODIMP
+TestConverter::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *ctxt) {
+ NS_ASSERTION(aListener, "null listener");
+
+ mListener = aListener;
+
+ // based on these types, setup internal state to handle the appropriate conversion.
+ fromType = aFromType;
+ toType = aToType;
+
+ return NS_OK;
+}
+
+// nsIStreamListener method
+/* This method handles asyncronous conversion of data. */
+NS_IMETHODIMP
+TestConverter::OnDataAvailable(nsIRequest* request,
+ nsISupports *ctxt,
+ nsIInputStream *inStr,
+ uint64_t sourceOffset,
+ uint32_t count) {
+ nsresult rv;
+ nsCOMPtr<nsIInputStream> convertedStream;
+ // just make a syncronous call to the Convert() method.
+ // Anything can happen here, I just happen to be using the sync call to
+ // do the actual conversion.
+ rv = Convert(inStr, fromType.get(), toType.get(), ctxt, getter_AddRefs(convertedStream));
+ if (NS_FAILED(rv)) return rv;
+
+ uint64_t len = 0;
+ convertedStream->Available(&len);
+
+ uint64_t offset = sourceOffset;
+ while (len > 0) {
+ uint32_t count = saturated(len);
+ rv = mListener->OnDataAvailable(request, ctxt, convertedStream, offset, count);
+ if (NS_FAILED(rv)) return rv;
+
+ offset += count;
+ len -= count;
+ }
+ return NS_OK;
+}
+
+// nsIRequestObserver methods
+/* These methods just pass through directly to the mListener */
+NS_IMETHODIMP
+TestConverter::OnStartRequest(nsIRequest* request, nsISupports *ctxt) {
+ return mListener->OnStartRequest(request, ctxt);
+}
+
+NS_IMETHODIMP
+TestConverter::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus) {
+ return mListener->OnStopRequest(request, ctxt, aStatus);
+}
+
+nsresult
+CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult)
+{
+ nsCOMPtr<nsISupports> conv = new TestConverter();
+ return conv->QueryInterface(aIID, aResult);
+}
diff --git a/netwerk/streamconv/test/Converters.h b/netwerk/streamconv/test/Converters.h
new file mode 100644
index 000000000..d7203262c
--- /dev/null
+++ b/netwerk/streamconv/test/Converters.h
@@ -0,0 +1,52 @@
+#ifndef Converters_h___
+#define Converters_h___
+
+#include "nsIStreamConverter.h"
+#include "nsIFactory.h"
+#include "nsCOMPtr.h"
+#include "nsStringAPI.h"
+
+#include <algorithm>
+
+/* This file defines stream converter components, and their accompanying factory class.
+ * These converters implement the nsIStreamConverter interface and support both
+ * asynchronous and synchronous stream conversion.
+ */
+
+///////////////////////////////////////////////
+// TestConverter
+
+extern const nsCID kTestConverterCID;
+
+class TestConverter : public nsIStreamConverter {
+ virtual ~TestConverter() {}
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ TestConverter();
+
+ // nsIStreamConverter methods
+ NS_IMETHOD Convert(nsIInputStream *aFromStream, const char *aFromType,
+ const char *aToType, nsISupports *ctxt, nsIInputStream **_retval) override;
+
+
+ NS_IMETHOD AsyncConvertData(const char *aFromType, const char *aToType,
+ nsIStreamListener *aListener, nsISupports *ctxt) override;
+
+ // member data
+ nsCOMPtr<nsIStreamListener> mListener;
+ nsCString fromType;
+ nsCString toType;
+};
+
+nsresult CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
+static inline uint32_t
+saturated(uint64_t aValue)
+{
+ return (uint32_t) std::min(aValue, (uint64_t) UINT32_MAX);
+}
+
+#endif /* !Converters_h___ */
diff --git a/netwerk/streamconv/test/TestStreamConv.cpp b/netwerk/streamconv/test/TestStreamConv.cpp
new file mode 100644
index 000000000..68b85fdd7
--- /dev/null
+++ b/netwerk/streamconv/test/TestStreamConv.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "nsIServiceManager.h"
+#include "nsIStreamConverterService.h"
+#include "nsIStreamConverter.h"
+#include "nsICategoryManager.h"
+#include "mozilla/Module.h"
+#include "nsXULAppAPI.h"
+#include "nsIStringStream.h"
+#include "nsCOMPtr.h"
+#include "nsThreadUtils.h"
+#include "mozilla/Attributes.h"
+#include "nsMemory.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIRequest.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+
+#define ASYNC_TEST // undefine this if you want to test sycnronous conversion.
+
+/////////////////////////////////
+// Event pump setup
+/////////////////////////////////
+#ifdef XP_WIN
+#include <windows.h>
+#endif
+
+static int gKeepRunning = 0;
+/////////////////////////////////
+// Event pump END
+/////////////////////////////////
+
+
+/////////////////////////////////
+// Test converters include
+/////////////////////////////////
+#include "Converters.h"
+
+// CID setup
+static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
+
+////////////////////////////////////////////////////////////////////////
+// EndListener - This listener is the final one in the chain. It
+// receives the fully converted data, although it doesn't do anything with
+// the data.
+////////////////////////////////////////////////////////////////////////
+class EndListener final : public nsIStreamListener {
+ ~EndListener() {}
+public:
+ // nsISupports declaration
+ NS_DECL_ISUPPORTS
+
+ EndListener() {}
+
+ // nsIStreamListener method
+ NS_IMETHOD OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr,
+ uint64_t sourceOffset, uint32_t count) override
+ {
+ nsresult rv;
+ uint32_t read;
+ uint64_t len64;
+ rv = inStr->Available(&len64);
+ if (NS_FAILED(rv)) return rv;
+ uint32_t len = (uint32_t)std::min(len64, (uint64_t)(UINT32_MAX - 1));
+
+ char *buffer = (char*)moz_xmalloc(len + 1);
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = inStr->Read(buffer, len, &read);
+ buffer[len] = '\0';
+ if (NS_SUCCEEDED(rv)) {
+ printf("CONTEXT %p: Received %u bytes and the following data: \n %s\n\n",
+ static_cast<void*>(ctxt), read, buffer);
+ }
+ free(buffer);
+
+ return NS_OK;
+ }
+
+ // nsIRequestObserver methods
+ NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt) override { return NS_OK; }
+
+ NS_IMETHOD OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus) override { return NS_OK; }
+};
+
+NS_IMPL_ISUPPORTS(EndListener,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+////////////////////////////////////////////////////////////////////////
+// EndListener END
+////////////////////////////////////////////////////////////////////////
+
+nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) {
+ nsresult rv;
+
+ nsCOMPtr<nsIStringInputStream> dataStream
+ (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = dataStream->SetData(aData, strlen(aData));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint64_t avail = 0;
+ dataStream->Available(&avail);
+
+ uint64_t offset = 0;
+ while (avail > 0) {
+ uint32_t count = saturated(avail);
+ rv = aListener->OnDataAvailable(request, nullptr, dataStream,
+ offset, count);
+ if (NS_FAILED(rv)) return rv;
+
+ offset += count;
+ avail -= count;
+ }
+ return NS_OK;
+}
+#define SEND_DATA(x) SendData(x, converterListener, request)
+
+static const mozilla::Module::CIDEntry kTestCIDs[] = {
+ { &kTestConverterCID, false, nullptr, CreateTestConverter },
+ { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry kTestContracts[] = {
+ { NS_ISTREAMCONVERTER_KEY "?from=a/foo&to=b/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=c/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=d/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=c/foo&to=d/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=e/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=f/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=t/foo&to=k/foo", &kTestConverterCID },
+ { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry kTestCategories[] = {
+ { NS_ISTREAMCONVERTER_KEY, "?from=a/foo&to=b/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=c/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=d/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=c/foo&to=d/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=e/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=f/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=t/foo&to=k/foo", "x" },
+ { nullptr }
+};
+
+static const mozilla::Module kTestModule = {
+ mozilla::Module::kVersion,
+ kTestCIDs,
+ kTestContracts,
+ kTestCategories
+};
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ {
+ XRE_AddStaticComponent(&kTestModule);
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr);
+
+ nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
+
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return -1;
+ nsCString previous;
+
+ nsCOMPtr<nsIStreamConverterService> StreamConvService =
+ do_GetService(kStreamConverterServiceCID, &rv);
+ if (NS_FAILED(rv)) return -1;
+
+ // Define the *from* content type and *to* content-type for conversion.
+ static const char fromStr[] = "a/foo";
+ static const char toStr[] = "c/foo";
+
+#ifdef ASYNC_TEST
+ // ASYNCHRONOUS conversion
+
+ // Build up a channel that represents the content we're
+ // starting the transaction with.
+ //
+ // sample multipart mixed content-type string:
+ // "multipart/x-mixed-replacE;boundary=thisrandomstring"
+#if 0
+ nsCOMPtr<nsIChannel> channel;
+ nsCOMPtr<nsIURI> dummyURI;
+ rv = NS_NewURI(getter_AddRefs(dummyURI), "http://meaningless");
+ if (NS_FAILED(rv)) return -1;
+
+ rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
+ dummyURI,
+ nullptr, // inStr
+ "text/plain", // content-type
+ -1); // XXX fix contentLength
+ if (NS_FAILED(rv)) return -1;
+
+ nsCOMPtr<nsIRequest> request(do_QueryInterface(channel));
+#endif
+
+ nsCOMPtr<nsIRequest> request;
+
+ // setup a listener to receive the converted data. This guy is the end
+ // listener in the chain, he wants the fully converted (toType) data.
+ // An example of this listener in mozilla would be the DocLoader.
+ nsIStreamListener *dataReceiver = new EndListener();
+ NS_ADDREF(dataReceiver);
+
+ // setup a listener to push the data into. This listener sits inbetween the
+ // unconverted data of fromType, and the final listener in the chain (in this case
+ // the dataReceiver.
+ nsIStreamListener *converterListener = nullptr;
+ rv = StreamConvService->AsyncConvertData(fromStr, toStr,
+ dataReceiver, nullptr, &converterListener);
+ if (NS_FAILED(rv)) return -1;
+ NS_RELEASE(dataReceiver);
+
+ // at this point we have a stream listener to push data to, and the one
+ // that will receive the converted data. Let's mimic On*() calls and get the conversion
+ // going. Typically these On*() calls would be made inside their respective wrappers On*()
+ // methods.
+ rv = converterListener->OnStartRequest(request, nullptr);
+ if (NS_FAILED(rv)) return -1;
+
+ rv = SEND_DATA("aaa");
+ if (NS_FAILED(rv)) return -1;
+
+ rv = SEND_DATA("aaa");
+ if (NS_FAILED(rv)) return -1;
+
+ // Finish the request.
+ rv = converterListener->OnStopRequest(request, nullptr, rv);
+ if (NS_FAILED(rv)) return -1;
+
+ NS_RELEASE(converterListener);
+#else
+ // SYNCHRONOUS conversion
+ nsCOMPtr<nsIInputStream> convertedData;
+ rv = StreamConvService->Convert(inputData, fromStr, toStr,
+ nullptr, getter_AddRefs(convertedData));
+ if (NS_FAILED(rv)) return -1;
+#endif
+
+ // Enter the message pump to allow the URL load to proceed.
+ while ( gKeepRunning ) {
+ if (!NS_ProcessNextEvent(thread))
+ break;
+ }
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ NS_ShutdownXPCOM(nullptr);
+ return 0;
+}
diff --git a/netwerk/streamconv/test/moz.build b/netwerk/streamconv/test/moz.build
new file mode 100644
index 000000000..ea081559b
--- /dev/null
+++ b/netwerk/streamconv/test/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+GeckoProgram('TestStreamConv', linkage='dependent')
+
+UNIFIED_SOURCES += [
+ 'Converters.cpp',
+ 'TestStreamConv.cpp',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ DEFINES['NGPREFS'] = True
+ if CONFIG['GNU_CXX']:
+ LDFLAGS += ['-mconsole']
+ else:
+ LDFLAGS += ['-SUBSYSTEM:CONSOLE']
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']