diff options
Diffstat (limited to 'xpcom/tests/gtest/Helpers.cpp')
-rw-r--r-- | xpcom/tests/gtest/Helpers.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/xpcom/tests/gtest/Helpers.cpp b/xpcom/tests/gtest/Helpers.cpp new file mode 100644 index 0000000000..84053cbeb3 --- /dev/null +++ b/xpcom/tests/gtest/Helpers.cpp @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +/* Helper routines for xpcom gtests. */ + +#include "Helpers.h" + +#include <algorithm> +#include "gtest/gtest.h" +#include "mozilla/gtest/MozAssertions.h" +#include "nsIOutputStream.h" +#include "nsStreamUtils.h" +#include "nsTArray.h" +#include "nsThreadUtils.h" + +namespace testing { + +// Populate an array with the given number of bytes. Data is lorem ipsum +// random text, but deterministic across multiple calls. +void CreateData(uint32_t aNumBytes, nsTArray<char>& aDataOut) { + static const char data[] = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas " + "purus eu condimentum iaculis. In accumsan leo eget odio porttitor, non " + "rhoncus nulla vestibulum. Etiam lacinia consectetur nisl nec " + "sollicitudin. Sed fringilla accumsan diam, pulvinar varius massa. Duis " + "mollis dignissim felis, eget tempus nisi tristique ut. Fusce euismod, " + "lectus non lacinia tempor, tellus diam suscipit quam, eget hendrerit " + "lacus nunc fringilla ante. Sed ultrices massa vitae risus molestie, ut " + "finibus quam laoreet nullam."; + static const uint32_t dataLength = sizeof(data) - 1; + + aDataOut.SetCapacity(aNumBytes); + + while (aNumBytes > 0) { + uint32_t amount = std::min(dataLength, aNumBytes); + aDataOut.AppendElements(data, amount); + aNumBytes -= amount; + } +} + +// Write the given number of bytes out to the stream. Loop until expected +// bytes count is reached or an error occurs. +void Write(nsIOutputStream* aStream, const nsTArray<char>& aData, + uint32_t aOffset, uint32_t aNumBytes) { + uint32_t remaining = + std::min(aNumBytes, static_cast<uint32_t>(aData.Length() - aOffset)); + + while (remaining > 0) { + uint32_t numWritten; + nsresult rv = + aStream->Write(aData.Elements() + aOffset, remaining, &numWritten); + ASSERT_NS_SUCCEEDED(rv); + if (numWritten < 1) { + break; + } + aOffset += numWritten; + remaining -= numWritten; + } +} + +// Write the given number of bytes and then close the stream. +void WriteAllAndClose(nsIOutputStream* aStream, const nsTArray<char>& aData) { + Write(aStream, aData, 0, aData.Length()); + aStream->Close(); +} + +// Synchronously consume the given input stream and validate the resulting data +// against the given array of expected values. +void ConsumeAndValidateStream(nsIInputStream* aStream, + const nsTArray<char>& aExpectedData) { + nsDependentCSubstring data(aExpectedData.Elements(), aExpectedData.Length()); + ConsumeAndValidateStream(aStream, data); +} + +// Synchronously consume the given input stream and validate the resulting data +// against the given string of expected values. +void ConsumeAndValidateStream(nsIInputStream* aStream, + const nsACString& aExpectedData) { + nsAutoCString outputData; + nsresult rv = NS_ConsumeStream(aStream, UINT32_MAX, outputData); + ASSERT_NS_SUCCEEDED(rv); + ASSERT_EQ(aExpectedData.Length(), outputData.Length()); + ASSERT_TRUE(aExpectedData.Equals(outputData)); +} + +NS_IMPL_ISUPPORTS(OutputStreamCallback, nsIOutputStreamCallback); + +OutputStreamCallback::OutputStreamCallback() : mCalled(false) {} + +OutputStreamCallback::~OutputStreamCallback() = default; + +NS_IMETHODIMP +OutputStreamCallback::OnOutputStreamReady(nsIAsyncOutputStream* aStream) { + mCalled = true; + return NS_OK; +} + +NS_IMPL_ISUPPORTS(InputStreamCallback, nsIInputStreamCallback); + +InputStreamCallback::InputStreamCallback() : mCalled(false) {} + +InputStreamCallback::~InputStreamCallback() = default; + +NS_IMETHODIMP +InputStreamCallback::OnInputStreamReady(nsIAsyncInputStream* aStream) { + mCalled = true; + return NS_OK; +} + +AsyncStringStream::AsyncStringStream(const nsACString& aBuffer) { + NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer); +} + +NS_IMETHODIMP +AsyncStringStream::Available(uint64_t* aLength) { + return mStream->Available(aLength); +} + +NS_IMETHODIMP +AsyncStringStream::StreamStatus() { return mStream->StreamStatus(); } + +NS_IMETHODIMP +AsyncStringStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) { + return mStream->Read(aBuffer, aCount, aReadCount); +} + +NS_IMETHODIMP +AsyncStringStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, + uint32_t aCount, uint32_t* aResult) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +AsyncStringStream::Close() { + nsresult rv = mStream->Close(); + if (NS_SUCCEEDED(rv)) { + MaybeExecCallback(mCallback, mCallbackEventTarget); + } + return rv; +} + +NS_IMETHODIMP +AsyncStringStream::IsNonBlocking(bool* aNonBlocking) { + return mStream->IsNonBlocking(aNonBlocking); +} + +NS_IMETHODIMP +AsyncStringStream::CloseWithStatus(nsresult aStatus) { return Close(); } + +NS_IMETHODIMP +AsyncStringStream::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags, + uint32_t aRequestedCount, + nsIEventTarget* aEventTarget) { + if (aFlags & nsIAsyncInputStream::WAIT_CLOSURE_ONLY) { + mCallback = aCallback; + mCallbackEventTarget = aEventTarget; + return NS_OK; + } + + MaybeExecCallback(aCallback, aEventTarget); + return NS_OK; +} + +void AsyncStringStream::MaybeExecCallback(nsIInputStreamCallback* aCallback, + nsIEventTarget* aEventTarget) { + if (!aCallback) { + return; + } + + nsCOMPtr<nsIInputStreamCallback> callback = aCallback; + nsCOMPtr<nsIAsyncInputStream> self = this; + + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "AsyncWait", [callback, self]() { callback->OnInputStreamReady(self); }); + + if (aEventTarget) { + aEventTarget->Dispatch(r.forget()); + } else { + r->Run(); + } +} + +NS_IMPL_ISUPPORTS(AsyncStringStream, nsIAsyncInputStream, nsIInputStream) + +NS_IMPL_ADDREF(LengthInputStream); +NS_IMPL_RELEASE(LengthInputStream); + +NS_INTERFACE_MAP_BEGIN(LengthInputStream) + NS_INTERFACE_MAP_ENTRY(nsIInputStream) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength, mIsInputStreamLength) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStreamLength, + mIsAsyncInputStreamLength) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) +NS_INTERFACE_MAP_END + +NS_IMPL_ISUPPORTS(LengthCallback, nsIInputStreamLengthCallback) + +} // namespace testing |