04bd9410306fed17c3a812be45dffec5f7089a66
[lldb.git] / llvm / unittests / DebugInfo / PDB / MsfBuilderTest.cpp
1 //===- MSFBuilderTest.cpp  Tests manipulation of MSF stream metadata ------===//
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 "ErrorChecking.h"
11
12 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
13 #include "llvm/DebugInfo/MSF/MSFCommon.h"
14
15 #include "gtest/gtest.h"
16
17 using namespace llvm;
18 using namespace llvm::msf;
19
20 namespace {
21 class MSFBuilderTest : public testing::Test {
22 protected:
23   void initializeSimpleSuperBlock(msf::SuperBlock &SB) {
24     initializeSuperBlock(SB);
25     SB.NumBlocks = 1000;
26     SB.NumDirectoryBytes = 8192;
27   }
28
29   void initializeSuperBlock(msf::SuperBlock &SB) {
30     ::memset(&SB, 0, sizeof(SB));
31
32     ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic));
33     SB.BlockMapAddr = 1;
34     SB.BlockSize = 4096;
35     SB.NumDirectoryBytes = 0;
36     SB.NumBlocks = 2; // one for the Super Block, one for the directory
37   }
38
39   BumpPtrAllocator Allocator;
40 };
41 }
42
43 TEST_F(MSFBuilderTest, ValidateSuperBlockAccept) {
44   // Test that a known good super block passes validation.
45   SuperBlock SB;
46   initializeSuperBlock(SB);
47
48   EXPECT_NO_ERROR(msf::validateSuperBlock(SB));
49 }
50
51 TEST_F(MSFBuilderTest, ValidateSuperBlockReject) {
52   // Test that various known problems cause a super block to be rejected.
53   SuperBlock SB;
54   initializeSimpleSuperBlock(SB);
55
56   // Mismatched magic
57   SB.MagicBytes[0] = 8;
58   EXPECT_ERROR(msf::validateSuperBlock(SB));
59   initializeSimpleSuperBlock(SB);
60
61   // Block 0 is reserved for super block, can't be occupied by the block map
62   SB.BlockMapAddr = 0;
63   EXPECT_ERROR(msf::validateSuperBlock(SB));
64   initializeSimpleSuperBlock(SB);
65
66   // Block sizes have to be powers of 2.
67   SB.BlockSize = 3120;
68   EXPECT_ERROR(msf::validateSuperBlock(SB));
69   initializeSimpleSuperBlock(SB);
70
71   // The directory itself has a maximum size.
72   SB.NumDirectoryBytes = SB.BlockSize * SB.BlockSize / 4;
73   EXPECT_NO_ERROR(msf::validateSuperBlock(SB));
74   SB.NumDirectoryBytes = SB.NumDirectoryBytes + 4;
75   EXPECT_ERROR(msf::validateSuperBlock(SB));
76 }
77
78 TEST_F(MSFBuilderTest, TestUsedBlocksMarkedAsUsed) {
79   // Test that when assigning a stream to a known list of blocks, the blocks
80   // are correctly marked as used after adding, but no other incorrect blocks
81   // are accidentally marked as used.
82
83   std::vector<uint32_t> Blocks = {4, 5, 6, 7, 8, 9, 10, 11, 12};
84   // Allocate some extra blocks at the end so we can verify that they're free
85   // after the initialization.
86   uint32_t NumBlocks = msf::getMinimumBlockCount() + Blocks.size() + 10;
87   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096, NumBlocks);
88   EXPECT_EXPECTED(ExpectedMsf);
89   auto &Msf = *ExpectedMsf;
90
91   EXPECT_NO_ERROR(Msf.addStream(Blocks.size() * 4096, Blocks));
92
93   for (auto B : Blocks) {
94     EXPECT_FALSE(Msf.isBlockFree(B));
95   }
96
97   uint32_t FreeBlockStart = Blocks.back() + 1;
98   for (uint32_t I = FreeBlockStart; I < NumBlocks; ++I) {
99     EXPECT_TRUE(Msf.isBlockFree(I));
100   }
101 }
102
103 TEST_F(MSFBuilderTest, TestAddStreamNoDirectoryBlockIncrease) {
104   // Test that adding a new stream correctly updates the directory.  This only
105   // tests the case where the directory *DOES NOT* grow large enough that it
106   // crosses a Block boundary.
107   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
108   EXPECT_EXPECTED(ExpectedMsf);
109   auto &Msf = *ExpectedMsf;
110
111   auto ExpectedL1 = Msf.build();
112   EXPECT_EXPECTED(ExpectedL1);
113   MSFLayout &L1 = *ExpectedL1;
114
115   auto OldDirBlocks = L1.DirectoryBlocks;
116   EXPECT_EQ(1U, OldDirBlocks.size());
117
118   auto ExpectedMsf2 = MSFBuilder::create(Allocator, 4096);
119   EXPECT_EXPECTED(ExpectedMsf2);
120   auto &Msf2 = *ExpectedMsf2;
121
122   EXPECT_NO_ERROR(Msf2.addStream(4000));
123   EXPECT_EQ(1U, Msf2.getNumStreams());
124   EXPECT_EQ(4000U, Msf2.getStreamSize(0));
125   auto Blocks = Msf2.getStreamBlocks(0);
126   EXPECT_EQ(1U, Blocks.size());
127
128   auto ExpectedL2 = Msf2.build();
129   EXPECT_EXPECTED(ExpectedL2);
130   MSFLayout &L2 = *ExpectedL2;
131   auto NewDirBlocks = L2.DirectoryBlocks;
132   EXPECT_EQ(1U, NewDirBlocks.size());
133 }
134
135 TEST_F(MSFBuilderTest, TestAddStreamWithDirectoryBlockIncrease) {
136   // Test that adding a new stream correctly updates the directory.  This only
137   // tests the case where the directory *DOES* grow large enough that it
138   // crosses a Block boundary.  This is because the newly added stream occupies
139   // so many Blocks that need to be indexed in the directory that the directory
140   // crosses a Block boundary.
141   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
142   EXPECT_EXPECTED(ExpectedMsf);
143   auto &Msf = *ExpectedMsf;
144
145   EXPECT_NO_ERROR(Msf.addStream(4096 * 4096 / sizeof(uint32_t)));
146
147   auto ExpectedL1 = Msf.build();
148   EXPECT_EXPECTED(ExpectedL1);
149   MSFLayout &L1 = *ExpectedL1;
150   auto DirBlocks = L1.DirectoryBlocks;
151   EXPECT_EQ(2U, DirBlocks.size());
152 }
153
154 TEST_F(MSFBuilderTest, TestGrowStreamNoBlockIncrease) {
155   // Test growing an existing stream by a value that does not affect the number
156   // of blocks it occupies.
157   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
158   EXPECT_EXPECTED(ExpectedMsf);
159   auto &Msf = *ExpectedMsf;
160
161   EXPECT_NO_ERROR(Msf.addStream(1024));
162   EXPECT_EQ(1024U, Msf.getStreamSize(0));
163   auto OldStreamBlocks = Msf.getStreamBlocks(0);
164   EXPECT_EQ(1U, OldStreamBlocks.size());
165
166   EXPECT_NO_ERROR(Msf.setStreamSize(0, 2048));
167   EXPECT_EQ(2048U, Msf.getStreamSize(0));
168   auto NewStreamBlocks = Msf.getStreamBlocks(0);
169   EXPECT_EQ(1U, NewStreamBlocks.size());
170
171   EXPECT_EQ(OldStreamBlocks, NewStreamBlocks);
172 }
173
174 TEST_F(MSFBuilderTest, TestGrowStreamWithBlockIncrease) {
175   // Test that growing an existing stream to a value large enough that it causes
176   // the need to allocate new Blocks to the stream correctly updates the
177   // stream's
178   // block list.
179   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
180   EXPECT_EXPECTED(ExpectedMsf);
181   auto &Msf = *ExpectedMsf;
182
183   EXPECT_NO_ERROR(Msf.addStream(2048));
184   EXPECT_EQ(2048U, Msf.getStreamSize(0));
185   std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
186   EXPECT_EQ(1U, OldStreamBlocks.size());
187
188   EXPECT_NO_ERROR(Msf.setStreamSize(0, 6144));
189   EXPECT_EQ(6144U, Msf.getStreamSize(0));
190   std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
191   EXPECT_EQ(2U, NewStreamBlocks.size());
192
193   EXPECT_EQ(OldStreamBlocks[0], NewStreamBlocks[0]);
194   EXPECT_NE(NewStreamBlocks[0], NewStreamBlocks[1]);
195 }
196
197 TEST_F(MSFBuilderTest, TestShrinkStreamNoBlockDecrease) {
198   // Test that shrinking an existing stream by a value that does not affect the
199   // number of Blocks it occupies makes no changes to stream's block list.
200   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
201   EXPECT_EXPECTED(ExpectedMsf);
202   auto &Msf = *ExpectedMsf;
203
204   EXPECT_NO_ERROR(Msf.addStream(2048));
205   EXPECT_EQ(2048U, Msf.getStreamSize(0));
206   std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
207   EXPECT_EQ(1U, OldStreamBlocks.size());
208
209   EXPECT_NO_ERROR(Msf.setStreamSize(0, 1024));
210   EXPECT_EQ(1024U, Msf.getStreamSize(0));
211   std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
212   EXPECT_EQ(1U, NewStreamBlocks.size());
213
214   EXPECT_EQ(OldStreamBlocks, NewStreamBlocks);
215 }
216
217 TEST_F(MSFBuilderTest, TestShrinkStreamWithBlockDecrease) {
218   // Test that shrinking an existing stream to a value large enough that it
219   // causes the need to deallocate new Blocks to the stream correctly updates
220   // the stream's block list.
221   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
222   EXPECT_EXPECTED(ExpectedMsf);
223   auto &Msf = *ExpectedMsf;
224
225   EXPECT_NO_ERROR(Msf.addStream(6144));
226   EXPECT_EQ(6144U, Msf.getStreamSize(0));
227   std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
228   EXPECT_EQ(2U, OldStreamBlocks.size());
229
230   EXPECT_NO_ERROR(Msf.setStreamSize(0, 2048));
231   EXPECT_EQ(2048U, Msf.getStreamSize(0));
232   std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
233   EXPECT_EQ(1U, NewStreamBlocks.size());
234
235   EXPECT_EQ(OldStreamBlocks[0], NewStreamBlocks[0]);
236 }
237
238 TEST_F(MSFBuilderTest, TestRejectReusedStreamBlock) {
239   // Test that attempting to add a stream and assigning a block that is already
240   // in use by another stream fails.
241   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
242   EXPECT_EXPECTED(ExpectedMsf);
243   auto &Msf = *ExpectedMsf;
244
245   EXPECT_NO_ERROR(Msf.addStream(6144));
246
247   std::vector<uint32_t> Blocks = {2, 3};
248   EXPECT_ERROR(Msf.addStream(6144, Blocks));
249 }
250
251 TEST_F(MSFBuilderTest, TestBlockCountsWhenAddingStreams) {
252   // Test that when adding multiple streams, the number of used and free Blocks
253   // allocated to the MSF file are as expected.
254   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
255   EXPECT_EXPECTED(ExpectedMsf);
256   auto &Msf = *ExpectedMsf;
257
258   // one for the super block, one for the directory block map
259   uint32_t NumUsedBlocks = Msf.getNumUsedBlocks();
260   EXPECT_EQ(msf::getMinimumBlockCount(), NumUsedBlocks);
261   EXPECT_EQ(0U, Msf.getNumFreeBlocks());
262
263   const uint32_t StreamSizes[] = {4000, 6193, 189723};
264   for (int I = 0; I < 3; ++I) {
265     EXPECT_NO_ERROR(Msf.addStream(StreamSizes[I]));
266     NumUsedBlocks += bytesToBlocks(StreamSizes[I], 4096);
267     EXPECT_EQ(NumUsedBlocks, Msf.getNumUsedBlocks());
268     EXPECT_EQ(0U, Msf.getNumFreeBlocks());
269   }
270 }
271
272 TEST_F(MSFBuilderTest, BuildMsfLayout) {
273   // Test that we can generate an MSFLayout structure from a valid layout
274   // specification.
275   auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
276   EXPECT_EXPECTED(ExpectedMsf);
277   auto &Msf = *ExpectedMsf;
278
279   const uint32_t StreamSizes[] = {4000, 6193, 189723};
280   uint32_t ExpectedNumBlocks = msf::getMinimumBlockCount();
281   for (int I = 0; I < 3; ++I) {
282     EXPECT_NO_ERROR(Msf.addStream(StreamSizes[I]));
283     ExpectedNumBlocks += bytesToBlocks(StreamSizes[I], 4096);
284   }
285   ++ExpectedNumBlocks; // The directory itself should use 1 block
286
287   auto ExpectedLayout = Msf.build();
288   EXPECT_EXPECTED(ExpectedLayout);
289   MSFLayout &L = *ExpectedLayout;
290   EXPECT_EQ(4096U, L.SB->BlockSize);
291   EXPECT_EQ(ExpectedNumBlocks, L.SB->NumBlocks);
292
293   EXPECT_EQ(1U, L.DirectoryBlocks.size());
294
295   EXPECT_EQ(3U, L.StreamMap.size());
296   EXPECT_EQ(3U, L.StreamSizes.size());
297   for (int I = 0; I < 3; ++I) {
298     EXPECT_EQ(StreamSizes[I], L.StreamSizes[I]);
299     uint32_t ExpectedNumBlocks = bytesToBlocks(StreamSizes[I], 4096);
300     EXPECT_EQ(ExpectedNumBlocks, L.StreamMap[I].size());
301   }
302 }
303
304 TEST_F(MSFBuilderTest, UseDirectoryBlockHint) {
305   Expected<MSFBuilder> ExpectedMsf = MSFBuilder::create(
306       Allocator, 4096, msf::getMinimumBlockCount() + 1, false);
307   EXPECT_EXPECTED(ExpectedMsf);
308   auto &Msf = *ExpectedMsf;
309
310   uint32_t B = msf::getFirstUnreservedBlock();
311   EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1}));
312   EXPECT_NO_ERROR(Msf.addStream(2048, {B + 2}));
313
314   auto ExpectedLayout = Msf.build();
315   EXPECT_EXPECTED(ExpectedLayout);
316   MSFLayout &L = *ExpectedLayout;
317   EXPECT_EQ(msf::getMinimumBlockCount() + 2, L.SB->NumBlocks);
318   EXPECT_EQ(1U, L.DirectoryBlocks.size());
319   EXPECT_EQ(1U, L.StreamMap[0].size());
320
321   EXPECT_EQ(B + 1, L.DirectoryBlocks[0]);
322   EXPECT_EQ(B + 2, L.StreamMap[0].front());
323 }
324
325 TEST_F(MSFBuilderTest, DirectoryBlockHintInsufficient) {
326   Expected<MSFBuilder> ExpectedMsf =
327       MSFBuilder::create(Allocator, 4096, msf::getMinimumBlockCount() + 2);
328   EXPECT_EXPECTED(ExpectedMsf);
329   auto &Msf = *ExpectedMsf;
330   uint32_t B = msf::getFirstUnreservedBlock();
331   EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1}));
332
333   uint32_t Size = 4096 * 4096 / 4;
334   EXPECT_NO_ERROR(Msf.addStream(Size));
335
336   auto ExpectedLayout = Msf.build();
337   EXPECT_EXPECTED(ExpectedLayout);
338   MSFLayout &L = *ExpectedLayout;
339   EXPECT_EQ(2U, L.DirectoryBlocks.size());
340   EXPECT_EQ(B + 1, L.DirectoryBlocks[0]);
341 }
342
343 TEST_F(MSFBuilderTest, DirectoryBlockHintOverestimated) {
344   Expected<MSFBuilder> ExpectedMsf =
345       MSFBuilder::create(Allocator, 4096, msf::getMinimumBlockCount() + 2);
346   EXPECT_EXPECTED(ExpectedMsf);
347   auto &Msf = *ExpectedMsf;
348
349   uint32_t B = msf::getFirstUnreservedBlock();
350   EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1, B + 2}));
351
352   EXPECT_NO_ERROR(Msf.addStream(2048));
353
354   auto ExpectedLayout = Msf.build();
355   EXPECT_EXPECTED(ExpectedLayout);
356   MSFLayout &L = *ExpectedLayout;
357   EXPECT_EQ(1U, L.DirectoryBlocks.size());
358   EXPECT_EQ(B + 1, L.DirectoryBlocks[0]);
359 }