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 = checkOffsetForRead(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 = checkOffsetForRead(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 = checkOffsetForWrite(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, StreamRefDynamicSize) { 271 StringRef Strings[] = {"1", "2", "3", "4"}; 272 AppendingBinaryByteStream Stream(support::little); 273 274 BinaryStreamWriter Writer(Stream); 275 BinaryStreamReader Reader(Stream); 276 const uint8_t *Byte; 277 StringRef Str; 278 279 // When the stream is empty, it should report a 0 length and we should get an 280 // error trying to read even 1 byte from it. 281 BinaryStreamRef ConstRef(Stream); 282 EXPECT_EQ(0, ConstRef.getLength()); 283 EXPECT_THAT_ERROR(Reader.readObject(Byte), Failed()); 284 285 // But if we write to it, its size should increase and we should be able to 286 // read not just a byte, but the string that was written. 287 EXPECT_THAT_ERROR(Writer.writeCString(Strings[0]), Succeeded()); 288 EXPECT_EQ(2, ConstRef.getLength()); 289 EXPECT_THAT_ERROR(Reader.readObject(Byte), Succeeded()); 290 291 Reader.setOffset(0); 292 EXPECT_THAT_ERROR(Reader.readCString(Str), Succeeded()); 293 EXPECT_EQ(Str, Strings[0]); 294 295 // If we drop some bytes from the front, we should still track the length as 296 // the 297 // underlying stream grows. 298 BinaryStreamRef Dropped = ConstRef.drop_front(1); 299 EXPECT_EQ(1, Dropped.getLength()); 300 301 EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded()); 302 EXPECT_EQ(4, ConstRef.getLength()); 303 EXPECT_EQ(3, Dropped.getLength()); 304 305 // If we drop zero bytes from the back, we should continue tracking the 306 // length. 307 Dropped = Dropped.drop_back(0); 308 EXPECT_THAT_ERROR(Writer.writeCString(Strings[2]), Succeeded()); 309 EXPECT_EQ(6, ConstRef.getLength()); 310 EXPECT_EQ(5, Dropped.getLength()); 311 312 // If we drop non-zero bytes from the back, we should stop tracking the 313 // length. 314 Dropped = Dropped.drop_back(1); 315 EXPECT_THAT_ERROR(Writer.writeCString(Strings[3]), Succeeded()); 316 EXPECT_EQ(8, ConstRef.getLength()); 317 EXPECT_EQ(4, Dropped.getLength()); 318 } 319 320 TEST_F(BinaryStreamTest, DropOperations) { 321 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5, 4, 3, 2, 1}; 322 auto RefData = makeArrayRef(InputData); 323 initializeInput(InputData, 1); 324 325 ArrayRef<uint8_t> Result; 326 BinaryStreamRef Original(InputData, support::little); 327 ASSERT_EQ(InputData.size(), Original.getLength()); 328 329 EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result), 330 Succeeded()); 331 EXPECT_EQ(RefData, Result); 332 333 auto Dropped = Original.drop_front(2); 334 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 335 Succeeded()); 336 EXPECT_EQ(RefData.drop_front(2), Result); 337 338 Dropped = Original.drop_back(2); 339 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 340 Succeeded()); 341 EXPECT_EQ(RefData.drop_back(2), Result); 342 343 Dropped = Original.keep_front(2); 344 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 345 Succeeded()); 346 EXPECT_EQ(RefData.take_front(2), Result); 347 348 Dropped = Original.keep_back(2); 349 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 350 Succeeded()); 351 EXPECT_EQ(RefData.take_back(2), Result); 352 353 Dropped = Original.drop_symmetric(2); 354 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result), 355 Succeeded()); 356 EXPECT_EQ(RefData.drop_front(2).drop_back(2), Result); 357 } 358 359 // Test that we can write to a BinaryStream without a StreamWriter. 360 TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) { 361 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'}; 362 initializeInput(InputData, 1); 363 initializeOutput(InputData.size(), 1); 364 365 // For every combination of input stream and output stream. 366 for (auto &Stream : Streams) { 367 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 368 369 // 1. Try two reads that are supposed to work. One from offset 0, and one 370 // from the middle. 371 uint32_t Offsets[] = {0, 3}; 372 for (auto Offset : Offsets) { 373 uint32_t ExpectedSize = Stream.Input->getLength() - Offset; 374 375 // Read everything from Offset until the end of the input data. 376 ArrayRef<uint8_t> Data; 377 ASSERT_THAT_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data), 378 Succeeded()); 379 ASSERT_EQ(ExpectedSize, Data.size()); 380 381 // Then write it to the destination. 382 ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded()); 383 384 // Then we read back what we wrote, it should match the corresponding 385 // slice of the original input data. 386 ArrayRef<uint8_t> Data2; 387 ASSERT_THAT_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2), 388 Succeeded()); 389 EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2); 390 } 391 392 std::vector<uint8_t> BigData = {0, 1, 2, 3, 4}; 393 // 2. If the write is too big, it should fail. 394 EXPECT_THAT_ERROR(Stream.Output->writeBytes(3, BigData), Failed()); 395 } 396 } 397 398 TEST_F(BinaryStreamTest, AppendingStream) { 399 AppendingBinaryByteStream Stream(llvm::support::little); 400 EXPECT_EQ(0, Stream.getLength()); 401 402 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', 'T', 'e', 's', 't'}; 403 auto Test = makeArrayRef(InputData).take_front(4); 404 // Writing past the end of the stream is an error. 405 EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Failed()); 406 407 // Writing exactly at the end of the stream is ok. 408 EXPECT_THAT_ERROR(Stream.writeBytes(0, Test), Succeeded()); 409 EXPECT_EQ(Test, Stream.data()); 410 411 // And now that the end of the stream is where we couldn't write before, now 412 // we can write. 413 EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Succeeded()); 414 EXPECT_EQ(MutableArrayRef<uint8_t>(InputData), Stream.data()); 415 } 416 417 // Test that FixedStreamArray works correctly. 418 TEST_F(BinaryStreamTest, FixedStreamArray) { 419 std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823}; 420 ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()), 421 Ints.size() * sizeof(uint32_t)); 422 423 initializeInput(IntBytes, alignof(uint32_t)); 424 425 for (auto &Stream : Streams) { 426 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 427 428 FixedStreamArray<uint32_t> Array(*Stream.Input); 429 auto Iter = Array.begin(); 430 ASSERT_EQ(Ints[0], *Iter++); 431 ASSERT_EQ(Ints[1], *Iter++); 432 ASSERT_EQ(Ints[2], *Iter++); 433 ASSERT_EQ(Ints[3], *Iter++); 434 ASSERT_EQ(Array.end(), Iter); 435 } 436 } 437 438 // Ensure FixedStreamArrayIterator::operator-> works. 439 // Added for coverage of r302257. 440 TEST_F(BinaryStreamTest, FixedStreamArrayIteratorArrow) { 441 std::vector<std::pair<uint32_t, uint32_t>> Pairs = {{867, 5309}, {555, 1212}}; 442 ArrayRef<uint8_t> PairBytes(reinterpret_cast<uint8_t *>(Pairs.data()), 443 Pairs.size() * sizeof(Pairs[0])); 444 445 initializeInput(PairBytes, alignof(uint32_t)); 446 447 for (auto &Stream : Streams) { 448 ASSERT_EQ(InputData.size(), Stream.Input->getLength()); 449 450 const FixedStreamArray<std::pair<uint32_t, uint32_t>> Array(*Stream.Input); 451 auto Iter = Array.begin(); 452 ASSERT_EQ(Pairs[0].first, Iter->first); 453 ASSERT_EQ(Pairs[0].second, Iter->second); 454 ++Iter; 455 ASSERT_EQ(Pairs[1].first, Iter->first); 456 ASSERT_EQ(Pairs[1].second, Iter->second); 457 ++Iter; 458 ASSERT_EQ(Array.end(), Iter); 459 } 460 } 461 462 // Test that VarStreamArray works correctly. 463 TEST_F(BinaryStreamTest, VarStreamArray) { 464 StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super " 465 "Extra Longest Test Of All"); 466 ArrayRef<uint8_t> StringBytes( 467 reinterpret_cast<const uint8_t *>(Strings.data()), Strings.size()); 468 initializeInput(StringBytes, 1); 469 470 struct StringExtractor { 471 public: 472 Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) { 473 if (Index == 0) 474 Len = strlen("1. Test"); 475 else if (Index == 1) 476 Len = strlen("2. Longer Test"); 477 else if (Index == 2) 478 Len = strlen("3. Really Long Test"); 479 else 480 Len = strlen("4. Super Extra Longest Test Of All"); 481 ArrayRef<uint8_t> Bytes; 482 if (auto EC = Stream.readBytes(0, Len, Bytes)) 483 return EC; 484 Item = 485 StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 486 ++Index; 487 return Error::success(); 488 } 489 490 uint32_t Index = 0; 491 }; 492 493 for (auto &Stream : Streams) { 494 VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input); 495 auto Iter = Array.begin(); 496 ASSERT_EQ("1. Test", *Iter++); 497 ASSERT_EQ("2. Longer Test", *Iter++); 498 ASSERT_EQ("3. Really Long Test", *Iter++); 499 ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++); 500 ASSERT_EQ(Array.end(), Iter); 501 } 502 } 503 504 TEST_F(BinaryStreamTest, StreamReaderBounds) { 505 std::vector<uint8_t> Bytes; 506 507 initializeInput(Bytes, 1); 508 for (auto &Stream : Streams) { 509 StringRef S; 510 BinaryStreamReader Reader(*Stream.Input); 511 EXPECT_EQ(0U, Reader.bytesRemaining()); 512 EXPECT_THAT_ERROR(Reader.readFixedString(S, 1), Failed()); 513 } 514 515 Bytes.resize(5); 516 initializeInput(Bytes, 1); 517 for (auto &Stream : Streams) { 518 StringRef S; 519 BinaryStreamReader Reader(*Stream.Input); 520 EXPECT_EQ(Bytes.size(), Reader.bytesRemaining()); 521 EXPECT_THAT_ERROR(Reader.readFixedString(S, 5), Succeeded()); 522 EXPECT_THAT_ERROR(Reader.readFixedString(S, 6), Failed()); 523 } 524 } 525 526 TEST_F(BinaryStreamTest, StreamReaderIntegers) { 527 support::ulittle64_t Little{908234}; 528 support::ubig32_t Big{28907823}; 529 short NS = 2897; 530 int NI = -89723; 531 unsigned long NUL = 902309023UL; 532 constexpr uint32_t Size = 533 sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL); 534 535 initializeOutput(Size, alignof(support::ulittle64_t)); 536 initializeInputFromOutput(alignof(support::ulittle64_t)); 537 538 for (auto &Stream : Streams) { 539 BinaryStreamWriter Writer(*Stream.Output); 540 ASSERT_THAT_ERROR(Writer.writeObject(Little), Succeeded()); 541 ASSERT_THAT_ERROR(Writer.writeObject(Big), Succeeded()); 542 ASSERT_THAT_ERROR(Writer.writeInteger(NS), Succeeded()); 543 ASSERT_THAT_ERROR(Writer.writeInteger(NI), Succeeded()); 544 ASSERT_THAT_ERROR(Writer.writeInteger(NUL), Succeeded()); 545 546 const support::ulittle64_t *Little2; 547 const support::ubig32_t *Big2; 548 short NS2; 549 int NI2; 550 unsigned long NUL2; 551 552 // 1. Reading fields individually. 553 BinaryStreamReader Reader(*Stream.Input); 554 ASSERT_THAT_ERROR(Reader.readObject(Little2), Succeeded()); 555 ASSERT_THAT_ERROR(Reader.readObject(Big2), Succeeded()); 556 ASSERT_THAT_ERROR(Reader.readInteger(NS2), Succeeded()); 557 ASSERT_THAT_ERROR(Reader.readInteger(NI2), Succeeded()); 558 ASSERT_THAT_ERROR(Reader.readInteger(NUL2), Succeeded()); 559 ASSERT_EQ(0U, Reader.bytesRemaining()); 560 561 EXPECT_EQ(Little, *Little2); 562 EXPECT_EQ(Big, *Big2); 563 EXPECT_EQ(NS, NS2); 564 EXPECT_EQ(NI, NI2); 565 EXPECT_EQ(NUL, NUL2); 566 } 567 } 568 569 TEST_F(BinaryStreamTest, StreamReaderIntegerArray) { 570 // 1. Arrays of integers 571 std::vector<int> Ints = {1, 2, 3, 4, 5}; 572 ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]), 573 Ints.size() * sizeof(int)); 574 575 initializeInput(IntBytes, alignof(int)); 576 for (auto &Stream : Streams) { 577 BinaryStreamReader Reader(*Stream.Input); 578 ArrayRef<int> IntsRef; 579 ASSERT_THAT_ERROR(Reader.readArray(IntsRef, Ints.size()), Succeeded()); 580 ASSERT_EQ(0U, Reader.bytesRemaining()); 581 EXPECT_EQ(makeArrayRef(Ints), IntsRef); 582 583 Reader.setOffset(0); 584 FixedStreamArray<int> FixedIntsRef; 585 ASSERT_THAT_ERROR(Reader.readArray(FixedIntsRef, Ints.size()), Succeeded()); 586 ASSERT_EQ(0U, Reader.bytesRemaining()); 587 ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end())); 588 } 589 } 590 591 TEST_F(BinaryStreamTest, StreamReaderEnum) { 592 enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 }; 593 594 std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo}; 595 596 initializeOutput(Enums.size() * sizeof(MyEnum), alignof(MyEnum)); 597 initializeInputFromOutput(alignof(MyEnum)); 598 for (auto &Stream : Streams) { 599 BinaryStreamWriter Writer(*Stream.Output); 600 for (auto Value : Enums) 601 ASSERT_THAT_ERROR(Writer.writeEnum(Value), Succeeded()); 602 603 BinaryStreamReader Reader(*Stream.Input); 604 605 FixedStreamArray<MyEnum> FSA; 606 607 for (size_t I = 0; I < Enums.size(); ++I) { 608 MyEnum Value; 609 ASSERT_THAT_ERROR(Reader.readEnum(Value), Succeeded()); 610 EXPECT_EQ(Enums[I], Value); 611 } 612 ASSERT_EQ(0U, Reader.bytesRemaining()); 613 } 614 } 615 616 TEST_F(BinaryStreamTest, StreamReaderObject) { 617 struct Foo { 618 int X; 619 double Y; 620 char Z; 621 622 bool operator==(const Foo &Other) const { 623 return X == Other.X && Y == Other.Y && Z == Other.Z; 624 } 625 }; 626 627 std::vector<Foo> Foos; 628 Foos.push_back({-42, 42.42, 42}); 629 Foos.push_back({100, 3.1415, static_cast<char>(-89)}); 630 Foos.push_back({200, 2.718, static_cast<char>(-12) }); 631 632 const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]); 633 634 initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo)); 635 636 for (auto &Stream : Streams) { 637 // 1. Reading object pointers. 638 BinaryStreamReader Reader(*Stream.Input); 639 const Foo *FPtrOut = nullptr; 640 const Foo *GPtrOut = nullptr; 641 const Foo *HPtrOut = nullptr; 642 ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded()); 643 ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded()); 644 ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded()); 645 EXPECT_EQ(0U, Reader.bytesRemaining()); 646 EXPECT_EQ(Foos[0], *FPtrOut); 647 EXPECT_EQ(Foos[1], *GPtrOut); 648 EXPECT_EQ(Foos[2], *HPtrOut); 649 } 650 } 651 652 TEST_F(BinaryStreamTest, StreamReaderStrings) { 653 std::vector<uint8_t> Bytes = {'O', 'n', 'e', '\0', 'T', 'w', 'o', 654 '\0', 'T', 'h', 'r', 'e', 'e', '\0', 655 'F', 'o', 'u', 'r', '\0'}; 656 initializeInput(Bytes, 1); 657 658 for (auto &Stream : Streams) { 659 BinaryStreamReader Reader(*Stream.Input); 660 661 StringRef S1; 662 StringRef S2; 663 StringRef S3; 664 StringRef S4; 665 ASSERT_THAT_ERROR(Reader.readCString(S1), Succeeded()); 666 ASSERT_THAT_ERROR(Reader.readCString(S2), Succeeded()); 667 ASSERT_THAT_ERROR(Reader.readCString(S3), Succeeded()); 668 ASSERT_THAT_ERROR(Reader.readCString(S4), Succeeded()); 669 ASSERT_EQ(0U, Reader.bytesRemaining()); 670 671 EXPECT_EQ("One", S1); 672 EXPECT_EQ("Two", S2); 673 EXPECT_EQ("Three", S3); 674 EXPECT_EQ("Four", S4); 675 676 S1 = S2 = S3 = S4 = ""; 677 Reader.setOffset(0); 678 ASSERT_THAT_ERROR(Reader.readFixedString(S1, 3), Succeeded()); 679 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 680 ASSERT_THAT_ERROR(Reader.readFixedString(S2, 3), Succeeded()); 681 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 682 ASSERT_THAT_ERROR(Reader.readFixedString(S3, 5), Succeeded()); 683 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 684 ASSERT_THAT_ERROR(Reader.readFixedString(S4, 4), Succeeded()); 685 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded()); 686 ASSERT_EQ(0U, Reader.bytesRemaining()); 687 688 EXPECT_EQ("One", S1); 689 EXPECT_EQ("Two", S2); 690 EXPECT_EQ("Three", S3); 691 EXPECT_EQ("Four", S4); 692 } 693 } 694 695 TEST_F(BinaryStreamTest, StreamWriterBounds) { 696 initializeOutput(5, 1); 697 698 for (auto &Stream : Streams) { 699 BinaryStreamWriter Writer(*Stream.Output); 700 701 // 1. Can write a string that exactly fills the buffer. 702 EXPECT_EQ(5U, Writer.bytesRemaining()); 703 EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded()); 704 EXPECT_EQ(0U, Writer.bytesRemaining()); 705 706 // 2. Can write an empty string even when you're full 707 EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded()); 708 EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed()); 709 710 // 3. Can't write a string that is one character too long. 711 Writer.setOffset(0); 712 EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed()); 713 } 714 } 715 716 TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) { 717 // 3. Arrays of integers 718 std::vector<int> SourceInts = {1, 2, 3, 4, 5}; 719 ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]), 720 SourceInts.size() * sizeof(int)); 721 722 initializeInput(SourceBytes, alignof(int)); 723 initializeOutputFromInput(alignof(int)); 724 725 for (auto &Stream : Streams) { 726 BinaryStreamReader Reader(*Stream.Input); 727 BinaryStreamWriter Writer(*Stream.Output); 728 ArrayRef<int> Ints; 729 ArrayRef<int> Ints2; 730 // First read them, then write them, then read them back. 731 ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded()); 732 ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded()); 733 734 BinaryStreamReader ReaderBacker(*Stream.Output); 735 ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()), 736 Succeeded()); 737 738 EXPECT_EQ(makeArrayRef(SourceInts), Ints2); 739 } 740 } 741 742 TEST_F(BinaryStreamTest, StringWriterStrings) { 743 StringRef Strings[] = {"First", "Second", "Third", "Fourth"}; 744 745 size_t Length = 0; 746 for (auto S : Strings) 747 Length += S.size() + 1; 748 initializeOutput(Length, 1); 749 initializeInputFromOutput(1); 750 751 for (auto &Stream : Streams) { 752 BinaryStreamWriter Writer(*Stream.Output); 753 for (auto S : Strings) 754 ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded()); 755 std::vector<StringRef> InStrings; 756 BinaryStreamReader Reader(*Stream.Input); 757 while (!Reader.empty()) { 758 StringRef S; 759 ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded()); 760 InStrings.push_back(S); 761 } 762 EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings)); 763 } 764 } 765 766 TEST_F(BinaryStreamTest, StreamWriterAppend) { 767 StringRef Strings[] = {"First", "Second", "Third", "Fourth"}; 768 AppendingBinaryByteStream Stream(support::little); 769 BinaryStreamWriter Writer(Stream); 770 771 for (auto &Str : Strings) { 772 EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded()); 773 } 774 775 BinaryStreamReader Reader(Stream); 776 for (auto &Str : Strings) { 777 StringRef S; 778 EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded()); 779 EXPECT_EQ(Str, S); 780 } 781 } 782 } 783 784 namespace { 785 struct BinaryItemStreamObject { 786 explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {} 787 788 ArrayRef<uint8_t> Bytes; 789 }; 790 } 791 792 namespace llvm { 793 template <> struct BinaryItemTraits<BinaryItemStreamObject> { 794 static size_t length(const BinaryItemStreamObject &Item) { 795 return Item.Bytes.size(); 796 } 797 798 static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) { 799 return Item.Bytes; 800 } 801 }; 802 } 803 804 namespace { 805 806 TEST_F(BinaryStreamTest, BinaryItemStream) { 807 std::vector<BinaryItemStreamObject> Objects; 808 809 struct Foo { 810 int X; 811 double Y; 812 }; 813 std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}}; 814 BumpPtrAllocator Allocator; 815 for (const auto &F : Foos) { 816 uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo), 817 alignof(Foo))); 818 MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo)); 819 MutableBinaryByteStream Stream(Buffer, llvm::support::big); 820 BinaryStreamWriter Writer(Stream); 821 ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded()); 822 Objects.push_back(BinaryItemStreamObject(Buffer)); 823 } 824 825 BinaryItemStream<BinaryItemStreamObject> ItemStream(big); 826 ItemStream.setItems(Objects); 827 BinaryStreamReader Reader(ItemStream); 828 829 for (const auto &F : Foos) { 830 const Foo *F2; 831 ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded()); 832 833 EXPECT_EQ(F.X, F2->X); 834 EXPECT_DOUBLE_EQ(F.Y, F2->Y); 835 } 836 } 837 838 } // end anonymous namespace 839