Bug 1203680 P4 Fix bug in nsStorageStream with reading streams created before data is populated. r=froydnj
authorBen Kelly <ben@wanderview.com>
Tue, 15 Sep 2015 10:15:45 -0700
changeset 262615 0c0bfeb70612ef41aa093eb0158b840fc7ad1115
parent 262614 278ddd4793c39195bbf156bb70b6838d845ea04a
child 262616 52093388544adaa41d3abfe0413d60763a7f1a7d
push id15198
push userkwierso@gmail.com
push dateWed, 16 Sep 2015 00:21:31 +0000
treeherderfx-team@dbfddd6efb5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1203680
milestone43.0a1
Bug 1203680 P4 Fix bug in nsStorageStream with reading streams created before data is populated. r=froydnj
xpcom/io/nsStorageStream.cpp
xpcom/tests/gtest/TestStorageStream.cpp
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -455,17 +455,25 @@ nsStorageInputStream::ReadSegments(nsWri
   while (remainingCapacity) {
     availableInSegment = mSegmentEnd - mReadCursor;
     if (!availableInSegment) {
       uint32_t available = mStorageStream->mLogicalLength - mLogicalCursor;
       if (!available) {
         goto out;
       }
 
-      mSegmentNum++;
+      // We have data in the stream, but if mSegmentEnd is zero, then we
+      // were likely constructed prior to any data being written into
+      // the stream.  Therefore, if mSegmentEnd is non-zero, we should
+      // move into the next segment; otherwise, we should stay in this
+      // segment so our input state can be updated and we can properly
+      // perform the initial read.
+      if (mSegmentEnd > 0) {
+        mSegmentNum++;
+      }
       mReadCursor = 0;
       mSegmentEnd = XPCOM_MIN(mSegmentSize, available);
       availableInSegment = mSegmentEnd;
     }
     const char* cur = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum);
 
     count = XPCOM_MIN(availableInSegment, remainingCapacity);
     rv = aWriter(this, aClosure, cur + mReadCursor, aCount - remainingCapacity,
--- a/xpcom/tests/gtest/TestStorageStream.cpp
+++ b/xpcom/tests/gtest/TestStorageStream.cpp
@@ -9,27 +9,29 @@
 #include "Helpers.h"
 #include "nsCOMPtr.h"
 #include "nsICloneableInputStream.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIStorageStream.h"
 
 namespace {
+
 void
 WriteData(nsIOutputStream* aOut, nsTArray<char>& aData, uint32_t aNumBytes,
           nsACString& aDataWritten)
 {
   uint32_t n;
   nsresult rv = aOut->Write(aData.Elements(), aNumBytes, &n);
   EXPECT_TRUE(NS_SUCCEEDED(rv));
   aDataWritten.Append(aData.Elements(), aNumBytes);
 }
 
 } // namespace
+
 TEST(StorageStreams, Main)
 {
   // generate some test data we will write in 4k chunks to the stream
   nsTArray<char> kData;
   testing::CreateData(4096, kData);
 
   // track how much data was written so we can compare at the end
   nsAutoCString dataWritten;
@@ -84,8 +86,45 @@ TEST(StorageStreams, Main)
 
   // now, read all
   rv = stor->NewInputStream(0, getter_AddRefs(in));
   EXPECT_TRUE(NS_SUCCEEDED(rv));
 
   testing::ConsumeAndValidateStream(in, dataWritten);
   in = nullptr;
 }
+
+TEST(StorageStreams, EarlyInputStream)
+{
+  // generate some test data we will write in 4k chunks to the stream
+  nsTArray<char> kData;
+  testing::CreateData(4096, kData);
+
+  // track how much data was written so we can compare at the end
+  nsAutoCString dataWritten;
+
+  nsresult rv;
+  nsCOMPtr<nsIStorageStream> stor;
+
+  rv = NS_NewStorageStream(kData.Length(), UINT32_MAX, getter_AddRefs(stor));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Get input stream before writing data into the output stream
+  nsCOMPtr<nsIInputStream> in;
+  rv = stor->NewInputStream(0, getter_AddRefs(in));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Write data to output stream
+  nsCOMPtr<nsIOutputStream> out;
+  rv = stor->GetOutputStream(0, getter_AddRefs(out));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  WriteData(out, kData, kData.Length(), dataWritten);
+  WriteData(out, kData, kData.Length(), dataWritten);
+
+  rv = out->Close();
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+  out = nullptr;
+
+  // Should be able to consume input stream
+  testing::ConsumeAndValidateStream(in, dataWritten);
+  in = nullptr;
+}