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