Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / Support / BinaryStreamTest.cpp
blob70cd4036fb2a665e0b0e42420221fc35067b72b8
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 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/Allocator.h"
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"
18 #include "gtest/gtest.h"
21 using namespace llvm;
22 using namespace llvm::support;
24 namespace {
26 class BrokenStream : public WritableBinaryStream {
27 public:
28 BrokenStream(MutableArrayRef<uint8_t> Data, endianness Endian, uint32_t Align)
29 : Data(Data), PartitionIndex(alignDown(Data.size() / 2, Align)),
30 Endian(Endian) {}
32 endianness getEndian() const override { return Endian; }
34 Error readBytes(uint64_t Offset, uint64_t Size,
35 ArrayRef<uint8_t> &Buffer) override {
36 if (auto EC = checkOffsetForRead(Offset, Size))
37 return EC;
38 uint64_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();
45 uint64_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 = ArrayRef<uint8_t>(Ptr, Size);
50 return Error::success();
53 Error readLongestContiguousChunk(uint64_t Offset,
54 ArrayRef<uint8_t> &Buffer) override {
55 if (auto EC = checkOffsetForRead(Offset, 1))
56 return EC;
57 uint64_t S = startIndex(Offset);
58 Buffer = Data.drop_front(S);
59 return Error::success();
62 uint64_t getLength() override { return Data.size(); }
64 Error writeBytes(uint64_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();
70 uint64_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();
78 uint64_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();
83 Error commit() override { return Error::success(); }
85 private:
86 uint64_t startIndex(uint64_t Offset) const {
87 return (Offset + PartitionIndex) % Data.size();
90 uint64_t endIndex(uint64_t Offset, uint64_t Size) const {
91 return (startIndex(Offset) + Size - 1) % Data.size();
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;
105 constexpr llvm::endianness Endians[] = {
106 llvm::endianness::big, llvm::endianness::little, llvm::endianness::native};
107 constexpr uint32_t NumEndians = std::size(Endians);
108 constexpr uint32_t NumStreams = 2 * NumEndians;
110 class BinaryStreamTest : public testing::Test {
112 public:
113 BinaryStreamTest() {}
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);
121 InputData.clear();
122 OutputData.clear();
125 protected:
126 struct StreamPair {
127 bool IsContiguous;
128 std::unique_ptr<BinaryStream> Input;
129 std::unique_ptr<WritableBinaryStream> Output;
132 void initializeInput(ArrayRef<uint8_t> Input, uint32_t Align) {
133 InputData = Input;
135 BrokenInputData.resize(InputData.size());
136 if (!Input.empty()) {
137 uint64_t PartitionIndex = alignDown(InputData.size() / 2, Align);
138 uint64_t RightBytes = InputData.size() - PartitionIndex;
139 uint64_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);
146 for (uint32_t I = 0; I < NumEndians; ++I) {
147 auto InByteStream =
148 std::make_unique<BinaryByteStream>(InputData, Endians[I]);
149 auto InBrokenStream = std::make_unique<BrokenStream>(
150 BrokenInputData, Endians[I], Align);
152 Streams[I * 2].Input = std::move(InByteStream);
153 Streams[I * 2 + 1].Input = std::move(InBrokenStream);
157 void initializeOutput(uint64_t Size, uint32_t Align) {
158 OutputData.resize(Size);
159 BrokenOutputData.resize(Size);
161 for (uint32_t I = 0; I < NumEndians; ++I) {
162 Streams[I * 2].Output =
163 std::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
164 Streams[I * 2 + 1].Output = std::make_unique<BrokenStream>(
165 BrokenOutputData, Endians[I], Align);
169 void initializeOutputFromInput(uint32_t Align) {
170 for (uint32_t I = 0; I < NumEndians; ++I) {
171 Streams[I * 2].Output =
172 std::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
173 Streams[I * 2 + 1].Output = std::make_unique<BrokenStream>(
174 BrokenInputData, Endians[I], Align);
178 void initializeInputFromOutput(uint32_t Align) {
179 for (uint32_t I = 0; I < NumEndians; ++I) {
180 Streams[I * 2].Input =
181 std::make_unique<BinaryByteStream>(OutputData, Endians[I]);
182 Streams[I * 2 + 1].Input = std::make_unique<BrokenStream>(
183 BrokenOutputData, Endians[I], Align);
187 std::vector<uint8_t> InputData;
188 std::vector<uint8_t> BrokenInputData;
190 std::vector<uint8_t> OutputData;
191 std::vector<uint8_t> BrokenOutputData;
193 std::vector<StreamPair> Streams;
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);
201 for (auto &Stream : Streams) {
202 ArrayRef<uint8_t> Buffer;
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(ArrayRef(InputData).slice(2, 1), Buffer);
208 ASSERT_THAT_ERROR(Stream.Input->readBytes(0, 4, Buffer), Succeeded());
209 EXPECT_EQ(ArrayRef(InputData).slice(0, 4), Buffer);
211 // 2. Reading past the bounds of the input should fail.
212 EXPECT_THAT_ERROR(Stream.Input->readBytes(4, 2, Buffer), Failed());
216 TEST_F(BinaryStreamTest, StreamRefBounds) {
217 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
218 initializeInput(InputData, 1);
220 for (const auto &Stream : Streams) {
221 ArrayRef<uint8_t> Buffer;
222 BinaryStreamRef Ref(*Stream.Input);
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(ArrayRef(InputData).slice(2, 1), Buffer);
229 // Reading everything from offset 2 on.
230 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
231 if (Stream.IsContiguous)
232 EXPECT_EQ(ArrayRef(InputData).slice(2), Buffer);
233 else
234 EXPECT_FALSE(Buffer.empty());
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());
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(ArrayRef(InputData).slice(3, 1), Buffer);
246 else
247 EXPECT_FALSE(Buffer.empty());
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(ArrayRef(InputData).slice(3), Buffer);
253 else
254 EXPECT_FALSE(Buffer.empty());
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());
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(ArrayRef(InputData).take_back(), Buffer);
268 TEST_F(BinaryStreamTest, StreamRefDynamicSize) {
269 StringRef Strings[] = {"1", "2", "3", "4"};
270 AppendingBinaryByteStream Stream(llvm::endianness::little);
272 BinaryStreamWriter Writer(Stream);
273 BinaryStreamReader Reader(Stream);
274 const uint8_t *Byte;
275 StringRef Str;
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());
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());
289 Reader.setOffset(0);
290 EXPECT_THAT_ERROR(Reader.readCString(Str), Succeeded());
291 EXPECT_EQ(Str, Strings[0]);
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());
299 EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded());
300 EXPECT_EQ(4U, ConstRef.getLength());
301 EXPECT_EQ(3U, Dropped.getLength());
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());
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());
318 TEST_F(BinaryStreamTest, DropOperations) {
319 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5, 4, 3, 2, 1};
320 auto RefData = ArrayRef(InputData);
321 initializeInput(InputData, 1);
323 ArrayRef<uint8_t> Result;
324 BinaryStreamRef Original(InputData, llvm::endianness::little);
325 ASSERT_EQ(InputData.size(), Original.getLength());
327 EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result),
328 Succeeded());
329 EXPECT_EQ(RefData, Result);
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);
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);
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);
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);
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);
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);
363 // For every combination of input stream and output stream.
364 for (auto &Stream : Streams) {
365 ASSERT_EQ(InputData.size(), Stream.Input->getLength());
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 uint64_t ExpectedSize = Stream.Input->getLength() - Offset;
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());
379 // Then write it to the destination.
380 ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded());
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(ArrayRef(InputData).drop_front(Offset), Data2);
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());
396 TEST_F(BinaryStreamTest, AppendingStream) {
397 AppendingBinaryByteStream Stream(llvm::endianness::little);
398 EXPECT_EQ(0U, Stream.getLength());
400 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', 'T', 'e', 's', 't'};
401 auto Test = ArrayRef(InputData).take_front(4);
402 // Writing past the end of the stream is an error.
403 EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Failed());
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());
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());
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));
421 initializeInput(IntBytes, alignof(uint32_t));
423 for (auto &Stream : Streams) {
424 ASSERT_EQ(InputData.size(), Stream.Input->getLength());
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);
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]));
443 initializeInput(PairBytes, alignof(uint32_t));
445 for (auto &Stream : Streams) {
446 ASSERT_EQ(InputData.size(), Stream.Input->getLength());
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);
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);
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();
488 uint32_t Index = 0;
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);
502 TEST_F(BinaryStreamTest, StreamReaderBounds) {
503 std::vector<uint8_t> Bytes;
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());
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());
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);
533 initializeOutput(Size, alignof(support::ulittle64_t));
534 initializeInputFromOutput(alignof(support::ulittle64_t));
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());
544 const support::ulittle64_t *Little2;
545 const support::ubig32_t *Big2;
546 short NS2;
547 int NI2;
548 unsigned long NUL2;
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());
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);
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));
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(ArrayRef(Ints), IntsRef);
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()));
589 TEST_F(BinaryStreamTest, StreamReaderEnum) {
590 enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
592 std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo};
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());
601 BinaryStreamReader Reader(*Stream.Input);
603 FixedStreamArray<MyEnum> FSA;
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);
610 ASSERT_EQ(0U, Reader.bytesRemaining());
614 TEST_F(BinaryStreamTest, StreamReaderULEB128) {
615 std::vector<uint64_t> TestValues = {
616 0, // Zero
617 0x7F, // One byte
618 0xFF, // One byte, all-ones
619 0xAAAA, // Two bytes
620 0xAAAAAAAA, // Four bytes
621 0xAAAAAAAAAAAAAAAA, // Eight bytes
622 0xffffffffffffffff // Eight bytess, all-ones
625 // Conservatively assume a 10-byte encoding for each of our LEB128s, with no
626 // alignment requirement.
627 initializeOutput(10 * TestValues.size(), 1);
628 initializeInputFromOutput(1);
630 for (auto &Stream : Streams) {
631 // Write fields.
632 BinaryStreamWriter Writer(*Stream.Output);
633 for (const auto &Value : TestValues)
634 ASSERT_THAT_ERROR(Writer.writeULEB128(Value), Succeeded());
636 // Read fields.
637 BinaryStreamReader Reader(*Stream.Input);
638 std::vector<uint64_t> Results;
639 Results.resize(TestValues.size());
640 for (unsigned I = 0; I != TestValues.size(); ++I)
641 ASSERT_THAT_ERROR(Reader.readULEB128(Results[I]), Succeeded());
643 for (unsigned I = 0; I != TestValues.size(); ++I)
644 EXPECT_EQ(TestValues[I], Results[I]);
648 TEST_F(BinaryStreamTest, StreamReaderSLEB128) {
649 std::vector<int64_t> TestValues = {
650 0, // Zero
651 0x7F, // One byte
652 -0x7F, // One byte, negative
653 0xFF, // One byte, all-ones
654 0xAAAA, // Two bytes
655 -0xAAAA, // Two bytes, negative
656 0xAAAAAAAA, // Four bytes
657 -0xAAAAAAAA, // Four bytes, negative
658 0x2AAAAAAAAAAAAAAA, // Eight bytes
659 -0x7ffffffffffffff // Eight bytess, negative
662 // Conservatively assume a 10-byte encoding for each of our LEB128s, with no
663 // alignment requirement.
664 initializeOutput(10 * TestValues.size(), 1);
665 initializeInputFromOutput(1);
667 for (auto &Stream : Streams) {
668 // Write fields.
669 BinaryStreamWriter Writer(*Stream.Output);
670 for (const auto &Value : TestValues)
671 ASSERT_THAT_ERROR(Writer.writeSLEB128(Value), Succeeded());
673 // Read fields.
674 BinaryStreamReader Reader(*Stream.Input);
675 std::vector<int64_t> Results;
676 Results.resize(TestValues.size());
677 for (unsigned I = 0; I != TestValues.size(); ++I)
678 ASSERT_THAT_ERROR(Reader.readSLEB128(Results[I]), Succeeded());
680 for (unsigned I = 0; I != TestValues.size(); ++I)
681 EXPECT_EQ(TestValues[I], Results[I]);
685 TEST_F(BinaryStreamTest, StreamReaderObject) {
686 struct Foo {
687 int X;
688 double Y;
689 char Z;
691 bool operator==(const Foo &Other) const {
692 return X == Other.X && Y == Other.Y && Z == Other.Z;
696 std::vector<Foo> Foos;
697 Foos.push_back({-42, 42.42, 42});
698 Foos.push_back({100, 3.1415, static_cast<char>(-89)});
699 Foos.push_back({200, 2.718, static_cast<char>(-12) });
701 const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
703 initializeInput(ArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo));
705 for (auto &Stream : Streams) {
706 // 1. Reading object pointers.
707 BinaryStreamReader Reader(*Stream.Input);
708 const Foo *FPtrOut = nullptr;
709 const Foo *GPtrOut = nullptr;
710 const Foo *HPtrOut = nullptr;
711 ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded());
712 ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded());
713 ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded());
714 EXPECT_EQ(0U, Reader.bytesRemaining());
715 EXPECT_EQ(Foos[0], *FPtrOut);
716 EXPECT_EQ(Foos[1], *GPtrOut);
717 EXPECT_EQ(Foos[2], *HPtrOut);
721 TEST_F(BinaryStreamTest, StreamReaderStrings) {
722 std::vector<uint8_t> Bytes = {'O', 'n', 'e', '\0', 'T', 'w', 'o',
723 '\0', 'T', 'h', 'r', 'e', 'e', '\0',
724 'F', 'o', 'u', 'r', '\0'};
725 initializeInput(Bytes, 1);
727 for (auto &Stream : Streams) {
728 BinaryStreamReader Reader(*Stream.Input);
730 StringRef S1;
731 StringRef S2;
732 StringRef S3;
733 StringRef S4;
734 ASSERT_THAT_ERROR(Reader.readCString(S1), Succeeded());
735 ASSERT_THAT_ERROR(Reader.readCString(S2), Succeeded());
736 ASSERT_THAT_ERROR(Reader.readCString(S3), Succeeded());
737 ASSERT_THAT_ERROR(Reader.readCString(S4), Succeeded());
738 ASSERT_EQ(0U, Reader.bytesRemaining());
740 EXPECT_EQ("One", S1);
741 EXPECT_EQ("Two", S2);
742 EXPECT_EQ("Three", S3);
743 EXPECT_EQ("Four", S4);
745 S1 = S2 = S3 = S4 = "";
746 Reader.setOffset(0);
747 ASSERT_THAT_ERROR(Reader.readFixedString(S1, 3), Succeeded());
748 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
749 ASSERT_THAT_ERROR(Reader.readFixedString(S2, 3), Succeeded());
750 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
751 ASSERT_THAT_ERROR(Reader.readFixedString(S3, 5), Succeeded());
752 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
753 ASSERT_THAT_ERROR(Reader.readFixedString(S4, 4), Succeeded());
754 ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
755 ASSERT_EQ(0U, Reader.bytesRemaining());
757 EXPECT_EQ("One", S1);
758 EXPECT_EQ("Two", S2);
759 EXPECT_EQ("Three", S3);
760 EXPECT_EQ("Four", S4);
764 TEST_F(BinaryStreamTest, StreamWriterBounds) {
765 initializeOutput(5, 1);
767 for (auto &Stream : Streams) {
768 BinaryStreamWriter Writer(*Stream.Output);
770 // 1. Can write a string that exactly fills the buffer.
771 EXPECT_EQ(5U, Writer.bytesRemaining());
772 EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded());
773 EXPECT_EQ(0U, Writer.bytesRemaining());
775 // 2. Can write an empty string even when you're full
776 EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded());
777 EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed());
779 // 3. Can't write a string that is one character too long.
780 Writer.setOffset(0);
781 EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed());
785 TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
786 // 3. Arrays of integers
787 std::vector<int> SourceInts = {1, 2, 3, 4, 5};
788 ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]),
789 SourceInts.size() * sizeof(int));
791 initializeInput(SourceBytes, alignof(int));
792 initializeOutputFromInput(alignof(int));
794 for (auto &Stream : Streams) {
795 BinaryStreamReader Reader(*Stream.Input);
796 BinaryStreamWriter Writer(*Stream.Output);
797 ArrayRef<int> Ints;
798 ArrayRef<int> Ints2;
799 // First read them, then write them, then read them back.
800 ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded());
801 ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded());
803 BinaryStreamReader ReaderBacker(*Stream.Output);
804 ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()),
805 Succeeded());
807 EXPECT_EQ(ArrayRef(SourceInts), Ints2);
811 TEST_F(BinaryStreamTest, StreamWriterStrings) {
812 StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
814 size_t Length = 0;
815 for (auto S : Strings)
816 Length += S.size() + 1;
817 initializeOutput(Length, 1);
818 initializeInputFromOutput(1);
820 for (auto &Stream : Streams) {
821 BinaryStreamWriter Writer(*Stream.Output);
822 for (auto S : Strings)
823 ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded());
824 std::vector<StringRef> InStrings;
825 BinaryStreamReader Reader(*Stream.Input);
826 while (!Reader.empty()) {
827 StringRef S;
828 ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded());
829 InStrings.push_back(S);
831 EXPECT_EQ(ArrayRef(Strings), ArrayRef(InStrings));
835 TEST_F(BinaryStreamTest, StreamWriterPadToAlignment) {
836 // This test may seem excessive but it is checking for past bugs and corner
837 // cases by making sure that the stream is allowed to grow and that
838 // both multiple pad chunks and single chunk extensions work.
839 AppendingBinaryByteStream Stream(llvm::endianness::little);
840 BinaryStreamWriter Writer(Stream);
842 // Offset 0: '0'
843 EXPECT_THAT_ERROR(Writer.writeInteger('0'), Succeeded());
844 // Offset 1..110: 0
845 EXPECT_THAT_ERROR(Writer.padToAlignment(111), Succeeded());
846 // Offset 111: '*'
847 EXPECT_THAT_ERROR(Writer.writeInteger('*'), Succeeded());
848 // Offset 112..120: 0
849 EXPECT_THAT_ERROR(Writer.padToAlignment(11), Succeeded());
851 BinaryStreamReader Reader(Stream);
852 char c;
853 // Offset 0
854 EXPECT_THAT_ERROR(Reader.readInteger<char>(c), Succeeded());
855 EXPECT_EQ('0', c);
856 // Offset 1..110
857 for (int i = 0; i < 110; ++i) {
858 char c;
859 EXPECT_THAT_ERROR(Reader.readInteger<char>(c), Succeeded());
860 EXPECT_EQ('\0', c);
862 // Offset 111
863 EXPECT_THAT_ERROR(Reader.readInteger<char>(c), Succeeded());
864 EXPECT_EQ('*', c);
865 // Offset 112..120
866 for (int i = 0; i < 9; ++i) {
867 char c;
868 EXPECT_THAT_ERROR(Reader.readInteger<char>(c), Succeeded());
869 EXPECT_EQ('\0', c);
872 // EOF.
873 EXPECT_THAT_ERROR(Reader.readInteger<char>(c), Failed());
876 TEST_F(BinaryStreamTest, StreamWriterAppend) {
877 StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
878 AppendingBinaryByteStream Stream(llvm::endianness::little);
879 BinaryStreamWriter Writer(Stream);
881 for (auto &Str : Strings) {
882 EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded());
885 BinaryStreamReader Reader(Stream);
886 for (auto &Str : Strings) {
887 StringRef S;
888 EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded());
889 EXPECT_EQ(Str, S);
894 namespace {
895 struct BinaryItemStreamObject {
896 explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {}
898 ArrayRef<uint8_t> Bytes;
902 namespace llvm {
903 template <> struct BinaryItemTraits<BinaryItemStreamObject> {
904 static size_t length(const BinaryItemStreamObject &Item) {
905 return Item.Bytes.size();
908 static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) {
909 return Item.Bytes;
914 namespace {
916 TEST_F(BinaryStreamTest, BinaryItemStream) {
917 std::vector<BinaryItemStreamObject> Objects;
919 struct Foo {
920 int X;
921 double Y;
923 std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
924 BumpPtrAllocator Allocator;
925 for (const auto &F : Foos) {
926 uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
927 alignof(Foo)));
928 MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
929 MutableBinaryByteStream Stream(Buffer, llvm::endianness::big);
930 BinaryStreamWriter Writer(Stream);
931 ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded());
932 Objects.push_back(BinaryItemStreamObject(Buffer));
935 BinaryItemStream<BinaryItemStreamObject> ItemStream(llvm::endianness::big);
936 ItemStream.setItems(Objects);
937 BinaryStreamReader Reader(ItemStream);
939 for (const auto &F : Foos) {
940 const Foo *F2;
941 ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded());
943 EXPECT_EQ(F.X, F2->X);
944 EXPECT_DOUBLE_EQ(F.Y, F2->Y);
948 } // end anonymous namespace