Bug 1879774 [wpt PR 44524] - WebKit export: Implement field-sizing support for input...
[gecko.git] / ipc / gtest / TestDataPipe.cpp
blob340da7c2180b17acaa955bfb8382deaec3a134f9
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "chrome/common/ipc_message.h"
8 #include "gtest/gtest.h"
10 #include "mozilla/gtest/MozAssertions.h"
11 #include "mozilla/ipc/DataPipe.h"
12 #include "nsIAsyncInputStream.h"
13 #include "nsIAsyncOutputStream.h"
14 #include "nsNetUtil.h"
15 #include "nsStreamUtils.h"
17 namespace mozilla::ipc {
19 namespace {
21 struct InputStreamCallback : public nsIInputStreamCallback {
22 public:
23 NS_DECL_THREADSAFE_ISUPPORTS
25 explicit InputStreamCallback(
26 std::function<nsresult(nsIAsyncInputStream*)> aFunc = nullptr)
27 : mFunc(std::move(aFunc)) {}
29 NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream* aStream) override {
30 MOZ_ALWAYS_FALSE(mCalled.exchange(true));
31 return mFunc ? mFunc(aStream) : NS_OK;
34 bool Called() const { return mCalled; }
36 private:
37 virtual ~InputStreamCallback() = default;
39 std::atomic<bool> mCalled = false;
40 std::function<nsresult(nsIAsyncInputStream*)> mFunc;
43 NS_IMPL_ISUPPORTS(InputStreamCallback, nsIInputStreamCallback)
45 struct OutputStreamCallback : public nsIOutputStreamCallback {
46 public:
47 NS_DECL_THREADSAFE_ISUPPORTS
49 explicit OutputStreamCallback(
50 std::function<nsresult(nsIAsyncOutputStream*)> aFunc = nullptr)
51 : mFunc(std::move(aFunc)) {}
53 NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream* aStream) override {
54 MOZ_ALWAYS_FALSE(mCalled.exchange(true));
55 return mFunc ? mFunc(aStream) : NS_OK;
58 bool Called() const { return mCalled; }
60 private:
61 virtual ~OutputStreamCallback() = default;
63 std::atomic<bool> mCalled = false;
64 std::function<nsresult(nsIAsyncOutputStream*)> mFunc;
67 NS_IMPL_ISUPPORTS(OutputStreamCallback, nsIOutputStreamCallback)
69 // Populate an array with the given number of bytes. Data is lorem ipsum
70 // random text, but deterministic across multiple calls.
71 void CreateData(uint32_t aNumBytes, nsCString& aDataOut) {
72 static const char data[] =
73 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas "
74 "purus eu condimentum iaculis. In accumsan leo eget odio porttitor, non "
75 "rhoncus nulla vestibulum. Etiam lacinia consectetur nisl nec "
76 "sollicitudin. Sed fringilla accumsan diam, pulvinar varius massa. Duis "
77 "mollis dignissim felis, eget tempus nisi tristique ut. Fusce euismod, "
78 "lectus non lacinia tempor, tellus diam suscipit quam, eget hendrerit "
79 "lacus nunc fringilla ante. Sed ultrices massa vitae risus molestie, ut "
80 "finibus quam laoreet nullam.";
81 static const uint32_t dataLength = sizeof(data) - 1;
83 aDataOut.SetCapacity(aNumBytes);
85 while (aNumBytes > 0) {
86 uint32_t amount = std::min(dataLength, aNumBytes);
87 aDataOut.Append(data, amount);
88 aNumBytes -= amount;
92 // Synchronously consume the given input stream and validate the resulting data
93 // against the given string of expected values.
94 void ConsumeAndValidateStream(nsIInputStream* aStream,
95 const nsACString& aExpectedData) {
96 nsAutoCString outputData;
97 nsresult rv = NS_ConsumeStream(aStream, UINT32_MAX, outputData);
98 ASSERT_NS_SUCCEEDED(rv);
99 ASSERT_EQ(aExpectedData.Length(), outputData.Length());
100 ASSERT_TRUE(aExpectedData.Equals(outputData));
103 } // namespace
105 TEST(DataPipe, SegmentedReadWrite)
107 RefPtr<DataPipeReceiver> reader;
108 RefPtr<DataPipeSender> writer;
110 nsresult rv =
111 NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
112 ASSERT_NS_SUCCEEDED(rv);
114 nsCString inputData1;
115 CreateData(512, inputData1);
117 uint32_t numWritten = 0;
118 rv = writer->Write(inputData1.BeginReading(), inputData1.Length(),
119 &numWritten);
120 ASSERT_NS_SUCCEEDED(rv);
121 EXPECT_EQ(numWritten, 512u);
123 uint64_t available = 0;
124 rv = reader->Available(&available);
125 EXPECT_EQ(available, 512u);
126 ConsumeAndValidateStream(reader, inputData1);
128 nsCString inputData2;
129 CreateData(1024, inputData2);
131 rv = writer->Write(inputData2.BeginReading(), inputData2.Length(),
132 &numWritten);
133 ASSERT_NS_SUCCEEDED(rv);
134 EXPECT_EQ(numWritten, 1024u);
136 rv = reader->Available(&available);
137 EXPECT_EQ(available, 1024u);
138 ConsumeAndValidateStream(reader, inputData2);
141 TEST(DataPipe, SegmentedPartialRead)
143 RefPtr<DataPipeReceiver> reader;
144 RefPtr<DataPipeSender> writer;
146 nsresult rv =
147 NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
148 ASSERT_NS_SUCCEEDED(rv);
150 nsCString inputData1;
151 CreateData(512, inputData1);
153 uint32_t numWritten = 0;
154 rv = writer->Write(inputData1.BeginReading(), inputData1.Length(),
155 &numWritten);
156 ASSERT_NS_SUCCEEDED(rv);
157 EXPECT_EQ(numWritten, 512u);
159 uint64_t available = 0;
160 rv = reader->Available(&available);
161 EXPECT_EQ(available, 512u);
162 ConsumeAndValidateStream(reader, inputData1);
164 nsCString inputData2;
165 CreateData(1024, inputData2);
167 rv = writer->Write(inputData2.BeginReading(), inputData2.Length(),
168 &numWritten);
169 ASSERT_NS_SUCCEEDED(rv);
170 EXPECT_EQ(numWritten, 1024u);
172 rv = reader->Available(&available);
173 EXPECT_EQ(available, 1024u);
175 nsAutoCString outputData;
176 rv = NS_ReadInputStreamToString(reader, outputData, 768);
177 ASSERT_NS_SUCCEEDED(rv);
178 ASSERT_EQ(768u, outputData.Length());
179 ASSERT_TRUE(Substring(inputData2, 0, 768).Equals(outputData));
181 rv = reader->Available(&available);
182 EXPECT_EQ(available, 256u);
184 nsAutoCString outputData2;
185 rv = NS_ReadInputStreamToString(reader, outputData2, 256);
186 ASSERT_NS_SUCCEEDED(rv);
187 ASSERT_EQ(256u, outputData2.Length());
188 ASSERT_TRUE(Substring(inputData2, 768).Equals(outputData2));
191 TEST(DataPipe, Write_AsyncWait)
193 RefPtr<DataPipeReceiver> reader;
194 RefPtr<DataPipeSender> writer;
196 const uint32_t segmentSize = 1024;
198 nsresult rv =
199 NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
200 ASSERT_NS_SUCCEEDED(rv);
202 nsCString inputData;
203 CreateData(segmentSize, inputData);
205 uint32_t numWritten = 0;
206 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
207 ASSERT_NS_SUCCEEDED(rv);
208 EXPECT_EQ(numWritten, segmentSize);
210 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
211 ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv);
213 RefPtr<OutputStreamCallback> cb = new OutputStreamCallback();
215 rv = writer->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
216 ASSERT_NS_SUCCEEDED(rv);
218 NS_ProcessPendingEvents(nullptr);
220 ASSERT_FALSE(cb->Called());
222 ConsumeAndValidateStream(reader, inputData);
224 ASSERT_FALSE(cb->Called());
226 NS_ProcessPendingEvents(nullptr);
228 ASSERT_TRUE(cb->Called());
231 TEST(DataPipe, Read_AsyncWait)
233 RefPtr<DataPipeReceiver> reader;
234 RefPtr<DataPipeSender> writer;
236 const uint32_t segmentSize = 1024;
238 nsresult rv =
239 NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
240 ASSERT_NS_SUCCEEDED(rv);
242 nsCString inputData;
243 CreateData(segmentSize, inputData);
245 RefPtr<InputStreamCallback> cb = new InputStreamCallback();
247 rv = reader->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
248 ASSERT_NS_SUCCEEDED(rv);
250 NS_ProcessPendingEvents(nullptr);
252 ASSERT_FALSE(cb->Called());
254 uint32_t numWritten = 0;
255 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
256 ASSERT_NS_SUCCEEDED(rv);
258 ASSERT_FALSE(cb->Called());
260 NS_ProcessPendingEvents(nullptr);
262 ASSERT_TRUE(cb->Called());
264 ConsumeAndValidateStream(reader, inputData);
267 TEST(DataPipe, Write_AsyncWait_Cancel)
269 RefPtr<DataPipeReceiver> reader;
270 RefPtr<DataPipeSender> writer;
272 const uint32_t segmentSize = 1024;
274 nsresult rv =
275 NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
276 ASSERT_NS_SUCCEEDED(rv);
278 nsCString inputData;
279 CreateData(segmentSize, inputData);
281 uint32_t numWritten = 0;
282 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
283 ASSERT_NS_SUCCEEDED(rv);
284 EXPECT_EQ(numWritten, segmentSize);
286 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
287 ASSERT_EQ(NS_BASE_STREAM_WOULD_BLOCK, rv);
289 RefPtr<OutputStreamCallback> cb = new OutputStreamCallback();
291 // Register a callback and immediately cancel it.
292 rv = writer->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
293 ASSERT_NS_SUCCEEDED(rv);
294 rv = writer->AsyncWait(nullptr, 0, 0, nullptr);
295 ASSERT_NS_SUCCEEDED(rv);
297 // Even after consuming the stream and processing pending events, the callback
298 // shouldn't be called as it was cancelled.
299 ConsumeAndValidateStream(reader, inputData);
300 NS_ProcessPendingEvents(nullptr);
301 ASSERT_FALSE(cb->Called());
304 TEST(DataPipe, Read_AsyncWait_Cancel)
306 RefPtr<DataPipeReceiver> reader;
307 RefPtr<DataPipeSender> writer;
309 const uint32_t segmentSize = 1024;
311 nsresult rv =
312 NewDataPipe(segmentSize, getter_AddRefs(writer), getter_AddRefs(reader));
313 ASSERT_NS_SUCCEEDED(rv);
315 nsCString inputData;
316 CreateData(segmentSize, inputData);
318 RefPtr<InputStreamCallback> cb = new InputStreamCallback();
320 // Register a callback and immediately cancel it.
321 rv = reader->AsyncWait(cb, 0, 0, GetCurrentSerialEventTarget());
322 ASSERT_NS_SUCCEEDED(rv);
324 rv = reader->AsyncWait(nullptr, 0, 0, nullptr);
325 ASSERT_NS_SUCCEEDED(rv);
327 // Write data into the pipe to make the callback become ready.
328 uint32_t numWritten = 0;
329 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
330 ASSERT_NS_SUCCEEDED(rv);
332 // Even after processing pending events, the callback shouldn't be called as
333 // it was cancelled.
334 NS_ProcessPendingEvents(nullptr);
335 ASSERT_FALSE(cb->Called());
337 ConsumeAndValidateStream(reader, inputData);
340 TEST(DataPipe, SerializeReader)
342 RefPtr<DataPipeReceiver> reader;
343 RefPtr<DataPipeSender> writer;
344 nsresult rv =
345 NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
346 ASSERT_NS_SUCCEEDED(rv);
348 IPC::Message msg(MSG_ROUTING_NONE, 0);
349 IPC::MessageWriter msgWriter(msg);
350 IPC::WriteParam(&msgWriter, reader);
352 uint64_t available = 0;
353 rv = reader->Available(&available);
354 ASSERT_NS_FAILED(rv);
356 nsCString inputData;
357 CreateData(512, inputData);
359 uint32_t numWritten = 0;
360 rv = writer->Write(inputData.BeginReading(), inputData.Length(), &numWritten);
361 ASSERT_NS_SUCCEEDED(rv);
363 RefPtr<DataPipeReceiver> reader2;
364 IPC::MessageReader msgReader(msg);
365 ASSERT_TRUE(IPC::ReadParam(&msgReader, &reader2));
366 ASSERT_TRUE(reader2);
368 rv = reader2->Available(&available);
369 ASSERT_NS_SUCCEEDED(rv);
370 ASSERT_EQ(available, 512u);
371 ConsumeAndValidateStream(reader2, inputData);
374 } // namespace mozilla::ipc