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