TestRandomAccessStreamUtils.cpp (6573B)
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/. */ 6 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" 16 #include "nsCOMPtr.h" 17 #include "nsDirectoryServiceUtils.h" 18 #include "nsIFile.h" 19 #include "nsIFileStreams.h" 20 #include "nsIRandomAccessStream.h" 21 #include "nsNetUtil.h" 22 #include "nsStreamUtils.h" 23 24 namespace mozilla::ipc { 25 26 namespace { 27 28 Result<nsCOMPtr<nsIRandomAccessStream>, nsresult> CreateFileStream() { 29 nsCOMPtr<nsIFile> dir; 30 nsresult rv = 31 NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(dir)); 32 if (NS_FAILED(rv)) { 33 return Err(rv); 34 } 35 36 nsCOMPtr<nsIFile> file; 37 rv = dir->Clone(getter_AddRefs(file)); 38 if (NS_FAILED(rv)) { 39 return Err(rv); 40 } 41 42 rv = file->Append(u"testfile"_ns); 43 if (NS_FAILED(rv)) { 44 return Err(rv); 45 } 46 47 rv = file->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0666); 48 if (NS_FAILED(rv)) { 49 return Err(rv); 50 } 51 52 nsCOMPtr<nsIRandomAccessStream> stream; 53 rv = NS_NewLocalFileRandomAccessStream(getter_AddRefs(stream), file); 54 if (NS_FAILED(rv)) { 55 return Err(rv); 56 } 57 58 return stream; 59 } 60 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; 74 75 aDataOut.SetCapacity(aNumBytes); 76 77 while (aNumBytes > 0) { 78 uint32_t amount = std::min(dataLength, aNumBytes); 79 aDataOut.Append(data, amount); 80 aNumBytes -= amount; 81 } 82 } 83 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()); 92 93 nsAutoCString outputData; 94 rv = NS_ConsumeStream(aStream, UINT32_MAX, outputData); 95 ASSERT_NS_SUCCEEDED(rv); 96 97 ASSERT_EQ(aExpectedData.Length(), outputData.Length()); 98 ASSERT_TRUE(aExpectedData.Equals(outputData)); 99 } 100 101 } // namespace 102 103 TEST(RandomAccessStreamUtils, NullRandomAccessStream_MaybeSerialize) 104 { 105 nsCOMPtr<nsIRandomAccessStream> stream; 106 107 Maybe<RandomAccessStreamParams> streamParams = 108 SerializeRandomAccessStream(stream, nullptr); 109 110 ASSERT_TRUE(streamParams.isNothing()); 111 112 auto res = DeserializeRandomAccessStream(streamParams); 113 ASSERT_TRUE(res.isOk()); 114 115 nsCOMPtr<nsIRandomAccessStream> stream2 = res.unwrap(); 116 ASSERT_EQ(stream2, nullptr); 117 } 118 119 TEST(RandomAccessStreamUtils, FileRandomAccessStream_Serialize) 120 { 121 const uint32_t dataSize = 256; 122 123 auto res = CreateFileStream(); 124 ASSERT_TRUE(res.isOk()); 125 126 auto stream = res.unwrap(); 127 ASSERT_TRUE(stream); 128 129 nsCOMPtr<nsIFileRandomAccessStream> fileStream = do_QueryInterface(stream); 130 ASSERT_TRUE(fileStream); 131 132 nsCString inputData; 133 CreateData(dataSize, inputData); 134 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); 140 141 RandomAccessStreamParams streamParams = SerializeRandomAccessStream( 142 WrapMovingNotNullUnchecked(std::move(stream)), nullptr); 143 144 ASSERT_EQ(streamParams.type(), 145 RandomAccessStreamParams::TFileRandomAccessStreamParams); 146 147 auto res2 = DeserializeRandomAccessStream(streamParams); 148 ASSERT_TRUE(res2.isOk()); 149 150 NotNull<nsCOMPtr<nsIRandomAccessStream>> stream2 = res2.unwrap(); 151 152 nsCOMPtr<nsIFileRandomAccessStream> fileStream2 = 153 do_QueryInterface(stream2.get()); 154 ASSERT_TRUE(fileStream2); 155 156 int64_t offset; 157 rv = stream2->Tell(&offset); 158 ASSERT_NS_SUCCEEDED(rv); 159 ASSERT_EQ(offset, dataSize); 160 161 rv = stream2->Seek(nsISeekableStream::NS_SEEK_SET, 0); 162 ASSERT_NS_SUCCEEDED(rv); 163 164 ConsumeAndValidateStream(stream2->InputStream(), inputData); 165 } 166 167 TEST(RandomAccessStreamUtils, FileRandomAccessStream_MaybeSerialize) 168 { 169 const uint32_t dataSize = 512; 170 171 auto res = CreateFileStream(); 172 ASSERT_TRUE(res.isOk()); 173 174 auto stream = res.unwrap(); 175 ASSERT_TRUE(stream); 176 177 nsCOMPtr<nsIFileRandomAccessStream> fileStream = do_QueryInterface(stream); 178 ASSERT_TRUE(fileStream); 179 180 nsCString inputData; 181 CreateData(dataSize, inputData); 182 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); 188 189 Maybe<RandomAccessStreamParams> streamParams = 190 SerializeRandomAccessStream(stream, nullptr); 191 192 ASSERT_TRUE(streamParams); 193 ASSERT_EQ(streamParams->type(), 194 RandomAccessStreamParams::TFileRandomAccessStreamParams); 195 196 auto res2 = DeserializeRandomAccessStream(streamParams); 197 ASSERT_TRUE(res2.isOk()); 198 199 nsCOMPtr<nsIRandomAccessStream> stream2 = res2.unwrap(); 200 ASSERT_TRUE(stream2); 201 202 nsCOMPtr<nsIFileRandomAccessStream> fileStream2 = do_QueryInterface(stream2); 203 ASSERT_TRUE(fileStream2); 204 205 int64_t offset; 206 rv = stream2->Tell(&offset); 207 ASSERT_NS_SUCCEEDED(rv); 208 ASSERT_EQ(offset, dataSize); 209 210 rv = stream2->Seek(nsISeekableStream::NS_SEEK_SET, 0); 211 ASSERT_NS_SUCCEEDED(rv); 212 213 ConsumeAndValidateStream(stream2->InputStream(), inputData); 214 } 215 216 } // namespace mozilla::ipc