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