Bug 1100398 P2 Make nsStringInputStream cloneable. r=froydnj
authorBen Kelly <ben@wanderview.com>
Tue, 10 Feb 2015 23:55:43 -0500
changeset 228745 507718807f6d78af80a493ecbdef21fcd5108631
parent 228744 f14875d011dccf4e4c923012cc7eef4ca2712670
child 228746 db0d65c0b7a7cecdeb2b8612729f19d03f49dffd
push id28271
push usercbook@mozilla.com
push dateThu, 12 Feb 2015 14:33:39 +0000
treeherdermozilla-central@81f979b17fbd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1100398
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1100398 P2 Make nsStringInputStream cloneable. r=froydnj
xpcom/io/nsStringStream.cpp
xpcom/tests/gtest/TestStringStream.cpp
xpcom/tests/gtest/moz.build
--- a/xpcom/io/nsStringStream.cpp
+++ b/xpcom/io/nsStringStream.cpp
@@ -8,16 +8,17 @@
  * Based on original code from nsIStringStream.cpp
  */
 
 #include "ipc/IPCMessageUtils.h"
 
 #include "nsStringStream.h"
 #include "nsStreamUtils.h"
 #include "nsReadableUtils.h"
+#include "nsICloneableInputStream.h"
 #include "nsISeekableStream.h"
 #include "nsISupportsPrimitives.h"
 #include "nsCRT.h"
 #include "prerror.h"
 #include "plstr.h"
 #include "nsIClassInfoImpl.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/InputStreamUtils.h"
@@ -29,31 +30,41 @@ using namespace mozilla::ipc;
 // nsIStringInputStream implementation
 //-----------------------------------------------------------------------------
 
 class nsStringInputStream MOZ_FINAL
   : public nsIStringInputStream
   , public nsISeekableStream
   , public nsISupportsCString
   , public nsIIPCSerializableInputStream
+  , public nsICloneableInputStream
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSISTRINGINPUTSTREAM
   NS_DECL_NSISEEKABLESTREAM
   NS_DECL_NSISUPPORTSPRIMITIVE
   NS_DECL_NSISUPPORTSCSTRING
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
+  NS_DECL_NSICLONEABLEINPUTSTREAM
 
   nsStringInputStream()
   {
     Clear();
   }
 
+  explicit nsStringInputStream(const nsStringInputStream& aOther)
+    : mOffset(aOther.mOffset)
+  {
+    // Use Assign() here because we don't want the life of the clone to be
+    // dependent on the life of the original stream.
+    mData.Assign(aOther.mData);
+  }
+
 private:
   ~nsStringInputStream()
   {
   }
 
   uint32_t Length() const
   {
     return mData.Length();
@@ -85,22 +96,24 @@ NS_IMPL_RELEASE(nsStringInputStream)
 
 NS_IMPL_CLASSINFO(nsStringInputStream, nullptr, nsIClassInfo::THREADSAFE,
                   NS_STRINGINPUTSTREAM_CID)
 NS_IMPL_QUERY_INTERFACE_CI(nsStringInputStream,
                            nsIStringInputStream,
                            nsIInputStream,
                            nsISupportsCString,
                            nsISeekableStream,
-                           nsIIPCSerializableInputStream)
+                           nsIIPCSerializableInputStream,
+                           nsICloneableInputStream)
 NS_IMPL_CI_INTERFACE_GETTER(nsStringInputStream,
                             nsIStringInputStream,
                             nsIInputStream,
                             nsISupportsCString,
-                            nsISeekableStream)
+                            nsISeekableStream,
+                            nsICloneableInputStream)
 
 /////////
 // nsISupportsCString implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::GetType(uint16_t* aType)
 {
@@ -303,16 +316,20 @@ nsStringInputStream::SetEOF()
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   mOffset = Length();
   return NS_OK;
 }
 
+/////////
+// nsIIPCSerializableInputStream implementation
+/////////
+
 void
 nsStringInputStream::Serialize(InputStreamParams& aParams,
                                FileDescriptorArray& /* aFDs */)
 {
   StringInputStreamParams params;
   params.data() = PromiseFlatCString(mData);
   aParams = params;
 }
@@ -332,16 +349,35 @@ nsStringInputStream::Deserialize(const I
   if (NS_FAILED(SetData(params.data()))) {
     NS_WARNING("SetData failed!");
     return false;
   }
 
   return true;
 }
 
+/////////
+// nsICloneableInputStream implementation
+/////////
+
+NS_IMETHODIMP
+nsStringInputStream::GetCloneable(bool* aCloneableOut)
+{
+  *aCloneableOut = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringInputStream::Clone(nsIInputStream** aCloneOut)
+{
+  nsRefPtr<nsIInputStream> ref = new nsStringInputStream(*this);
+  ref.forget(aCloneOut);
+  return NS_OK;
+}
+
 nsresult
 NS_NewByteInputStream(nsIInputStream** aStreamResult,
                       const char* aStringToRead, int32_t aLength,
                       nsAssignmentType aAssignment)
 {
   NS_PRECONDITION(aStreamResult, "null out ptr");
 
   nsStringInputStream* stream = new nsStringInputStream();
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/gtest/TestStringStream.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; 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 "gtest/gtest.h"
+#include "Helpers.h"
+#include "nsICloneableInputStream.h"
+#include "nsStringStream.h"
+
+namespace {
+
+static void TestStringStream(uint32_t aNumBytes)
+{
+  nsTArray<char> inputData;
+  testing::CreateData(aNumBytes, inputData);
+  nsDependentCSubstring inputString(inputData.Elements(), inputData.Length());
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream), inputString);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  testing::ConsumeAndValidateStream(stream, inputString);
+}
+
+static void TestStringStreamClone(uint32_t aNumBytes)
+{
+  nsTArray<char> inputData;
+  testing::CreateData(aNumBytes, inputData);
+  nsDependentCSubstring inputString(inputData.Elements(), inputData.Length());
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream), inputString);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
+  ASSERT_TRUE(cloneable != nullptr);
+  ASSERT_TRUE(cloneable->GetCloneable());
+
+  nsCOMPtr<nsIInputStream> clone;
+  rv = cloneable->Clone(getter_AddRefs(clone));
+
+  testing::ConsumeAndValidateStream(stream, inputString);
+
+  // Release the stream to verify that the clone's string survives correctly.
+  stream = nullptr;
+
+  testing::ConsumeAndValidateStream(clone, inputString);
+}
+
+} // anonymous namespace
+
+TEST(StringStream, Simple_4k)
+{
+  TestStringStream(1024 * 4);
+}
+
+TEST(StringStream, Clone_4k)
+{
+  TestStringStreamClone(1024 * 4);
+}
--- a/xpcom/tests/gtest/moz.build
+++ b/xpcom/tests/gtest/moz.build
@@ -9,16 +9,17 @@ UNIFIED_SOURCES += [
     'TestCRT.cpp',
     'TestEncoding.cpp',
     'TestExpirationTracker.cpp',
     'TestPipes.cpp',
     'TestPriorityQueue.cpp',
     'TestSnappyStreams.cpp',
     'TestStorageStream.cpp',
     'TestStrings.cpp',
+    'TestStringStream.cpp',
     'TestSynchronization.cpp',
     'TestThreadPool.cpp',
     'TestTimeStamp.cpp',
     'TestUTF.cpp',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'