1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef __Helpers_h 8 #define __Helpers_h 9 10 #include "nsCOMPtr.h" 11 #include "nsIAsyncInputStream.h" 12 #include "nsIAsyncOutputStream.h" 13 #include "nsIInputStreamLength.h" 14 #include "nsString.h" 15 #include "nsStringStream.h" 16 #include "nsTArrayForwardDeclare.h" 17 #include "nsThreadUtils.h" 18 #include <stdint.h> 19 20 class nsIInputStream; 21 class nsIOutputStream; 22 23 namespace testing { 24 25 void CreateData(uint32_t aNumBytes, nsTArray<char>& aDataOut); 26 27 void Write(nsIOutputStream* aStream, const nsTArray<char>& aData, 28 uint32_t aOffset, uint32_t aNumBytes); 29 30 void WriteAllAndClose(nsIOutputStream* aStream, const nsTArray<char>& aData); 31 32 void ConsumeAndValidateStream(nsIInputStream* aStream, 33 const nsTArray<char>& aExpectedData); 34 35 void ConsumeAndValidateStream(nsIInputStream* aStream, 36 const nsACString& aExpectedData); 37 38 class OutputStreamCallback final : public nsIOutputStreamCallback { 39 public: 40 OutputStreamCallback(); 41 Called()42 bool Called() const { return mCalled; } 43 44 private: 45 ~OutputStreamCallback(); 46 47 bool mCalled; 48 49 public: 50 NS_DECL_ISUPPORTS 51 NS_DECL_NSIOUTPUTSTREAMCALLBACK 52 }; 53 54 class InputStreamCallback final : public nsIInputStreamCallback { 55 public: 56 InputStreamCallback(); 57 Called()58 bool Called() const { return mCalled; } 59 60 private: 61 ~InputStreamCallback(); 62 63 bool mCalled; 64 65 public: 66 NS_DECL_ISUPPORTS 67 NS_DECL_NSIINPUTSTREAMCALLBACK 68 }; 69 70 class AsyncStringStream final : public nsIAsyncInputStream { 71 nsCOMPtr<nsIInputStream> mStream; 72 73 public: 74 NS_DECL_THREADSAFE_ISUPPORTS 75 NS_DECL_NSIINPUTSTREAM 76 NS_DECL_NSIASYNCINPUTSTREAM 77 78 explicit AsyncStringStream(const nsACString& aBuffer); 79 80 private: 81 ~AsyncStringStream() = default; 82 83 void MaybeExecCallback(nsIInputStreamCallback* aCallback, 84 nsIEventTarget* aEventTarget); 85 86 nsCOMPtr<nsIInputStreamCallback> mCallback; 87 nsCOMPtr<nsIEventTarget> mCallbackEventTarget; 88 }; 89 90 // This class implements a simple nsIInputStreamLength stream. 91 class LengthInputStream : public nsIInputStream, 92 public nsIInputStreamLength, 93 public nsIAsyncInputStreamLength { 94 nsCOMPtr<nsIInputStream> mStream; 95 bool mIsInputStreamLength; 96 bool mIsAsyncInputStreamLength; 97 nsresult mLengthRv; 98 bool mNegativeValue; 99 100 public: 101 NS_DECL_THREADSAFE_ISUPPORTS 102 103 LengthInputStream(const nsACString& aBuffer, bool aIsInputStreamLength, 104 bool aIsAsyncInputStreamLength, nsresult aLengthRv = NS_OK, 105 bool aNegativeValue = false) mIsInputStreamLength(aIsInputStreamLength)106 : mIsInputStreamLength(aIsInputStreamLength), 107 mIsAsyncInputStreamLength(aIsAsyncInputStreamLength), 108 mLengthRv(aLengthRv), 109 mNegativeValue(aNegativeValue) { 110 NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer); 111 } 112 113 NS_IMETHOD Available(uint64_t * aLength)114 Available(uint64_t* aLength) override { return mStream->Available(aLength); } 115 116 NS_IMETHOD Read(char * aBuffer,uint32_t aCount,uint32_t * aReadCount)117 Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override { 118 return mStream->Read(aBuffer, aCount, aReadCount); 119 } 120 121 NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter,void * aClosure,uint32_t aCount,uint32_t * aResult)122 ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, 123 uint32_t* aResult) override { 124 return mStream->ReadSegments(aWriter, aClosure, aCount, aResult); 125 } 126 127 NS_IMETHOD Close()128 Close() override { return mStream->Close(); } 129 130 NS_IMETHOD IsNonBlocking(bool * aNonBlocking)131 IsNonBlocking(bool* aNonBlocking) override { 132 return mStream->IsNonBlocking(aNonBlocking); 133 } 134 135 NS_IMETHOD Length(int64_t * aLength)136 Length(int64_t* aLength) override { 137 if (mNegativeValue) { 138 *aLength = -1; 139 } else { 140 mStream->Available((uint64_t*)aLength); 141 } 142 return mLengthRv; 143 } 144 145 NS_IMETHOD AsyncLengthWait(nsIInputStreamLengthCallback * aCallback,nsIEventTarget * aEventTarget)146 AsyncLengthWait(nsIInputStreamLengthCallback* aCallback, 147 nsIEventTarget* aEventTarget) override { 148 RefPtr<LengthInputStream> self = this; 149 nsCOMPtr<nsIInputStreamLengthCallback> callback = aCallback; 150 151 nsCOMPtr<nsIRunnable> r = 152 NS_NewRunnableFunction("AsyncLengthWait", [self, callback]() { 153 int64_t length; 154 self->Length(&length); 155 callback->OnInputStreamLengthReady(self, length); 156 }); 157 158 return aEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL); 159 } 160 161 protected: 162 virtual ~LengthInputStream() = default; 163 }; 164 165 class LengthCallback final : public nsIInputStreamLengthCallback { 166 bool mCalled; 167 int64_t mSize; 168 169 public: 170 NS_DECL_THREADSAFE_ISUPPORTS 171 LengthCallback()172 LengthCallback() : mCalled(false), mSize(0) {} 173 174 NS_IMETHOD OnInputStreamLengthReady(nsIAsyncInputStreamLength * aStream,int64_t aLength)175 OnInputStreamLengthReady(nsIAsyncInputStreamLength* aStream, 176 int64_t aLength) override { 177 mCalled = true; 178 mSize = aLength; 179 return NS_OK; 180 } 181 Called()182 bool Called() const { return mCalled; } 183 Size()184 int64_t Size() const { return mSize; } 185 186 private: 187 ~LengthCallback() = default; 188 }; 189 190 } // namespace testing 191 192 #endif // __Helpers_h 193