Backed out 4 changesets (bug 1636823) for bustages on TestReadStreamToString.cpp . CLOSED TREE

Backed out changeset 13ab343d2c45 (bug 1636823)
Backed out changeset 50dd67f96214 (bug 1636823)
Backed out changeset 9cdc2e31ee04 (bug 1636823)
Backed out changeset 7d220fd9ac49 (bug 1636823)
This commit is contained in:
Narcis Beleuzu 2020-06-13 01:13:40 +03:00
parent 692fccc5dd
commit f5fcf19b63
15 changed files with 77 additions and 308 deletions

View File

@ -7,6 +7,7 @@
#include "nsIOService.h"
#include "nsInputStreamPump.h"
#include "nsIStreamTransportService.h"
#include "nsITransport.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "nsThreadUtils.h"
#include "nsCOMPtr.h"
@ -319,14 +320,50 @@ nsInputStreamPump::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) {
"nsInputStreamPump should be read from the "
"main thread only.");
nsresult rv = NS_MakeAsyncNonBlockingInputStream(
mStream.forget(), getter_AddRefs(mAsyncStream), mCloseWhenDone, mSegSize,
mSegCount);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
//
// OK, we need to use the stream transport service if
//
// (1) the stream is blocking
// (2) the stream does not support nsIAsyncInputStream
//
bool nonBlocking;
nsresult rv = mStream->IsNonBlocking(&nonBlocking);
if (NS_FAILED(rv)) return rv;
if (nonBlocking) {
mAsyncStream = do_QueryInterface(mStream);
if (!mAsyncStream) {
rv = NonBlockingAsyncInputStream::Create(mStream.forget(),
getter_AddRefs(mAsyncStream));
if (NS_WARN_IF(NS_FAILED(rv))) return rv;
}
MOZ_ASSERT(mAsyncStream);
}
MOZ_ASSERT(mAsyncStream);
if (!mAsyncStream) {
// ok, let's use the stream transport service to read this stream.
nsCOMPtr<nsIStreamTransportService> sts =
do_GetService(kStreamTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(mStream, mCloseWhenDone,
getter_AddRefs(transport));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> wrapper;
rv = transport->OpenInputStream(0, mSegSize, mSegCount,
getter_AddRefs(wrapper));
if (NS_FAILED(rv)) return rv;
mAsyncStream = do_QueryInterface(wrapper, &rv);
if (NS_FAILED(rv)) return rv;
}
// release our reference to the original stream. from this point forward,
// we only reference the "stream" via mAsyncStream.
mStream = nullptr;
// mStreamOffset now holds the number of bytes currently read.
mStreamOffset = 0;

View File

@ -29,61 +29,36 @@ namespace net {
// and close-when-done semantics while utilizing NS_AsyncCopy.
//-----------------------------------------------------------------------------
class nsInputStreamTransport : public nsITransport,
public nsIAsyncInputStream,
public nsIInputStreamCallback {
class nsInputStreamTransport : public nsITransport, public nsIInputStream {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITRANSPORT
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
nsInputStreamTransport(nsIInputStream* source, bool closeWhenDone)
: mMutex("nsInputStreamTransport::mMutex"),
mSource(source),
: mSource(source),
mOffset(0),
mCloseWhenDone(closeWhenDone),
mInProgress(false) {
mAsyncSource = do_QueryInterface(mSource);
}
mInProgress(false) {}
private:
virtual ~nsInputStreamTransport() = default;
Mutex mMutex;
// This value is protected by mutex.
nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
nsCOMPtr<nsIAsyncInputStream> mPipeIn;
// while the copy is active, these members may only be accessed from the
// nsIInputStream implementation.
nsCOMPtr<nsITransportEventSink> mEventSink;
nsCOMPtr<nsIInputStream> mSource;
// It can be null.
nsCOMPtr<nsIAsyncInputStream> mAsyncSource;
int64_t mOffset;
const bool mCloseWhenDone;
bool mCloseWhenDone;
// this variable serves as a lock to prevent the state of the transport
// from being modified once the copy is in progress.
bool mInProgress;
};
NS_IMPL_ADDREF(nsInputStreamTransport);
NS_IMPL_RELEASE(nsInputStreamTransport);
NS_INTERFACE_MAP_BEGIN(nsInputStreamTransport)
NS_INTERFACE_MAP_ENTRY(nsITransport)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, !!mAsyncSource)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, !!mAsyncSource)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransport)
NS_INTERFACE_MAP_END
NS_IMPL_ISUPPORTS(nsInputStreamTransport, nsITransport, nsIInputStream)
/** nsITransport **/
@ -192,53 +167,6 @@ nsInputStreamTransport::IsNonBlocking(bool* result) {
return NS_OK;
}
// nsIAsyncInputStream interface
NS_IMETHODIMP
nsInputStreamTransport::CloseWithStatus(nsresult aStatus) { return Close(); }
NS_IMETHODIMP
nsInputStreamTransport::AsyncWait(nsIInputStreamCallback* aCallback,
uint32_t aFlags, uint32_t aRequestedCount,
nsIEventTarget* aEventTarget) {
NS_ENSURE_STATE(!!mAsyncSource);
nsCOMPtr<nsIInputStreamCallback> callback = aCallback ? this : nullptr;
{
MutexAutoLock lock(mMutex);
if (mAsyncWaitCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mAsyncWaitCallback = aCallback;
}
return mAsyncSource->AsyncWait(callback, aFlags, aRequestedCount,
aEventTarget);
}
// nsIInputStreamCallback
NS_IMETHODIMP
nsInputStreamTransport::OnInputStreamReady(nsIAsyncInputStream* aStream) {
nsCOMPtr<nsIInputStreamCallback> callback;
{
MutexAutoLock lock(mMutex);
// We have been canceled in the meanwhile.
if (!mAsyncWaitCallback) {
return NS_OK;
}
callback.swap(mAsyncWaitCallback);
}
MOZ_ASSERT(callback);
return callback->OnInputStreamReady(this);
}
//-----------------------------------------------------------------------------
// nsStreamTransportService
//-----------------------------------------------------------------------------

View File

@ -39,5 +39,6 @@ class WaitForCondition final : public nsIRunnable {
uint32_t mPending = 0;
};
NS_IMPL_ISUPPORTS(WaitForCondition, nsIRunnable)
#endif

View File

@ -1,7 +0,0 @@
/* 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 "TestCommon.h"
NS_IMPL_ISUPPORTS(WaitForCondition, nsIRunnable)

View File

@ -1,191 +0,0 @@
#include "gtest/gtest.h"
#include "nsIStreamTransportService.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "Helpers.h"
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
void CreateStream(already_AddRefed<nsIInputStream> aSource,
nsIAsyncInputStream** aStream) {
nsCOMPtr<nsIInputStream> source = std::move(aSource);
nsresult rv;
nsCOMPtr<nsIStreamTransportService> sts =
do_GetService(kStreamTransportServiceCID, &rv);
ASSERT_EQ(NS_OK, rv);
nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(source, true, getter_AddRefs(transport));
ASSERT_EQ(NS_OK, rv);
nsCOMPtr<nsIInputStream> wrapper;
rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
ASSERT_EQ(NS_OK, rv);
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(wrapper);
MOZ_ASSERT(asyncStream);
asyncStream.forget(aStream);
}
class BlockingSyncStream final : public nsIInputStream {
nsCOMPtr<nsIInputStream> mStream;
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit BlockingSyncStream(const nsACString& aBuffer) {
NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
}
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
uint32_t* aResult) override {
return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
}
NS_IMETHOD
Close() override { return mStream->Close(); }
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override {
*aNonBlocking = false;
return NS_OK;
}
private:
~BlockingSyncStream() = default;
};
NS_IMPL_ISUPPORTS(BlockingSyncStream, nsIInputStream)
// Testing a simple blocking stream.
TEST(TestInputStreamTransport, BlockingNotAsync)
{
RefPtr<BlockingSyncStream> stream =
new BlockingSyncStream(NS_LITERAL_CSTRING("Hello world"));
nsCOMPtr<nsIAsyncInputStream> ais;
CreateStream(stream.forget(), getter_AddRefs(ais));
ASSERT_TRUE(!!ais);
nsAutoCString data;
nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
ASSERT_EQ(NS_OK, rv);
ASSERT_TRUE(data.EqualsLiteral("Hello world"));
}
class BlockingAsyncStream final : public nsIAsyncInputStream {
nsCOMPtr<nsIInputStream> mStream;
bool mPending;
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit BlockingAsyncStream(const nsACString& aBuffer) : mPending(false) {
NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
}
NS_IMETHOD
Available(uint64_t* aLength) override {
mStream->Available(aLength);
// 1 char at the time, just to test the asyncWait+Read loop a bit more.
if (*aLength > 0) {
*aLength = 1;
}
return NS_OK;
}
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
mPending = !mPending;
if (mPending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
// 1 char at the time, just to test the asyncWait+Read loop a bit more.
aCount = 1;
return mStream->Read(aBuffer, aCount, aReadCount);
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
uint32_t* aResult) override {
mPending = !mPending;
if (mPending) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
// 1 char at the time, just to test the asyncWait+Read loop a bit more.
aCount = 1;
return mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
}
NS_IMETHOD
Close() override { return mStream->Close(); }
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override {
*aNonBlocking = false;
return NS_OK;
}
NS_IMETHOD
CloseWithStatus(nsresult aStatus) override { return Close(); }
NS_IMETHOD
AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
uint32_t aRequestedCount, nsIEventTarget* aEventTarget) override {
RefPtr<BlockingAsyncStream> self = this;
nsCOMPtr<nsIInputStreamCallback> callback = aCallback;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"gtest-asyncwait",
[self, callback]() { callback->OnInputStreamReady(self); });
if (aEventTarget) {
aEventTarget->Dispatch(r.forget());
} else {
r->Run();
}
return NS_OK;
}
private:
~BlockingAsyncStream() = default;
};
NS_IMPL_ISUPPORTS(BlockingAsyncStream, nsIInputStream, nsIAsyncInputStream)
// Testing an async blocking stream.
TEST(TestInputStreamTransport, BlockingAsync)
{
RefPtr<BlockingAsyncStream> stream =
new BlockingAsyncStream(NS_LITERAL_CSTRING("Hello world"));
nsCOMPtr<nsIAsyncInputStream> ais;
CreateStream(stream.forget(), getter_AddRefs(ais));
ASSERT_TRUE(!!ais);
nsAutoCString data;
nsresult rv = NS_ReadInputStreamToString(ais, data, -1);
ASSERT_EQ(NS_OK, rv);
ASSERT_TRUE(data.EqualsLiteral("Hello world"));
}

View File

@ -2,7 +2,6 @@
#include "nsCOMPtr.h"
#include "nsNetUtil.h"
#include "nsStringStream.h"
// Here we test the reading a pre-allocated size
TEST(TestReadStreamToString, SyncStreamPreAllocatedSize)

View File

@ -1,7 +1,6 @@
#include "gtest/gtest.h"
#include "nsCOMPtr.h"
#include "nsNetCID.h"
#include "nsIURIMutator.h"
#include "nsIURL.h"
#include "nsThreadPool.h"
#include "nsNetUtil.h"

View File

@ -5,14 +5,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestBind.cpp',
'TestBufferedInputStream.cpp',
'TestCommon.cpp',
'TestCookie.cpp',
'TestHeaders.cpp',
'TestHttpAuthUtils.cpp',
'TestHttpResponseHead.cpp',
'TestInputStreamTransport.cpp',
'TestIsValidIp.cpp',
'TestMIMEInputStream.cpp',
'TestMozURL.cpp',
@ -21,17 +17,8 @@ UNIFIED_SOURCES += [
'TestServerTimingHeader.cpp',
'TestSocketTransportService.cpp',
'TestStandardURL.cpp',
'TestUDPSocket.cpp',
]
if CONFIG['OS_TARGET'] == 'WINNT':
UNIFIED_SOURCES += [
'TestNamedPipeService.cpp',
]
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-shadow']
# skip the test on windows10-aarch64
if not(CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CPU_ARCH'] == 'aarch64'):
UNIFIED_SOURCES += [
@ -66,7 +53,6 @@ TEST_DIRS += [
LOCAL_INCLUDES += [
'/netwerk/base',
'/netwerk/cookie',
'/toolkit/components/jsoncpp/include',
'/xpcom/tests/gtest',
]

View File

@ -14,6 +14,27 @@ XPCSHELL_TESTS_MANIFESTS += [
'unit_ipc/xpcshell.ini',
]
FINAL_LIBRARY = 'xul-gtest'
UNIFIED_SOURCES += [
'TestBind.cpp',
'TestCookie.cpp',
'TestUDPSocket.cpp',
]
LOCAL_INCLUDES += [
'/netwerk/cookie',
]
if CONFIG['OS_TARGET'] == 'WINNT':
UNIFIED_SOURCES += [
'TestNamedPipeService.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-shadow']
if CONFIG['FUZZING_INTERFACES']:
TEST_DIRS += [
'fuzz'

View File

@ -890,8 +890,7 @@ nsresult NS_CloneInputStream(nsIInputStream* aSource,
nsresult NS_MakeAsyncNonBlockingInputStream(
already_AddRefed<nsIInputStream> aSource,
nsIAsyncInputStream** aAsyncInputStream, bool aCloseWhenDone,
uint32_t aFlags, uint32_t aSegmentSize, uint32_t aSegmentCount) {
nsIAsyncInputStream** aAsyncInputStream) {
nsCOMPtr<nsIInputStream> source = std::move(aSource);
if (NS_WARN_IF(!aAsyncInputStream)) {
return NS_ERROR_FAILURE;
@ -924,14 +923,17 @@ nsresult NS_MakeAsyncNonBlockingInputStream(
}
nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(source, aCloseWhenDone,
rv = sts->CreateInputTransport(source,
/* aCloseWhenDone */ true,
getter_AddRefs(transport));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIInputStream> wrapper;
rv = transport->OpenInputStream(aFlags, aSegmentSize, aSegmentCount,
rv = transport->OpenInputStream(/* aFlags */ 0,
/* aSegmentSize */ 0,
/* aSegmentCount */ 0,
getter_AddRefs(wrapper));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -306,15 +306,9 @@ extern nsresult NS_CloneInputStream(nsIInputStream* aSource,
* The last step is to use nsIStreamTransportService and create a pipe in order
* to expose a non-blocking async inputStream and read |aSource| data from
* a separate thread.
*
* In case we need to create a pipe, |aCloseWhenDone| will be used to create the
* inputTransport, |aFlags|, |aSegmentSize|, |asegmentCount| will be used to
* open the inputStream. If true, the input stream will be closed after it has
* been read. Read more in nsITransport.idl.
*/
extern nsresult NS_MakeAsyncNonBlockingInputStream(
already_AddRefed<nsIInputStream> aSource,
nsIAsyncInputStream** aAsyncInputStream, bool aCloseWhenDone = true,
uint32_t aFlags = 0, uint32_t aSegmentSize = 0, uint32_t aSegmentCount = 0);
nsIAsyncInputStream** aAsyncInputStream);
#endif // !nsStreamUtils_h__