blob: ef0be1909e7d717a51c4602977128f1fe14dba27 [file] [log] [blame]
Zachary Turner081b1bc2017-03-01 17:22:36 +00001//===- 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
Zachary Turnerd9dc2822017-03-02 20:52:51 +000010#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"
Zachary Turnercb30e702017-06-14 16:41:50 +000016#include "llvm/Testing/Support/Error.h"
17
Zachary Turner081b1bc2017-03-01 17:22:36 +000018#include "gtest/gtest.h"
19
20#include <unordered_map>
Adrian McCarthyec694112017-05-16 22:11:25 +000021#include <utility>
Zachary Turner081b1bc2017-03-01 17:22:36 +000022
23using namespace llvm;
24using namespace llvm::support;
25
Zachary Turner081b1bc2017-03-01 17:22:36 +000026namespace {
27
Zachary Turner73295692017-03-01 21:30:06 +000028class BrokenStream : public WritableBinaryStream {
Zachary Turner081b1bc2017-03-01 17:22:36 +000029public:
Zachary Turner73295692017-03-01 21:30:06 +000030 BrokenStream(MutableArrayRef<uint8_t> Data, endianness Endian,
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +000031 uint32_t Align)
32 : Data(Data), PartitionIndex(alignDown(Data.size() / 2, Align)),
33 Endian(Endian) {}
Zachary Turner081b1bc2017-03-01 17:22:36 +000034
35 endianness getEndian() const override { return Endian; }
36
37 Error readBytes(uint32_t Offset, uint32_t Size,
38 ArrayRef<uint8_t> &Buffer) override {
Zachary Turner96c69852017-11-27 18:48:37 +000039 if (auto EC = checkOffsetForRead(Offset, Size))
Zachary Turner081b1bc2017-03-01 17:22:36 +000040 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 {
Zachary Turner96c69852017-11-27 18:48:37 +000058 if (auto EC = checkOffsetForRead(Offset, 1))
Zachary Turner081b1bc2017-03-01 17:22:36 +000059 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 {
Zachary Turner96c69852017-11-27 18:48:37 +000068 if (auto EC = checkOffsetForWrite(Offset, SrcData.size()))
Zachary Turner081b1bc2017-03-01 17:22:36 +000069 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
88private:
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 // -------------------------------------------------
Adrian McCarthyec694112017-05-16 22:11:25 +000099 // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N/2-1 |
Zachary Turner081b1bc2017-03-01 17:22:36 +0000100 // -------------------------------------------------
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
Zachary Turnerd9dc2822017-03-02 20:52:51 +0000108constexpr endianness Endians[] = {big, little, native};
Zachary Turner081b1bc2017-03-01 17:22:36 +0000109constexpr uint32_t NumEndians = llvm::array_lengthof(Endians);
110constexpr uint32_t NumStreams = 2 * NumEndians;
111
112class BinaryStreamTest : public testing::Test {
113
114public:
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
127protected:
128 struct StreamPair {
129 bool IsContiguous;
130 std::unique_ptr<BinaryStream> Input;
131 std::unique_ptr<WritableBinaryStream> Output;
132 };
133
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000134 void initializeInput(ArrayRef<uint8_t> Input, uint32_t Align) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000135 InputData = Input;
136
137 BrokenInputData.resize(InputData.size());
138 if (!Input.empty()) {
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000139 uint32_t PartitionIndex = alignDown(InputData.size() / 2, Align);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000140 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]);
Zachary Turner73295692017-03-01 21:30:06 +0000151 auto InBrokenStream = llvm::make_unique<BrokenStream>(
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000152 BrokenInputData, Endians[I], Align);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000153
154 Streams[I * 2].Input = std::move(InByteStream);
155 Streams[I * 2 + 1].Input = std::move(InBrokenStream);
156 }
157 }
158
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000159 void initializeOutput(uint32_t Size, uint32_t Align) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000160 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]);
Zachary Turner73295692017-03-01 21:30:06 +0000166 Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000167 BrokenOutputData, Endians[I], Align);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000168 }
169 }
170
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000171 void initializeOutputFromInput(uint32_t Align) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000172 for (uint32_t I = 0; I < NumEndians; ++I) {
173 Streams[I * 2].Output =
174 llvm::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
Zachary Turner73295692017-03-01 21:30:06 +0000175 Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000176 BrokenInputData, Endians[I], Align);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000177 }
178 }
179
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000180 void initializeInputFromOutput(uint32_t Align) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000181 for (uint32_t I = 0; I < NumEndians; ++I) {
182 Streams[I * 2].Input =
183 llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]);
Zachary Turner73295692017-03-01 21:30:06 +0000184 Streams[I * 2 + 1].Input = llvm::make_unique<BrokenStream>(
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000185 BrokenOutputData, Endians[I], Align);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000186 }
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.
199TEST_F(BinaryStreamTest, BinaryByteStreamBounds) {
200 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000201 initializeInput(InputData, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000202
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());
Zachary Turnercb30e702017-06-14 16:41:50 +0000208 ASSERT_THAT_ERROR(Stream.Input->readBytes(2, 1, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000209 EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
Zachary Turnercb30e702017-06-14 16:41:50 +0000210 ASSERT_THAT_ERROR(Stream.Input->readBytes(0, 4, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000211 EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
212
213 // 2. Reading past the bounds of the input should fail.
Zachary Turnercb30e702017-06-14 16:41:50 +0000214 EXPECT_THAT_ERROR(Stream.Input->readBytes(4, 2, Buffer), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000215 }
216}
217
218TEST_F(BinaryStreamTest, StreamRefBounds) {
219 std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000220 initializeInput(InputData, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000221
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());
Zachary Turnercb30e702017-06-14 16:41:50 +0000228 ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000229 EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
230
231 // Reading everything from offset 2 on.
Zachary Turnercb30e702017-06-14 16:41:50 +0000232 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000233 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.
Zachary Turnercb30e702017-06-14 16:41:50 +0000239 EXPECT_THAT_ERROR(Ref.readBytes(0, 6, Buffer), Failed());
240 EXPECT_THAT_ERROR(Ref.readLongestContiguousChunk(6, Buffer), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000241
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);
Zachary Turnercb30e702017-06-14 16:41:50 +0000245 ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000246 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.
Zachary Turnercb30e702017-06-14 16:41:50 +0000252 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000253 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);
Zachary Turnercb30e702017-06-14 16:41:50 +0000261 EXPECT_THAT_ERROR(Ref.readBytes(2, 2, Buffer), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000262
263 // But if we read the longest contiguous chunk instead, we should still
264 // get the 1 byte at the end.
Zachary Turnercb30e702017-06-14 16:41:50 +0000265 ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000266 EXPECT_EQ(makeArrayRef(InputData).take_back(), Buffer);
267 }
268}
269
Zachary Turner96c69852017-11-27 18:48:37 +0000270TEST_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);
David Blaikie551d3af2017-11-27 19:43:57 +0000282 EXPECT_EQ(0U, ConstRef.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000283 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());
David Blaikie551d3af2017-11-27 19:43:57 +0000288 EXPECT_EQ(2U, ConstRef.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000289 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);
David Blaikie551d3af2017-11-27 19:43:57 +0000299 EXPECT_EQ(1U, Dropped.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000300
301 EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded());
David Blaikie551d3af2017-11-27 19:43:57 +0000302 EXPECT_EQ(4U, ConstRef.getLength());
303 EXPECT_EQ(3U, Dropped.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000304
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());
David Blaikie551d3af2017-11-27 19:43:57 +0000309 EXPECT_EQ(6U, ConstRef.getLength());
310 EXPECT_EQ(5U, Dropped.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000311
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());
David Blaikie551d3af2017-11-27 19:43:57 +0000316 EXPECT_EQ(8U, ConstRef.getLength());
317 EXPECT_EQ(4U, Dropped.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000318}
319
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000320TEST_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
Zachary Turnercb30e702017-06-14 16:41:50 +0000329 EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result),
330 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000331 EXPECT_EQ(RefData, Result);
332
333 auto Dropped = Original.drop_front(2);
Zachary Turnercb30e702017-06-14 16:41:50 +0000334 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
335 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000336 EXPECT_EQ(RefData.drop_front(2), Result);
337
338 Dropped = Original.drop_back(2);
Zachary Turnercb30e702017-06-14 16:41:50 +0000339 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
340 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000341 EXPECT_EQ(RefData.drop_back(2), Result);
342
343 Dropped = Original.keep_front(2);
Zachary Turnercb30e702017-06-14 16:41:50 +0000344 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
345 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000346 EXPECT_EQ(RefData.take_front(2), Result);
347
348 Dropped = Original.keep_back(2);
Zachary Turnercb30e702017-06-14 16:41:50 +0000349 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
350 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000351 EXPECT_EQ(RefData.take_back(2), Result);
352
353 Dropped = Original.drop_symmetric(2);
Zachary Turnercb30e702017-06-14 16:41:50 +0000354 EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
355 Succeeded());
Zachary Turnerd2b418b2017-05-17 20:42:52 +0000356 EXPECT_EQ(RefData.drop_front(2).drop_back(2), Result);
357}
358
Zachary Turner081b1bc2017-03-01 17:22:36 +0000359// Test that we can write to a BinaryStream without a StreamWriter.
360TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {
361 std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'};
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000362 initializeInput(InputData, 1);
363 initializeOutput(InputData.size(), 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000364
365 // For every combination of input stream and output stream.
366 for (auto &Stream : Streams) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000367 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;
Zachary Turnercb30e702017-06-14 16:41:50 +0000377 ASSERT_THAT_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data),
378 Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000379 ASSERT_EQ(ExpectedSize, Data.size());
380
381 // Then write it to the destination.
Zachary Turnercb30e702017-06-14 16:41:50 +0000382 ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000383
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;
Zachary Turnercb30e702017-06-14 16:41:50 +0000387 ASSERT_THAT_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2),
388 Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000389 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.
Zachary Turnercb30e702017-06-14 16:41:50 +0000394 EXPECT_THAT_ERROR(Stream.Output->writeBytes(3, BigData), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000395 }
396}
397
Zachary Turner96c69852017-11-27 18:48:37 +0000398TEST_F(BinaryStreamTest, AppendingStream) {
399 AppendingBinaryByteStream Stream(llvm::support::little);
David Blaikie551d3af2017-11-27 19:43:57 +0000400 EXPECT_EQ(0U, Stream.getLength());
Zachary Turner96c69852017-11-27 18:48:37 +0000401
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
Zachary Turner081b1bc2017-03-01 17:22:36 +0000417// Test that FixedStreamArray works correctly.
418TEST_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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000423 initializeInput(IntBytes, alignof(uint32_t));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000424
425 for (auto &Stream : Streams) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000426 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
Adrian McCarthyec694112017-05-16 22:11:25 +0000438// Ensure FixedStreamArrayIterator::operator-> works.
439// Added for coverage of r302257.
440TEST_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
Zachary Turner081b1bc2017-03-01 17:22:36 +0000462// Test that VarStreamArray works correctly.
463TEST_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());
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000468 initializeInput(StringBytes, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000469
470 struct StringExtractor {
471 public:
Zachary Turner7e62cd12017-06-09 17:54:36 +0000472 Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
Zachary Turner59e83892017-05-03 05:34:00 +0000473 if (Index == 0)
Zachary Turner081b1bc2017-03-01 17:22:36 +0000474 Len = strlen("1. Test");
Zachary Turner59e83892017-05-03 05:34:00 +0000475 else if (Index == 1)
Zachary Turner081b1bc2017-03-01 17:22:36 +0000476 Len = strlen("2. Longer Test");
Zachary Turner59e83892017-05-03 05:34:00 +0000477 else if (Index == 2)
Zachary Turner081b1bc2017-03-01 17:22:36 +0000478 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());
Zachary Turner59e83892017-05-03 05:34:00 +0000486 ++Index;
Zachary Turner081b1bc2017-03-01 17:22:36 +0000487 return Error::success();
488 }
Zachary Turner7e62cd12017-06-09 17:54:36 +0000489
490 uint32_t Index = 0;
Zachary Turner081b1bc2017-03-01 17:22:36 +0000491 };
492
493 for (auto &Stream : Streams) {
Zachary Turner7e62cd12017-06-09 17:54:36 +0000494 VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000495 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
504TEST_F(BinaryStreamTest, StreamReaderBounds) {
505 std::vector<uint8_t> Bytes;
506
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000507 initializeInput(Bytes, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000508 for (auto &Stream : Streams) {
509 StringRef S;
510 BinaryStreamReader Reader(*Stream.Input);
511 EXPECT_EQ(0U, Reader.bytesRemaining());
Zachary Turnercb30e702017-06-14 16:41:50 +0000512 EXPECT_THAT_ERROR(Reader.readFixedString(S, 1), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000513 }
514
515 Bytes.resize(5);
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000516 initializeInput(Bytes, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000517 for (auto &Stream : Streams) {
518 StringRef S;
519 BinaryStreamReader Reader(*Stream.Input);
520 EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
Zachary Turnercb30e702017-06-14 16:41:50 +0000521 EXPECT_THAT_ERROR(Reader.readFixedString(S, 5), Succeeded());
522 EXPECT_THAT_ERROR(Reader.readFixedString(S, 6), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000523 }
524}
525
526TEST_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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000535 initializeOutput(Size, alignof(support::ulittle64_t));
536 initializeInputFromOutput(alignof(support::ulittle64_t));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000537
538 for (auto &Stream : Streams) {
539 BinaryStreamWriter Writer(*Stream.Output);
Zachary Turnercb30e702017-06-14 16:41:50 +0000540 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());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000545
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);
Zachary Turnercb30e702017-06-14 16:41:50 +0000554 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());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000559 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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000569TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000570 // 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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000575 initializeInput(IntBytes, alignof(int));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000576 for (auto &Stream : Streams) {
577 BinaryStreamReader Reader(*Stream.Input);
578 ArrayRef<int> IntsRef;
Zachary Turnercb30e702017-06-14 16:41:50 +0000579 ASSERT_THAT_ERROR(Reader.readArray(IntsRef, Ints.size()), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000580 ASSERT_EQ(0U, Reader.bytesRemaining());
581 EXPECT_EQ(makeArrayRef(Ints), IntsRef);
582
583 Reader.setOffset(0);
584 FixedStreamArray<int> FixedIntsRef;
Zachary Turnercb30e702017-06-14 16:41:50 +0000585 ASSERT_THAT_ERROR(Reader.readArray(FixedIntsRef, Ints.size()), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000586 ASSERT_EQ(0U, Reader.bytesRemaining());
587 ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end()));
588 }
589}
590
591TEST_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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000596 initializeOutput(Enums.size() * sizeof(MyEnum), alignof(MyEnum));
597 initializeInputFromOutput(alignof(MyEnum));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000598 for (auto &Stream : Streams) {
599 BinaryStreamWriter Writer(*Stream.Output);
600 for (auto Value : Enums)
Zachary Turnercb30e702017-06-14 16:41:50 +0000601 ASSERT_THAT_ERROR(Writer.writeEnum(Value), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000602
603 BinaryStreamReader Reader(*Stream.Input);
604
Zachary Turner081b1bc2017-03-01 17:22:36 +0000605 FixedStreamArray<MyEnum> FSA;
606
607 for (size_t I = 0; I < Enums.size(); ++I) {
608 MyEnum Value;
Zachary Turnercb30e702017-06-14 16:41:50 +0000609 ASSERT_THAT_ERROR(Reader.readEnum(Value), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000610 EXPECT_EQ(Enums[I], Value);
611 }
612 ASSERT_EQ(0U, Reader.bytesRemaining());
613 }
614}
615
Zachary Turner73295692017-03-01 21:30:06 +0000616TEST_F(BinaryStreamTest, StreamReaderObject) {
Zachary Turner081b1bc2017-03-01 17:22:36 +0000617 struct Foo {
618 int X;
619 double Y;
620 char Z;
Zachary Turner73295692017-03-01 21:30:06 +0000621
622 bool operator==(const Foo &Other) const {
623 return X == Other.X && Y == Other.Y && Z == Other.Z;
624 }
Zachary Turner081b1bc2017-03-01 17:22:36 +0000625 };
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)});
Zachary Turner73295692017-03-01 21:30:06 +0000630 Foos.push_back({200, 2.718, static_cast<char>(-12) });
Zachary Turner081b1bc2017-03-01 17:22:36 +0000631
632 const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
633
Zachary Turner73295692017-03-01 21:30:06 +0000634 initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000635
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;
Zachary Turner73295692017-03-01 21:30:06 +0000641 const Foo *HPtrOut = nullptr;
Zachary Turnercb30e702017-06-14 16:41:50 +0000642 ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded());
643 ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded());
644 ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000645 EXPECT_EQ(0U, Reader.bytesRemaining());
Zachary Turner73295692017-03-01 21:30:06 +0000646 EXPECT_EQ(Foos[0], *FPtrOut);
647 EXPECT_EQ(Foos[1], *GPtrOut);
648 EXPECT_EQ(Foos[2], *HPtrOut);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000649 }
650}
651
652TEST_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'};
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000656 initializeInput(Bytes, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000657
658 for (auto &Stream : Streams) {
659 BinaryStreamReader Reader(*Stream.Input);
660
661 StringRef S1;
662 StringRef S2;
663 StringRef S3;
664 StringRef S4;
Zachary Turnercb30e702017-06-14 16:41:50 +0000665 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());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000669 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);
Zachary Turnercb30e702017-06-14 16:41:50 +0000678 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());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000686 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
695TEST_F(BinaryStreamTest, StreamWriterBounds) {
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000696 initializeOutput(5, 1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000697
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());
Zachary Turnercb30e702017-06-14 16:41:50 +0000703 EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000704 EXPECT_EQ(0U, Writer.bytesRemaining());
705
706 // 2. Can write an empty string even when you're full
Zachary Turnercb30e702017-06-14 16:41:50 +0000707 EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded());
708 EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000709
710 // 3. Can't write a string that is one character too long.
711 Writer.setOffset(0);
Zachary Turnercb30e702017-06-14 16:41:50 +0000712 EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000713 }
714}
715
716TEST_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
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000722 initializeInput(SourceBytes, alignof(int));
723 initializeOutputFromInput(alignof(int));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000724
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.
Zachary Turnercb30e702017-06-14 16:41:50 +0000731 ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded());
732 ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000733
734 BinaryStreamReader ReaderBacker(*Stream.Output);
Zachary Turnercb30e702017-06-14 16:41:50 +0000735 ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()),
736 Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000737
738 EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
739 }
740}
741
742TEST_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;
Zachary Turnerd2fd4ae2017-03-01 19:29:11 +0000748 initializeOutput(Length, 1);
749 initializeInputFromOutput(1);
Zachary Turner081b1bc2017-03-01 17:22:36 +0000750
751 for (auto &Stream : Streams) {
752 BinaryStreamWriter Writer(*Stream.Output);
753 for (auto S : Strings)
Zachary Turnercb30e702017-06-14 16:41:50 +0000754 ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000755 std::vector<StringRef> InStrings;
756 BinaryStreamReader Reader(*Stream.Input);
757 while (!Reader.empty()) {
758 StringRef S;
Zachary Turnercb30e702017-06-14 16:41:50 +0000759 ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000760 InStrings.push_back(S);
761 }
762 EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
763 }
764}
Zachary Turner96c69852017-11-27 18:48:37 +0000765
766TEST_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}
Zachary Turner081b1bc2017-03-01 17:22:36 +0000782}
783
784namespace {
785struct BinaryItemStreamObject {
786 explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {}
787
788 ArrayRef<uint8_t> Bytes;
789};
790}
791
792namespace llvm {
793template <> 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
804namespace {
805
806TEST_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) {
Adrian McCarthyec694112017-05-16 22:11:25 +0000816 uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
Jordan Roseca9ca542017-03-11 01:24:56 +0000817 alignof(Foo)));
Zachary Turner081b1bc2017-03-01 17:22:36 +0000818 MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
819 MutableBinaryByteStream Stream(Buffer, llvm::support::big);
820 BinaryStreamWriter Writer(Stream);
Zachary Turnercb30e702017-06-14 16:41:50 +0000821 ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000822 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;
Zachary Turnercb30e702017-06-14 16:41:50 +0000831 ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded());
Zachary Turner081b1bc2017-03-01 17:22:36 +0000832
833 EXPECT_EQ(F.X, F2->X);
834 EXPECT_DOUBLE_EQ(F.Y, F2->Y);
835 }
836}
837
838} // end anonymous namespace