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