1 //===- llvm/unittest/Support/BinaryStreamTest.cpp -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/BinaryByteStream.h" 10 #include "llvm/Support/BinaryItemStream.h" 11 #include "llvm/Support/BinaryStreamArray.h" 12 #include "llvm/Support/BinaryStreamReader.h" 13 #include "llvm/Support/BinaryStreamRef.h" 14 #include "llvm/Support/BinaryStreamWriter.h" 15 #include "llvm/Testing/Support/Error.h" 16 17 #include "gtest/gtest.h" 18 19 20 using namespace llvm; 21 using namespace llvm::support; 22 23 namespace { 24 25 class BrokenStream : public WritableBinaryStream { 26 public: 27 BrokenStream(MutableArrayRef<uint8_t> Data, endianness Endian, 28 uint32_t Align) 29 : Data(Data), PartitionIndex(alignDown(Data.size() / 2, Align)), 30 Endian(Endian) {} 31 32 endianness getEndian() const override { return Endian; } 33 34 Error readBytes(uint32_t Offset, uint32_t Size, 35 ArrayRef<uint8_t> &Buffer) override { 36 if (auto EC = checkOffsetForRead(Offset, Size)) 37 return EC; 38 uint32_t S = startIndex(Offset); 39 auto Ref = Data.drop_front(S); 40 if (Ref.size() >= Size) { 41 Buffer = Ref.take_front(Size); 42 return Error::success(); 43 } 44 45 uint32_t BytesLeft = Size - Ref.size(); 46 uint8_t *Ptr = Allocator.Allocate<uint8_t>(Size); 47 ::memcpy(Ptr, Ref.data(), Ref.size()); 48 ::memcpy(Ptr + Ref.size(), Data.data(), BytesLeft); 49 Buffer = makeArrayRef<uint8_t>(Ptr, Size); 50 return Error::success(); 51 } 52 53 Error readLongestContiguousChunk(uint32_t Offset, 54 ArrayRef<uint8_t> &Buffer) override { 55 if (auto EC = checkOffsetForRead(Offset, 1)) 56 return EC; 57 uint32_t S = startIndex(Offset); 58 Buffer = Data.drop_front(S); 59 return Error::success(); 60 } 61 62 uint32_t getLength() override { return Data.size(); } 63 64 Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override { 65 if (auto EC = checkOffsetForWrite(Offset, SrcData.size())) 66 return EC; 67 if (SrcData.empty()) 68 return Error::success(); 69 70 uint32_t S = startIndex(Offset); 71 MutableArrayRef<uint8_t> Ref(Data); 72 Ref = Ref.drop_front(S); 73 if (Ref.size() >= SrcData.size()) { 74 ::memcpy(Ref.data(), SrcData.data(), SrcData.size()); 75 return Error::success(); 76 } 77 78 uint32_t BytesLeft = SrcData.size() - Ref.size(); 79 ::memcpy(Ref.data(), SrcData.data(), Ref.size()); 80 ::memcpy(&Data[0], SrcData.data() + Ref.size(), BytesLeft); 81 return Error::success(); 82 } 83 Error commit() override { return Error::success(); } 84 85 private: 86 uint32_t startIndex(uint32_t Offset) const { 87 return (Offset + PartitionIndex) % Data.size(); 88 } 89 90 uint32_t endIndex(uint32_t Offset, uint32_t Size) const { 91 return (startIndex(Offset) + Size - 1) % Data.size(); 92 } 93 94 // Buffer is organized like this: 95 // ------------------------------------------------- 96 // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N/2-1 | 97 // ------------------------------------------------- 98 // So reads from the beginning actually come from the middle. 99 MutableArrayRef<uint8_t> Data; 100 uint32_t PartitionIndex = 0; 101 endianness Endian; 102 BumpPtrAllocator Allocator; 103 }; 104 105 constexpr endianness Endians[] = {big, little, native}; 106 constexpr uint32_t NumEndians = llvm::array_lengthof(Endians); 107 constexpr uint32_t NumStreams = 2 * NumEndians; 108 109 class BinaryStreamTest : public testing::Test { 110 111 public: 112 BinaryStreamTest() {} 113 114 void SetUp() override { 115 Streams.clear(); 116 Streams.resize(NumStreams); 117 for (uint32_t I = 0; I < NumStreams; ++I) 118 Streams[I].IsContiguous = (I % 2 == 0); 119 120 InputData.clear(); 121 OutputData.clear(); 122 } 123 124 protected: 125 struct StreamPair { 126 bool IsContiguous; 127 std::unique_ptr<BinaryStream> Input; 128 std::unique_ptr<WritableBinaryStream> Output; 129 }; 130 131 void initializeInput(ArrayRef<uint8_t> Input, uint32_t Align) { 132 InputData = Input; 133 134 BrokenInputData.resize(InputData.size()); 135 if (!Input.empty()) { 136 uint32_t PartitionIndex = alignDown(InputData.size() / 2, Align); 137 uint32_t RightBytes = InputData.size() - PartitionIndex; 138 uint32_t LeftBytes = PartitionIndex; 139 if (RightBytes > 0) 140 ::memcpy(&BrokenInputData[PartitionIndex], Input.data(), RightBytes); 141 if (LeftBytes > 0) 142 ::memcpy(&BrokenInputData[0], Input.data() + RightBytes, LeftBytes); 143 } 144 145 for (uint32_t I = 0; I < NumEndians; ++I) { 146 auto InByteStream = 147 llvm::make_unique<BinaryByteStream>(InputData, Endians[I]); 148 auto InBrokenStream = llvm::make_unique<BrokenStream>( 149 BrokenInputData, Endians[I], Align); 150 151 Streams[I * 2].Input = std::move(InByteStream); 152 Streams[I * 2 + 1].Input = std::move(InBrokenStream); 153 } 154 } 155 156 void initializeOutput(uint32_t Size, uint32_t Align) { 157 OutputData.resize(Size); 158 BrokenOutputData.resize(Size); 159 160 for (uint32_t I = 0; I < NumEndians; ++I) { 161 Streams[I * 2].Output = 162 llvm::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]); 163 Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>( 164 BrokenOutputData, Endians[I], Align); 165 } 166 } 167 168 void initializeOutputFromInput(uint32_t Align) { 169 for (uint32_t I = 0; I < NumEndians; ++I) { 170 Streams[I * 2].Output = 171 llvm::make_unique<MutableBinaryByteStream>(InputData, Endians[I]); 172 Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>( 173 BrokenInputData, Endians[I], Align); 174 } 175 } 176 177 void initializeInputFromOutput(uint32_t Align) { 178 for (uint32_t I = 0; I < NumEndians; ++I) { 179 Streams[I * 2].Input = 180 llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]); 181 Streams[I * 2 + 1].Input = llvm::make_unique<BrokenStream>( 182 BrokenOutputData, Endians[I], Align); 183 } 184 } 185 186 std::vector<uint8_t> InputData; 187 std::vector<uint8_t> BrokenInputData; 188 189 std::vector<uint8_t> OutputData; 190 std::vector<uint8_t> BrokenOutputData; 191 192 std::vector<StreamPair> Streams; 193 }; 194 195 // Tests that a we can read from a BinaryByteStream without a StreamReader. 196 TEST_F(BinaryStreamTest, BinaryByteStreamBounds) { 197 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5}; 198 initializeInput(InputData, 1); 199 200 for (auto &Stream : Streams) { 201 ArrayRef<uint8_t> Buffer; 202 203 // 1. If the read fits it should work. 204 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 205 ASSERT_THAT_ERROR(Stream.Input->readBytes(2, 1, Buffer), Succeeded()); 206 EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer); 207 ASSERT_THAT_ERROR(Stream.Input->readBytes(0, 4, Buffer), Succeeded()); 208 EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer); 209 210 // 2. Reading past the bounds of the input should fail. 211 EXPECT_THAT_ERROR(Stream.Input->readBytes(4, 2, Buffer), Failed()); 212 } 213 } 214 215 TEST_F(BinaryStreamTest, StreamRefBounds) { 216 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5}; 217 initializeInput(InputData, 1); 218 219 for (const auto &Stream : Streams) { 220 ArrayRef<uint8_t> Buffer; 221 BinaryStreamRef Ref(*Stream.Input); 222 223 // Read 1 byte from offset 2 should work 224 ASSERT_EQ(InputData.size(), Ref.getLength()); 225 ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded()); 226 EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer); 227 228 // Reading everything from offset 2 on. 229 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded()); 230 if (Stream.IsContiguous) 231 EXPECT_EQ(makeArrayRef(InputData).slice(2), Buffer); 232 else 233 EXPECT_FALSE(Buffer.empty()); 234 235 // Reading 6 bytes from offset 0 is too big. 236 EXPECT_THAT_ERROR(Ref.readBytes(0, 6, Buffer), Failed()); 237 EXPECT_THAT_ERROR(Ref.readLongestContiguousChunk(6, Buffer), Failed()); 238 239 // Reading 1 byte from offset 2 after dropping 1 byte is the same as reading 240 // 1 byte from offset 3. 241 Ref = Ref.drop_front(1); 242 ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded()); 243 if (Stream.IsContiguous) 244 EXPECT_EQ(makeArrayRef(InputData).slice(3, 1), Buffer); 245 else 246 EXPECT_FALSE(Buffer.empty()); 247 248 // Reading everything from offset 2 on after dropping 1 byte. 249 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded()); 250 if (Stream.IsContiguous) 251 EXPECT_EQ(makeArrayRef(InputData).slice(3), Buffer); 252 else 253 EXPECT_FALSE(Buffer.empty()); 254 255 // Reading 2 bytes from offset 2 after dropping 2 bytes is the same as 256 // reading 2 bytes from offset 4, and should fail. 257 Ref = Ref.drop_front(1); 258 EXPECT_THAT_ERROR(Ref.readBytes(2, 2, Buffer), Failed()); 259 260 // But if we read the longest contiguous chunk instead, we should still 261 // get the 1 byte at the end. 262 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded()); 263 EXPECT_EQ(makeArrayRef(InputData).take_back(), Buffer); 264 } 265 } 266 267 TEST_F(BinaryStreamTest, StreamRefDynamicSize) { 268 StringRef Strings[] = {"1", "2", "3", "4"}; 269 AppendingBinaryByteStream Stream(support::little); 270 271 BinaryStreamWriter Writer(Stream); 272 BinaryStreamReader Reader(Stream); 273 const uint8_t *Byte; 274 StringRef Str; 275 276 // When the stream is empty, it should report a 0 length and we should get an 277 // error trying to read even 1 byte from it. 278 BinaryStreamRef ConstRef(Stream); 279 EXPECT_EQ(0U, ConstRef.getLength()); 280 EXPECT_THAT_ERROR(Reader.readObject(Byte), Failed()); 281 282 // But if we write to it, its size should increase and we should be able to 283 // read not just a byte, but the string that was written. 284 EXPECT_THAT_ERROR(Writer.writeCString(Strings[0]), Succeeded()); 285 EXPECT_EQ(2U, ConstRef.getLength()); 286 EXPECT_THAT_ERROR(Reader.readObject(Byte), Succeeded()); 287 288 Reader.setOffset(0); 289 EXPECT_THAT_ERROR(Reader.readCString(Str), Succeeded()); 290 EXPECT_EQ(Str, Strings[0]); 291 292 // If we drop some bytes from the front, we should still track the length as 293 // the 294 // underlying stream grows. 295 BinaryStreamRef Dropped = ConstRef.drop_front(1); 296 EXPECT_EQ(1U, Dropped.getLength()); 297 298 EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded()); 299 EXPECT_EQ(4U, ConstRef.getLength()); 300 EXPECT_EQ(3U, Dropped.getLength()); 301 302 // If we drop zero bytes from the back, we should continue tracking the 303 // length. 304 Dropped = Dropped.drop_back(0); 305 EXPECT_THAT_ERROR(Writer.writeCString(Strings[2]), Succeeded()); 306 EXPECT_EQ(6U, ConstRef.getLength()); 307 EXPECT_EQ(5U, Dropped.getLength()); 308 309 // If we drop non-zero bytes from the back, we should stop tracking the 310 // length. 311 Dropped = Dropped.drop_back(1); 312 EXPECT_THAT_ERROR(Writer.writeCString(Strings[3]), Succeeded()); 313 EXPECT_EQ(8U, ConstRef.getLength()); 314 EXPECT_EQ(4U, Dropped.getLength()); 315 } 316 317 TEST_F(BinaryStreamTest, DropOperations) { 318 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5, 4, 3, 2, 1}; 319 auto RefData = makeArrayRef(InputData); 320 initializeInput(InputData, 1); 321 322 ArrayRef<uint8_t> Result; 323 BinaryStreamRef Original(InputData, support::little); 324 ASSERT_EQ(InputData.size(), Original.getLength()); 325 326 EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result), 327 Succeeded()); 328 EXPECT_EQ(RefData, Result); 329 330 auto Dropped = Original.drop_front(2); 331 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 332 Succeeded()); 333 EXPECT_EQ(RefData.drop_front(2), Result); 334 335 Dropped = Original.drop_back(2); 336 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 337 Succeeded()); 338 EXPECT_EQ(RefData.drop_back(2), Result); 339 340 Dropped = Original.keep_front(2); 341 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 342 Succeeded()); 343 EXPECT_EQ(RefData.take_front(2), Result); 344 345 Dropped = Original.keep_back(2); 346 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 347 Succeeded()); 348 EXPECT_EQ(RefData.take_back(2), Result); 349 350 Dropped = Original.drop_symmetric(2); 351 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 352 Succeeded()); 353 EXPECT_EQ(RefData.drop_front(2).drop_back(2), Result); 354 } 355 356 // Test that we can write to a BinaryStream without a StreamWriter. 357 TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) { 358 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'}; 359 initializeInput(InputData, 1); 360 initializeOutput(InputData.size(), 1); 361 362 // For every combination of input stream and output stream. 363 for (auto &Stream : Streams) { 364 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 365 366 // 1. Try two reads that are supposed to work. One from offset 0, and one 367 // from the middle. 368 uint32_t Offsets[] = {0, 3}; 369 for (auto Offset : Offsets) { 370 uint32_t ExpectedSize = Stream.Input->getLength() - Offset; 371 372 // Read everything from Offset until the end of the input data. 373 ArrayRef<uint8_t> Data; 374 ASSERT_THAT_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data), 375 Succeeded()); 376 ASSERT_EQ(ExpectedSize, Data.size()); 377 378 // Then write it to the destination. 379 ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded()); 380 381 // Then we read back what we wrote, it should match the corresponding 382 // slice of the original input data. 383 ArrayRef<uint8_t> Data2; 384 ASSERT_THAT_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2), 385 Succeeded()); 386 EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2); 387 } 388 389 std::vector<uint8_t> BigData = {0, 1, 2, 3, 4}; 390 // 2. If the write is too big, it should fail. 391 EXPECT_THAT_ERROR(Stream.Output->writeBytes(3, BigData), Failed()); 392 } 393 } 394 395 TEST_F(BinaryStreamTest, AppendingStream) { 396 AppendingBinaryByteStream Stream(llvm::support::little); 397 EXPECT_EQ(0U, Stream.getLength()); 398 399 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', 'T', 'e', 's', 't'}; 400 auto Test = makeArrayRef(InputData).take_front(4); 401 // Writing past the end of the stream is an error. 402 EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Failed()); 403 404 // Writing exactly at the end of the stream is ok. 405 EXPECT_THAT_ERROR(Stream.writeBytes(0, Test), Succeeded()); 406 EXPECT_EQ(Test, Stream.data()); 407 408 // And now that the end of the stream is where we couldn't write before, now 409 // we can write. 410 EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Succeeded()); 411 EXPECT_EQ(MutableArrayRef<uint8_t>(InputData), Stream.data()); 412 } 413 414 // Test that FixedStreamArray works correctly. 415 TEST_F(BinaryStreamTest, FixedStreamArray) { 416 std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823}; 417 ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()), 418 Ints.size() * sizeof(uint32_t)); 419 420 initializeInput(IntBytes, alignof(uint32_t)); 421 422 for (auto &Stream : Streams) { 423 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 424 425 FixedStreamArray<uint32_t> Array(*Stream.Input); 426 auto Iter = Array.begin(); 427 ASSERT_EQ(Ints[0], *Iter++); 428 ASSERT_EQ(Ints[1], *Iter++); 429 ASSERT_EQ(Ints[2], *Iter++); 430 ASSERT_EQ(Ints[3], *Iter++); 431 ASSERT_EQ(Array.end(), Iter); 432 } 433 } 434 435 // Ensure FixedStreamArrayIterator::operator-> works. 436 // Added for coverage of r302257. 437 TEST_F(BinaryStreamTest, FixedStreamArrayIteratorArrow) { 438 std::vector<std::pair<uint32_t, uint32_t>> Pairs = {{867, 5309}, {555, 1212}}; 439 ArrayRef<uint8_t> PairBytes(reinterpret_cast<uint8_t *>(Pairs.data()), 440 Pairs.size() * sizeof(Pairs[0])); 441 442 initializeInput(PairBytes, alignof(uint32_t)); 443 444 for (auto &Stream : Streams) { 445 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 446 447 const FixedStreamArray<std::pair<uint32_t, uint32_t>> Array(*Stream.Input); 448 auto Iter = Array.begin(); 449 ASSERT_EQ(Pairs[0].first, Iter->first); 450 ASSERT_EQ(Pairs[0].second, Iter->second); 451 ++Iter; 452 ASSERT_EQ(Pairs[1].first, Iter->first); 453 ASSERT_EQ(Pairs[1].second, Iter->second); 454 ++Iter; 455 ASSERT_EQ(Array.end(), Iter); 456 } 457 } 458 459 // Test that VarStreamArray works correctly. 460 TEST_F(BinaryStreamTest, VarStreamArray) { 461 StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super " 462 "Extra Longest Test Of All"); 463 ArrayRef<uint8_t> StringBytes( 464 reinterpret_cast<const uint8_t *>(Strings.data()), Strings.size()); 465 initializeInput(StringBytes, 1); 466 467 struct StringExtractor { 468 public: 469 Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) { 470 if (Index == 0) 471 Len = strlen("1. Test"); 472 else if (Index == 1) 473 Len = strlen("2. Longer Test"); 474 else if (Index == 2) 475 Len = strlen("3. Really Long Test"); 476 else 477 Len = strlen("4. Super Extra Longest Test Of All"); 478 ArrayRef<uint8_t> Bytes; 479 if (auto EC = Stream.readBytes(0, Len, Bytes)) 480 return EC; 481 Item = 482 StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 483 ++Index; 484 return Error::success(); 485 } 486 487 uint32_t Index = 0; 488 }; 489 490 for (auto &Stream : Streams) { 491 VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input); 492 auto Iter = Array.begin(); 493 ASSERT_EQ("1. Test", *Iter++); 494 ASSERT_EQ("2. Longer Test", *Iter++); 495 ASSERT_EQ("3. Really Long Test", *Iter++); 496 ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++); 497 ASSERT_EQ(Array.end(), Iter); 498 } 499 } 500 501 TEST_F(BinaryStreamTest, StreamReaderBounds) { 502 std::vector<uint8_t> Bytes; 503 504 initializeInput(Bytes, 1); 505 for (auto &Stream : Streams) { 506 StringRef S; 507 BinaryStreamReader Reader(*Stream.Input); 508 EXPECT_EQ(0U, Reader.bytesRemaining()); 509 EXPECT_THAT_ERROR(Reader.readFixedString(S, 1), Failed()); 510 } 511 512 Bytes.resize(5); 513 initializeInput(Bytes, 1); 514 for (auto &Stream : Streams) { 515 StringRef S; 516 BinaryStreamReader Reader(*Stream.Input); 517 EXPECT_EQ(Bytes.size(), Reader.bytesRemaining()); 518 EXPECT_THAT_ERROR(Reader.readFixedString(S, 5), Succeeded()); 519 EXPECT_THAT_ERROR(Reader.readFixedString(S, 6), Failed()); 520 } 521 } 522 523 TEST_F(BinaryStreamTest, StreamReaderIntegers) { 524 support::ulittle64_t Little{908234}; 525 support::ubig32_t Big{28907823}; 526 short NS = 2897; 527 int NI = -89723; 528 unsigned long NUL = 902309023UL; 529 constexpr uint32_t Size = 530 sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL); 531 532 initializeOutput(Size, alignof(support::ulittle64_t)); 533 initializeInputFromOutput(alignof(support::ulittle64_t)); 534 535 for (auto &Stream : Streams) { 536 BinaryStreamWriter Writer(*Stream.Output); 537 ASSERT_THAT_ERROR(Writer.writeObject(Little), Succeeded()); 538 ASSERT_THAT_ERROR(Writer.writeObject(Big), Succeeded()); 539 ASSERT_THAT_ERROR(Writer.writeInteger(NS), Succeeded()); 540 ASSERT_THAT_ERROR(Writer.writeInteger(NI), Succeeded()); 541 ASSERT_THAT_ERROR(Writer.writeInteger(NUL), Succeeded()); 542 543 const support::ulittle64_t *Little2; 544 const support::ubig32_t *Big2; 545 short NS2; 546 int NI2; 547 unsigned long NUL2; 548 549 // 1. Reading fields individually. 550 BinaryStreamReader Reader(*Stream.Input); 551 ASSERT_THAT_ERROR(Reader.readObject(Little2), Succeeded()); 552 ASSERT_THAT_ERROR(Reader.readObject(Big2), Succeeded()); 553 ASSERT_THAT_ERROR(Reader.readInteger(NS2), Succeeded()); 554 ASSERT_THAT_ERROR(Reader.readInteger(NI2), Succeeded()); 555 ASSERT_THAT_ERROR(Reader.readInteger(NUL2), Succeeded()); 556 ASSERT_EQ(0U, Reader.bytesRemaining()); 557 558 EXPECT_EQ(Little, *Little2); 559 EXPECT_EQ(Big, *Big2); 560 EXPECT_EQ(NS, NS2); 561 EXPECT_EQ(NI, NI2); 562 EXPECT_EQ(NUL, NUL2); 563 } 564 } 565 566 TEST_F(BinaryStreamTest, StreamReaderIntegerArray) { 567 // 1. Arrays of integers 568 std::vector<int> Ints = {1, 2, 3, 4, 5}; 569 ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]), 570 Ints.size() * sizeof(int)); 571 572 initializeInput(IntBytes, alignof(int)); 573 for (auto &Stream : Streams) { 574 BinaryStreamReader Reader(*Stream.Input); 575 ArrayRef<int> IntsRef; 576 ASSERT_THAT_ERROR(Reader.readArray(IntsRef, Ints.size()), Succeeded()); 577 ASSERT_EQ(0U, Reader.bytesRemaining()); 578 EXPECT_EQ(makeArrayRef(Ints), IntsRef); 579 580 Reader.setOffset(0); 581 FixedStreamArray<int> FixedIntsRef; 582 ASSERT_THAT_ERROR(Reader.readArray(FixedIntsRef, Ints.size()), Succeeded()); 583 ASSERT_EQ(0U, Reader.bytesRemaining()); 584 ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end())); 585 } 586 } 587 588 TEST_F(BinaryStreamTest, StreamReaderEnum) { 589 enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 }; 590 591 std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo}; 592 593 initializeOutput(Enums.size() * sizeof(MyEnum), alignof(MyEnum)); 594 initializeInputFromOutput(alignof(MyEnum)); 595 for (auto &Stream : Streams) { 596 BinaryStreamWriter Writer(*Stream.Output); 597 for (auto Value : Enums) 598 ASSERT_THAT_ERROR(Writer.writeEnum(Value), Succeeded()); 599 600 BinaryStreamReader Reader(*Stream.Input); 601 602 FixedStreamArray<MyEnum> FSA; 603 604 for (size_t I = 0; I < Enums.size(); ++I) { 605 MyEnum Value; 606 ASSERT_THAT_ERROR(Reader.readEnum(Value), Succeeded()); 607 EXPECT_EQ(Enums[I], Value); 608 } 609 ASSERT_EQ(0U, Reader.bytesRemaining()); 610 } 611 } 612 613 TEST_F(BinaryStreamTest, StreamReaderULEB128) { 614 std::vector<uint64_t> TestValues = { 615 0, // Zero 616 0x7F, // One byte 617 0xFF, // One byte, all-ones 618 0xAAAA, // Two bytes 619 0xAAAAAAAA, // Four bytes 620 0xAAAAAAAAAAAAAAAA, // Eight bytes 621 0xffffffffffffffff // Eight bytess, all-ones 622 }; 623 624 // Conservatively assume a 10-byte encoding for each of our LEB128s, with no 625 // alignment requirement. 626 initializeOutput(10 * TestValues.size(), 1); 627 initializeInputFromOutput(1); 628 629 for (auto &Stream : Streams) { 630 // Write fields. 631 BinaryStreamWriter Writer(*Stream.Output); 632 for (const auto &Value : TestValues) 633 ASSERT_THAT_ERROR(Writer.writeULEB128(Value), Succeeded()); 634 635 // Read fields. 636 BinaryStreamReader Reader(*Stream.Input); 637 std::vector<uint64_t> Results; 638 Results.resize(TestValues.size()); 639 for (unsigned I = 0; I != TestValues.size(); ++I) 640 ASSERT_THAT_ERROR(Reader.readULEB128(Results[I]), Succeeded()); 641 642 for (unsigned I = 0; I != TestValues.size(); ++I) 643 EXPECT_EQ(TestValues[I], Results[I]); 644 } 645 } 646 647 TEST_F(BinaryStreamTest, StreamReaderSLEB128) { 648 std::vector<int64_t> TestValues = { 649 0, // Zero 650 0x7F, // One byte 651 -0x7F, // One byte, negative 652 0xFF, // One byte, all-ones 653 0xAAAA, // Two bytes 654 -0xAAAA, // Two bytes, negative 655 0xAAAAAAAA, // Four bytes 656 -0xAAAAAAAA, // Four bytes, negative 657 0x2AAAAAAAAAAAAAAA, // Eight bytes 658 -0x7ffffffffffffff // Eight bytess, negative 659 }; 660 661 // Conservatively assume a 10-byte encoding for each of our LEB128s, with no 662 // alignment requirement. 663 initializeOutput(10 * TestValues.size(), 1); 664 initializeInputFromOutput(1); 665 666 for (auto &Stream : Streams) { 667 // Write fields. 668 BinaryStreamWriter Writer(*Stream.Output); 669 for (const auto &Value : TestValues) 670 ASSERT_THAT_ERROR(Writer.writeSLEB128(Value), Succeeded()); 671 672 // Read fields. 673 BinaryStreamReader Reader(*Stream.Input); 674 std::vector<int64_t> Results; 675 Results.resize(TestValues.size()); 676 for (unsigned I = 0; I != TestValues.size(); ++I) 677 ASSERT_THAT_ERROR(Reader.readSLEB128(Results[I]), Succeeded()); 678 679 for (unsigned I = 0; I != TestValues.size(); ++I) 680 EXPECT_EQ(TestValues[I], Results[I]); 681 } 682 } 683 684 TEST_F(BinaryStreamTest, StreamReaderObject) { 685 struct Foo { 686 int X; 687 double Y; 688 char Z; 689 690 bool operator==(const Foo &Other) const { 691 return X == Other.X && Y == Other.Y && Z == Other.Z; 692 } 693 }; 694 695 std::vector<Foo> Foos; 696 Foos.push_back({-42, 42.42, 42}); 697 Foos.push_back({100, 3.1415, static_cast<char>(-89)}); 698 Foos.push_back({200, 2.718, static_cast<char>(-12) }); 699 700 const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]); 701 702 initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo)); 703 704 for (auto &Stream : Streams) { 705 // 1. Reading object pointers. 706 BinaryStreamReader Reader(*Stream.Input); 707 const Foo *FPtrOut = nullptr; 708 const Foo *GPtrOut = nullptr; 709 const Foo *HPtrOut = nullptr; 710 ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded()); 711 ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded()); 712 ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded()); 713 EXPECT_EQ(0U, Reader.bytesRemaining()); 714 EXPECT_EQ(Foos[0], *FPtrOut); 715 EXPECT_EQ(Foos[1], *GPtrOut); 716 EXPECT_EQ(Foos[2], *HPtrOut); 717 } 718 } 719 720 TEST_F(BinaryStreamTest, StreamReaderStrings) { 721 std::vector<uint8_t> Bytes = {'O', 'n', 'e', '\0', 'T', 'w', 'o', 722 '\0', 'T', 'h', 'r', 'e', 'e', '\0', 723 'F', 'o', 'u', 'r', '\0'}; 724 initializeInput(Bytes, 1); 725 726 for (auto &Stream : Streams) { 727 BinaryStreamReader Reader(*Stream.Input); 728 729 StringRef S1; 730 StringRef S2; 731 StringRef S3; 732 StringRef S4; 733 ASSERT_THAT_ERROR(Reader.readCString(S1), Succeeded()); 734 ASSERT_THAT_ERROR(Reader.readCString(S2), Succeeded()); 735 ASSERT_THAT_ERROR(Reader.readCString(S3), Succeeded()); 736 ASSERT_THAT_ERROR(Reader.readCString(S4), Succeeded()); 737 ASSERT_EQ(0U, Reader.bytesRemaining()); 738 739 EXPECT_EQ("One", S1); 740 EXPECT_EQ("Two", S2); 741 EXPECT_EQ("Three", S3); 742 EXPECT_EQ("Four", S4); 743 744 S1 = S2 = S3 = S4 = ""; 745 Reader.setOffset(0); 746 ASSERT_THAT_ERROR(Reader.readFixedString(S1, 3), Succeeded()); 747 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 748 ASSERT_THAT_ERROR(Reader.readFixedString(S2, 3), Succeeded()); 749 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 750 ASSERT_THAT_ERROR(Reader.readFixedString(S3, 5), Succeeded()); 751 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 752 ASSERT_THAT_ERROR(Reader.readFixedString(S4, 4), Succeeded()); 753 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 754 ASSERT_EQ(0U, Reader.bytesRemaining()); 755 756 EXPECT_EQ("One", S1); 757 EXPECT_EQ("Two", S2); 758 EXPECT_EQ("Three", S3); 759 EXPECT_EQ("Four", S4); 760 } 761 } 762 763 TEST_F(BinaryStreamTest, StreamWriterBounds) { 764 initializeOutput(5, 1); 765 766 for (auto &Stream : Streams) { 767 BinaryStreamWriter Writer(*Stream.Output); 768 769 // 1. Can write a string that exactly fills the buffer. 770 EXPECT_EQ(5U, Writer.bytesRemaining()); 771 EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded()); 772 EXPECT_EQ(0U, Writer.bytesRemaining()); 773 774 // 2. Can write an empty string even when you're full 775 EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded()); 776 EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed()); 777 778 // 3. Can't write a string that is one character too long. 779 Writer.setOffset(0); 780 EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed()); 781 } 782 } 783 784 TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) { 785 // 3. Arrays of integers 786 std::vector<int> SourceInts = {1, 2, 3, 4, 5}; 787 ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]), 788 SourceInts.size() * sizeof(int)); 789 790 initializeInput(SourceBytes, alignof(int)); 791 initializeOutputFromInput(alignof(int)); 792 793 for (auto &Stream : Streams) { 794 BinaryStreamReader Reader(*Stream.Input); 795 BinaryStreamWriter Writer(*Stream.Output); 796 ArrayRef<int> Ints; 797 ArrayRef<int> Ints2; 798 // First read them, then write them, then read them back. 799 ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded()); 800 ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded()); 801 802 BinaryStreamReader ReaderBacker(*Stream.Output); 803 ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()), 804 Succeeded()); 805 806 EXPECT_EQ(makeArrayRef(SourceInts), Ints2); 807 } 808 } 809 810 TEST_F(BinaryStreamTest, StringWriterStrings) { 811 StringRef Strings[] = {"First", "Second", "Third", "Fourth"}; 812 813 size_t Length = 0; 814 for (auto S : Strings) 815 Length += S.size() + 1; 816 initializeOutput(Length, 1); 817 initializeInputFromOutput(1); 818 819 for (auto &Stream : Streams) { 820 BinaryStreamWriter Writer(*Stream.Output); 821 for (auto S : Strings) 822 ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded()); 823 std::vector<StringRef> InStrings; 824 BinaryStreamReader Reader(*Stream.Input); 825 while (!Reader.empty()) { 826 StringRef S; 827 ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded()); 828 InStrings.push_back(S); 829 } 830 EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings)); 831 } 832 } 833 834 TEST_F(BinaryStreamTest, StreamWriterAppend) { 835 StringRef Strings[] = {"First", "Second", "Third", "Fourth"}; 836 AppendingBinaryByteStream Stream(support::little); 837 BinaryStreamWriter Writer(Stream); 838 839 for (auto &Str : Strings) { 840 EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded()); 841 } 842 843 BinaryStreamReader Reader(Stream); 844 for (auto &Str : Strings) { 845 StringRef S; 846 EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded()); 847 EXPECT_EQ(Str, S); 848 } 849 } 850 } 851 852 namespace { 853 struct BinaryItemStreamObject { 854 explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {} 855 856 ArrayRef<uint8_t> Bytes; 857 }; 858 } 859 860 namespace llvm { 861 template <> struct BinaryItemTraits<BinaryItemStreamObject> { 862 static size_t length(const BinaryItemStreamObject &Item) { 863 return Item.Bytes.size(); 864 } 865 866 static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) { 867 return Item.Bytes; 868 } 869 }; 870 } 871 872 namespace { 873 874 TEST_F(BinaryStreamTest, BinaryItemStream) { 875 std::vector<BinaryItemStreamObject> Objects; 876 877 struct Foo { 878 int X; 879 double Y; 880 }; 881 std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}}; 882 BumpPtrAllocator Allocator; 883 for (const auto &F : Foos) { 884 uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo), 885 alignof(Foo))); 886 MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo)); 887 MutableBinaryByteStream Stream(Buffer, llvm::support::big); 888 BinaryStreamWriter Writer(Stream); 889 ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded()); 890 Objects.push_back(BinaryItemStreamObject(Buffer)); 891 } 892 893 BinaryItemStream<BinaryItemStreamObject> ItemStream(big); 894 ItemStream.setItems(Objects); 895 BinaryStreamReader Reader(ItemStream); 896 897 for (const auto &F : Foos) { 898 const Foo *F2; 899 ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded()); 900 901 EXPECT_EQ(F.X, F2->X); 902 EXPECT_DOUBLE_EQ(F.Y, F2->Y); 903 } 904 } 905 906 } // end anonymous namespace 907