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