1 //===- llvm/unittest/Support/BinaryStreamTest.cpp -------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/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"
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:
BrokenStream(MutableArrayRef<uint8_t> Data,endianness Endian,uint32_t Align)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
getEndian() const33 endianness getEndian() const override { return Endian; }
34
readBytes(uint32_t Offset,uint32_t Size,ArrayRef<uint8_t> & Buffer)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
readLongestContiguousChunk(uint32_t Offset,ArrayRef<uint8_t> & Buffer)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
getLength()63 uint32_t getLength() override { return Data.size(); }
64
writeBytes(uint32_t Offset,ArrayRef<uint8_t> SrcData)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 }
commit()84 Error commit() override { return Error::success(); }
85
86 private:
startIndex(uint32_t Offset) const87 uint32_t startIndex(uint32_t Offset) const {
88 return (Offset + PartitionIndex) % Data.size();
89 }
90
endIndex(uint32_t Offset,uint32_t Size) const91 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:
BinaryStreamTest()113 BinaryStreamTest() {}
114
SetUp()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
initializeInput(ArrayRef<uint8_t> Input,uint32_t Align)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 std::make_unique<BinaryByteStream>(InputData, Endians[I]);
149 auto InBrokenStream = std::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
initializeOutput(uint32_t Size,uint32_t Align)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 std::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
164 Streams[I * 2 + 1].Output = std::make_unique<BrokenStream>(
165 BrokenOutputData, Endians[I], Align);
166 }
167 }
168
initializeOutputFromInput(uint32_t 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);
175 }
176 }
177
initializeInputFromOutput(uint32_t 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);
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.
TEST_F(BinaryStreamTest,BinaryByteStreamBounds)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
TEST_F(BinaryStreamTest,StreamRefBounds)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
TEST_F(BinaryStreamTest,StreamRefDynamicSize)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
TEST_F(BinaryStreamTest,DropOperations)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.
TEST_F(BinaryStreamTest,MutableBinaryByteStreamBounds)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
TEST_F(BinaryStreamTest,AppendingStream)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.
TEST_F(BinaryStreamTest,FixedStreamArray)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.
TEST_F(BinaryStreamTest,FixedStreamArrayIteratorArrow)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.
TEST_F(BinaryStreamTest,VarStreamArray)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
TEST_F(BinaryStreamTest,StreamReaderBounds)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
TEST_F(BinaryStreamTest,StreamReaderIntegers)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
TEST_F(BinaryStreamTest,StreamReaderIntegerArray)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
TEST_F(BinaryStreamTest,StreamReaderEnum)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
TEST_F(BinaryStreamTest,StreamReaderULEB128)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
623 };
624
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);
629
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());
635
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());
642
643 for (unsigned I = 0; I != TestValues.size(); ++I)
644 EXPECT_EQ(TestValues[I], Results[I]);
645 }
646 }
647
TEST_F(BinaryStreamTest,StreamReaderSLEB128)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
660 };
661
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);
666
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());
672
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());
679
680 for (unsigned I = 0; I != TestValues.size(); ++I)
681 EXPECT_EQ(TestValues[I], Results[I]);
682 }
683 }
684
TEST_F(BinaryStreamTest,StreamReaderObject)685 TEST_F(BinaryStreamTest, StreamReaderObject) {
686 struct Foo {
687 int X;
688 double Y;
689 char Z;
690
691 bool operator==(const Foo &Other) const {
692 return X == Other.X && Y == Other.Y && Z == Other.Z;
693 }
694 };
695
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) });
700
701 const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
702
703 initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo));
704
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);
718 }
719 }
720
TEST_F(BinaryStreamTest,StreamReaderStrings)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);
726
727 for (auto &Stream : Streams) {
728 BinaryStreamReader Reader(*Stream.Input);
729
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());
739
740 EXPECT_EQ("One", S1);
741 EXPECT_EQ("Two", S2);
742 EXPECT_EQ("Three", S3);
743 EXPECT_EQ("Four", S4);
744
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());
756
757 EXPECT_EQ("One", S1);
758 EXPECT_EQ("Two", S2);
759 EXPECT_EQ("Three", S3);
760 EXPECT_EQ("Four", S4);
761 }
762 }
763
TEST_F(BinaryStreamTest,StreamWriterBounds)764 TEST_F(BinaryStreamTest, StreamWriterBounds) {
765 initializeOutput(5, 1);
766
767 for (auto &Stream : Streams) {
768 BinaryStreamWriter Writer(*Stream.Output);
769
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());
774
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());
778
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());
782 }
783 }
784
TEST_F(BinaryStreamTest,StreamWriterIntegerArrays)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));
790
791 initializeInput(SourceBytes, alignof(int));
792 initializeOutputFromInput(alignof(int));
793
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());
802
803 BinaryStreamReader ReaderBacker(*Stream.Output);
804 ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()),
805 Succeeded());
806
807 EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
808 }
809 }
810
TEST_F(BinaryStreamTest,StringWriterStrings)811 TEST_F(BinaryStreamTest, StringWriterStrings) {
812 StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
813
814 size_t Length = 0;
815 for (auto S : Strings)
816 Length += S.size() + 1;
817 initializeOutput(Length, 1);
818 initializeInputFromOutput(1);
819
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);
830 }
831 EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
832 }
833 }
834
TEST_F(BinaryStreamTest,StreamWriterAppend)835 TEST_F(BinaryStreamTest, StreamWriterAppend) {
836 StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
837 AppendingBinaryByteStream Stream(support::little);
838 BinaryStreamWriter Writer(Stream);
839
840 for (auto &Str : Strings) {
841 EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded());
842 }
843
844 BinaryStreamReader Reader(Stream);
845 for (auto &Str : Strings) {
846 StringRef S;
847 EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded());
848 EXPECT_EQ(Str, S);
849 }
850 }
851 }
852
853 namespace {
854 struct BinaryItemStreamObject {
BinaryItemStreamObject__anonfcd284590211::BinaryItemStreamObject855 explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {}
856
857 ArrayRef<uint8_t> Bytes;
858 };
859 }
860
861 namespace llvm {
862 template <> struct BinaryItemTraits<BinaryItemStreamObject> {
lengthllvm::BinaryItemTraits863 static size_t length(const BinaryItemStreamObject &Item) {
864 return Item.Bytes.size();
865 }
866
bytesllvm::BinaryItemTraits867 static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) {
868 return Item.Bytes;
869 }
870 };
871 }
872
873 namespace {
874
TEST_F(BinaryStreamTest,BinaryItemStream)875 TEST_F(BinaryStreamTest, BinaryItemStream) {
876 std::vector<BinaryItemStreamObject> Objects;
877
878 struct Foo {
879 int X;
880 double Y;
881 };
882 std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
883 BumpPtrAllocator Allocator;
884 for (const auto &F : Foos) {
885 uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
886 alignof(Foo)));
887 MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
888 MutableBinaryByteStream Stream(Buffer, llvm::support::big);
889 BinaryStreamWriter Writer(Stream);
890 ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded());
891 Objects.push_back(BinaryItemStreamObject(Buffer));
892 }
893
894 BinaryItemStream<BinaryItemStreamObject> ItemStream(big);
895 ItemStream.setItems(Objects);
896 BinaryStreamReader Reader(ItemStream);
897
898 for (const auto &F : Foos) {
899 const Foo *F2;
900 ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded());
901
902 EXPECT_EQ(F.X, F2->X);
903 EXPECT_DOUBLE_EQ(F.Y, F2->Y);
904 }
905 }
906
907 } // end anonymous namespace
908