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"
9 #include "mozilla/NotNull.h"
10 #include "mozilla/Result.h"
11 #include "mozilla/ResultVariant.h"
12 #include "mozilla/ipc/RandomAccessStreamParams.h"
13 #include "mozilla/ipc/RandomAccessStreamUtils.h"
14 #include "mozilla/gtest/MozAssertions.h"
15 #include "nsAppDirectoryServiceDefs.h"
17 #include "nsDirectoryServiceUtils.h"
19 #include "nsIFileStreams.h"
20 #include "nsIRandomAccessStream.h"
21 #include "nsNetUtil.h"
22 #include "nsStreamUtils.h"
24 namespace mozilla::ipc
{
28 Result
<nsCOMPtr
<nsIRandomAccessStream
>, nsresult
> CreateFileStream() {
29 nsCOMPtr
<nsIFile
> dir
;
31 NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
, getter_AddRefs(dir
));
36 nsCOMPtr
<nsIFile
> file
;
37 rv
= dir
->Clone(getter_AddRefs(file
));
42 rv
= file
->Append(u
"testfile"_ns
);
47 rv
= file
->CreateUnique(nsIFile::NORMAL_FILE_TYPE
, 0666);
52 nsCOMPtr
<nsIRandomAccessStream
> stream
;
53 rv
= NS_NewLocalFileRandomAccessStream(getter_AddRefs(stream
), file
);
61 // Populate an array with the given number of bytes. Data is lorem ipsum
62 // random text, but deterministic across multiple calls.
63 void CreateData(uint32_t aNumBytes
, nsCString
& aDataOut
) {
64 static const char data
[] =
65 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas "
66 "purus eu condimentum iaculis. In accumsan leo eget odio porttitor, non "
67 "rhoncus nulla vestibulum. Etiam lacinia consectetur nisl nec "
68 "sollicitudin. Sed fringilla accumsan diam, pulvinar varius massa. Duis "
69 "mollis dignissim felis, eget tempus nisi tristique ut. Fusce euismod, "
70 "lectus non lacinia tempor, tellus diam suscipit quam, eget hendrerit "
71 "lacus nunc fringilla ante. Sed ultrices massa vitae risus molestie, ut "
72 "finibus quam laoreet nullam.";
73 static const uint32_t dataLength
= sizeof(data
) - 1;
75 aDataOut
.SetCapacity(aNumBytes
);
77 while (aNumBytes
> 0) {
78 uint32_t amount
= std::min(dataLength
, aNumBytes
);
79 aDataOut
.Append(data
, amount
);
84 // Synchronously consume the given input stream and validate the resulting data
85 // against the given string of expected values.
86 void ConsumeAndValidateStream(nsIInputStream
* aStream
,
87 const nsACString
& aExpectedData
) {
88 uint64_t available
= 0;
89 nsresult rv
= aStream
->Available(&available
);
90 ASSERT_NS_SUCCEEDED(rv
);
91 ASSERT_EQ(available
, aExpectedData
.Length());
93 nsAutoCString outputData
;
94 rv
= NS_ConsumeStream(aStream
, UINT32_MAX
, outputData
);
95 ASSERT_NS_SUCCEEDED(rv
);
97 ASSERT_EQ(aExpectedData
.Length(), outputData
.Length());
98 ASSERT_TRUE(aExpectedData
.Equals(outputData
));
103 TEST(RandomAccessStreamUtils
, NullRandomAccessStream_MaybeSerialize
)
105 nsCOMPtr
<nsIRandomAccessStream
> stream
;
107 Maybe
<RandomAccessStreamParams
> streamParams
=
108 SerializeRandomAccessStream(stream
, nullptr);
110 ASSERT_TRUE(streamParams
.isNothing());
112 auto res
= DeserializeRandomAccessStream(streamParams
);
113 ASSERT_TRUE(res
.isOk());
115 nsCOMPtr
<nsIRandomAccessStream
> stream2
= res
.unwrap();
116 ASSERT_EQ(stream2
, nullptr);
119 TEST(RandomAccessStreamUtils
, FileRandomAccessStream_Serialize
)
121 const uint32_t dataSize
= 256;
123 auto res
= CreateFileStream();
124 ASSERT_TRUE(res
.isOk());
126 auto stream
= res
.unwrap();
129 nsCOMPtr
<nsIFileRandomAccessStream
> fileStream
= do_QueryInterface(stream
);
130 ASSERT_TRUE(fileStream
);
133 CreateData(dataSize
, inputData
);
135 uint32_t numWritten
= 0;
136 nsresult rv
= stream
->OutputStream()->Write(inputData
.BeginReading(),
137 inputData
.Length(), &numWritten
);
138 ASSERT_NS_SUCCEEDED(rv
);
139 ASSERT_EQ(numWritten
, dataSize
);
141 RandomAccessStreamParams streamParams
= SerializeRandomAccessStream(
142 WrapMovingNotNullUnchecked(std::move(stream
)), nullptr);
144 ASSERT_EQ(streamParams
.type(),
145 RandomAccessStreamParams::TFileRandomAccessStreamParams
);
147 auto res2
= DeserializeRandomAccessStream(streamParams
);
148 ASSERT_TRUE(res2
.isOk());
150 NotNull
<nsCOMPtr
<nsIRandomAccessStream
>> stream2
= res2
.unwrap();
152 nsCOMPtr
<nsIFileRandomAccessStream
> fileStream2
=
153 do_QueryInterface(stream2
.get());
154 ASSERT_TRUE(fileStream2
);
157 rv
= stream2
->Tell(&offset
);
158 ASSERT_NS_SUCCEEDED(rv
);
159 ASSERT_EQ(offset
, dataSize
);
161 rv
= stream2
->Seek(nsISeekableStream::NS_SEEK_SET
, 0);
162 ASSERT_NS_SUCCEEDED(rv
);
164 ConsumeAndValidateStream(stream2
->InputStream(), inputData
);
167 TEST(RandomAccessStreamUtils
, FileRandomAccessStream_MaybeSerialize
)
169 const uint32_t dataSize
= 512;
171 auto res
= CreateFileStream();
172 ASSERT_TRUE(res
.isOk());
174 auto stream
= res
.unwrap();
177 nsCOMPtr
<nsIFileRandomAccessStream
> fileStream
= do_QueryInterface(stream
);
178 ASSERT_TRUE(fileStream
);
181 CreateData(dataSize
, inputData
);
183 uint32_t numWritten
= 0;
184 nsresult rv
= stream
->OutputStream()->Write(inputData
.BeginReading(),
185 inputData
.Length(), &numWritten
);
186 ASSERT_NS_SUCCEEDED(rv
);
187 ASSERT_EQ(numWritten
, dataSize
);
189 Maybe
<RandomAccessStreamParams
> streamParams
=
190 SerializeRandomAccessStream(stream
, nullptr);
192 ASSERT_TRUE(streamParams
);
193 ASSERT_EQ(streamParams
->type(),
194 RandomAccessStreamParams::TFileRandomAccessStreamParams
);
196 auto res2
= DeserializeRandomAccessStream(streamParams
);
197 ASSERT_TRUE(res2
.isOk());
199 nsCOMPtr
<nsIRandomAccessStream
> stream2
= res2
.unwrap();
200 ASSERT_TRUE(stream2
);
202 nsCOMPtr
<nsIFileRandomAccessStream
> fileStream2
= do_QueryInterface(stream2
);
203 ASSERT_TRUE(fileStream2
);
206 rv
= stream2
->Tell(&offset
);
207 ASSERT_NS_SUCCEEDED(rv
);
208 ASSERT_EQ(offset
, dataSize
);
210 rv
= stream2
->Seek(nsISeekableStream::NS_SEEK_SET
, 0);
211 ASSERT_NS_SUCCEEDED(rv
);
213 ConsumeAndValidateStream(stream2
->InputStream(), inputData
);
216 } // namespace mozilla::ipc