OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #region | |
6 | |
7 using System; | |
8 using System.Collections.Generic; | |
9 using System.Linq; | |
10 using Google.NaClVsx.DebugSupport.DWARF; | |
11 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
12 | |
13 #endregion | |
14 | |
15 namespace NaClVsx.Package_UnitTestProject { | |
16 ///<summary> | |
17 /// This is a test class for SymbolDatabaseTest and is intended to contain al
l | |
18 /// SymbolDatabaseTest Unit Tests. Note that it is not possible to build the
se tests on a | |
19 /// compiled nexe, like the NaClSymbolProvider test suite because these all d
eal in | |
20 /// addresses and we can't predict how address information might change on a
recompilation | |
21 /// of loop.cc or a change in the toolchain. | |
22 /// In order to make this test stable, all the addresses and constants in the
test are made | |
23 /// up to test particular characteristics of the SymbolDatabase without inter
fering with each | |
24 /// other. When modifying these tests, care must be taken to choose offsets
and values that | |
25 /// are not already in use. | |
26 ///</summary> | |
27 [TestClass] | |
28 public class SymbolDatabaseTest { | |
29 ///<summary> | |
30 /// Gets or sets the test context which provides information about and func
tionality for the | |
31 /// current test run. | |
32 ///</summary> | |
33 public TestContext TestContext { get; set; } | |
34 | |
35 #region Additional test attributes | |
36 | |
37 //Use TestInitialize to run code before running each test | |
38 [TestInitialize] | |
39 public void MyTestInitialize() { | |
40 target_ = null; | |
41 } | |
42 | |
43 #endregion | |
44 | |
45 ///<summary> | |
46 /// A test for SourceFilesByFilename | |
47 ///</summary> | |
48 [TestMethod] | |
49 public void SourceFilesByFilenameTest() { | |
50 SymbolDatabaseConstructorTest(); | |
51 AddTestFiles(); | |
52 target_.BuildIndices(); | |
53 Assert.AreEqual(3, target_.SourceFilesByFilename.Count); | |
54 // File names are not enough to disambiguate between files. Path should | |
55 // be considered as well. Once that is the case, the count below should | |
56 // be 2, not 3. | |
57 var fileEntries = target_.SourceFilesByFilename[kRecurringName]; | |
58 Assert.AreEqual(3, fileEntries.Count); | |
59 } | |
60 | |
61 ///<summary> | |
62 /// A test for ScopeTransitions | |
63 ///</summary> | |
64 [TestMethod] | |
65 public void ScopeTransitionsTest() { | |
66 SymbolDatabaseConstructorTest(); | |
67 var scopeTransition = new SymbolDatabase.ScopeTransition { | |
68 Address = 123456, | |
69 Entry = null | |
70 }; | |
71 TestDictionaryAccessor( | |
72 scopeTransition.Address, | |
73 scopeTransition, | |
74 "ScopeTransitions"); | |
75 } | |
76 | |
77 ///<summary> | |
78 /// A test for LocLists | |
79 ///</summary> | |
80 [TestMethod] | |
81 public void LocListsTest() { | |
82 SymbolDatabaseConstructorTest(); | |
83 var locListEntry = new SymbolDatabase.LocListEntry { | |
84 Data = null, | |
85 StartAddress = 123456, | |
86 EndAddress = 234567 | |
87 }; | |
88 var locList = new List<SymbolDatabase.LocListEntry> {locListEntry}; | |
89 TestDictionaryAccessor(locListEntry.StartAddress, locList, "LocLists"); | |
90 } | |
91 | |
92 /// <summary> | |
93 /// A simple test for the RangeLists accessor. | |
94 /// </summary> | |
95 [TestMethod] | |
96 public void RangeListsTest() { | |
97 SymbolDatabaseConstructorTest(); | |
98 var rangeListEntry = new RangeListEntry { | |
99 BaseAddress = 123456, | |
100 HighPC = 456, | |
101 LowPC = 123, | |
102 Offset = 12 | |
103 }; | |
104 var rangeList = new Dictionary<ulong, RangeListEntry> {{123, rangeListEntr
y}}; | |
105 TestDictionaryAccessor(rangeListEntry.Offset, rangeList, "RangeLists"); | |
106 } | |
107 | |
108 /// <summary> | |
109 /// A simple test of the RangeListsByDIE accessor. | |
110 /// </summary> | |
111 [TestMethod] | |
112 public void RangeListsByDIETest() { | |
113 SymbolDatabaseConstructorTest(); | |
114 AddTestDIEs(); | |
115 AddTestAttributes(); | |
116 AddTestRangeLists(); | |
117 AddTestScopeTransitions(); | |
118 target_.BuildIndices(); | |
119 Assert.AreEqual(2, target_.RangeListsByDIE.Count); | |
120 } | |
121 | |
122 ///<summary> | |
123 /// A test for LocationsByFile | |
124 ///</summary> | |
125 [TestMethod] | |
126 public void LocationsByFileTest() { | |
127 SymbolDatabaseConstructorTest(); | |
128 AddTestLocations(); | |
129 // If you add locations to the DB, you also need to add scope transitions | |
130 // or BuildIndices will fail. | |
131 AddTestScopeTransitions(); | |
132 target_.BuildIndices(); | |
133 Assert.AreEqual(2, target_.LocationsByFile.Count); | |
134 var locationEntries = target_.LocationsByFile[kRecurringLocationKey]; | |
135 Assert.AreEqual(3, locationEntries.Count); | |
136 } | |
137 | |
138 ///<summary> | |
139 /// A test for Locations | |
140 ///</summary> | |
141 [TestMethod] | |
142 public void LocationsTest() { | |
143 SymbolDatabaseConstructorTest(); | |
144 var location = new SymbolDatabase.SourceLocation { | |
145 StartAddress = 123456, | |
146 Length = 1, | |
147 SourceFileKey = 2, | |
148 Line = 3, | |
149 Column = 4 | |
150 }; | |
151 TestDictionaryAccessor(location.StartAddress, location, "Locations"); | |
152 } | |
153 | |
154 ///<summary> | |
155 /// A test for Files | |
156 ///</summary> | |
157 [TestMethod] | |
158 public void FilesTest() { | |
159 SymbolDatabaseConstructorTest(); | |
160 var file = new SymbolDatabase.SourceFile { | |
161 Key = 1, | |
162 Filename = "name", | |
163 RelativePath = "/path", | |
164 CurrentAbsolutePath = "drive:/long/path" | |
165 }; | |
166 TestDictionaryAccessor(file.Key, file, "Files"); | |
167 } | |
168 | |
169 ///<summary> | |
170 /// A test for EntriesByParent | |
171 ///</summary> | |
172 [TestMethod] | |
173 public void EntriesByParentTest() { | |
174 SymbolDatabaseConstructorTest(); | |
175 AddTestDIEs(); | |
176 target_.BuildIndices(); | |
177 Assert.AreEqual(4, target_.EntriesByParent.Count); | |
178 var childEntries = target_.EntriesByParent[parentDIE_.Key]; | |
179 Assert.AreEqual(9, childEntries.Count); | |
180 } | |
181 | |
182 ///<summary> | |
183 /// A test for Entries | |
184 ///</summary> | |
185 [TestMethod] | |
186 public void EntriesTest() { | |
187 SymbolDatabaseConstructorTest(); | |
188 var entry = new DebugInfoEntry { | |
189 Key = 1, | |
190 OuterScope = null, | |
191 ParentKey = 0, | |
192 Tag = DwarfTag.DW_TAG_with_stmt | |
193 }; | |
194 TestDictionaryAccessor(entry.Key, entry, "Entries"); | |
195 } | |
196 | |
197 ///<summary> | |
198 /// A test for CallFrames | |
199 ///</summary> | |
200 [TestMethod] | |
201 public void CallFramesTest() { | |
202 SymbolDatabaseConstructorTest(); | |
203 var callFrame = new SymbolDatabase.CallFrame { | |
204 Address = 123456, | |
205 }; | |
206 TestDictionaryAccessor(callFrame.Address, callFrame, "CallFrames"); | |
207 } | |
208 | |
209 ///<summary> | |
210 /// A test for Attributes. Simple test to ensure we can modify attributes. | |
211 ///</summary> | |
212 [TestMethod] | |
213 public void AttributesTest() { | |
214 SymbolDatabaseConstructorTest(); | |
215 var attribute = new SymbolDatabase.DebugInfoAttribute { | |
216 Key = 1, | |
217 ParentKey = 1, | |
218 Tag = DwarfAttribute.DW_AT_trampoline, | |
219 Value = null | |
220 }; | |
221 TestDictionaryAccessor(1, attribute, "Attributes"); | |
222 } | |
223 | |
224 /// <summary> | |
225 /// A test for GetScopeAddress | |
226 /// </summary> | |
227 [TestMethod] | |
228 public void GetScopeAddressTest() { | |
229 SymbolDatabaseConstructorTest(); | |
230 AddTestScopeTransitions(); | |
231 target_.BuildIndices(); | |
232 // A small offset is added here to make sure that the function will find t
he address for | |
233 // our scope, even if it does not fall on an exact scope entry point. | |
234 var scopeAddress = target_.GetScopeAddress(kRecurringScopeKey + 5); | |
235 Assert.AreEqual(kEncapsulatingScopeAddress, scopeAddress); | |
236 } | |
237 | |
238 ///<summary> | |
239 /// A test for GetScopeForAddress | |
240 ///</summary> | |
241 [TestMethod] | |
242 public void GetScopeForAddressTest() { | |
243 SymbolDatabaseConstructorTest(); | |
244 AddTestScopeTransitions(); | |
245 target_.BuildIndices(); | |
246 // A small offset is added here to make sure that the function will find t
he address for | |
247 // our scope, even if it does not fall on an exact scope entry point. | |
248 var scopeForAddress = target_.GetScopeForAddress(kRecurringScopeKey + 5); | |
249 Assert.AreEqual( | |
250 kEncapsulatingScopeAddress, | |
251 scopeForAddress.Attributes[DwarfAttribute.DW_AT_low_pc]); | |
252 } | |
253 | |
254 ///<summary> | |
255 /// A test for GetLocationsByLine | |
256 ///</summary> | |
257 [TestMethod] | |
258 public void GetLocationsByLineTest() { | |
259 SymbolDatabaseConstructorTest(); | |
260 AddTestDIEs(); | |
261 AddTestLocations(); | |
262 AddTestScopeTransitions(); | |
263 target_.BuildIndices(); | |
264 var sourceLocationsForScope = target_.GetLocationsByLine(parentDIE_, 0); | |
265 Assert.AreEqual(4, sourceLocationsForScope.Count()); | |
266 } | |
267 | |
268 [TestMethod] | |
269 public void GetRangeForAddressTest() { | |
270 SymbolDatabaseConstructorTest(); | |
271 AddTestDIEs(); | |
272 AddTestAttributes(); | |
273 AddTestLocations(); | |
274 AddTestRangeLists(); | |
275 AddTestScopeTransitions(); | |
276 | |
277 target_.BuildIndices(); | |
278 var testAddress = kFirstRangeListLowPC + firstRangeListEntry_.BaseAddress; | |
279 // A small offset is added here to make sure that the function will find t
he address for | |
280 // our scope, even if it does not fall on an exact scope entry point. | |
281 var result = target_.GetRangeForAddress( | |
282 testAddress + 4, rangeListDie0_); | |
283 Assert.IsNotNull(result); | |
284 Assert.AreEqual(kFirstRangeListLowPC, result.LowPC); | |
285 } | |
286 | |
287 /// <summary> | |
288 /// This test checks to ensure that the GetLocationsByLine function | |
289 /// works for DIEs with ranges instead of loclists. | |
290 /// </summary> | |
291 [TestMethod] | |
292 public void GetLocationsByLineRangesTest() { | |
293 SymbolDatabaseConstructorTest(); | |
294 AddTestDIEs(); | |
295 AddTestAttributes(); | |
296 AddTestLocations(); | |
297 AddTestRangeLists(); | |
298 AddTestScopeTransitions(); | |
299 | |
300 target_.BuildIndices(); | |
301 var rangeListBaseAddress = target_.RangeLists[0][kFirstRangeListLowPC].Bas
eAddress + | |
302 kFirstRangeListLowPC; | |
303 var sourceLocationsForScope = target_.GetLocationsByLine | |
304 (rangeListDie0_, rangeListBaseAddress); | |
305 Assert.AreEqual(2, sourceLocationsForScope.Count()); | |
306 } | |
307 | |
308 ///<summary> | |
309 /// A test for GetLocationForAddress | |
310 ///</summary> | |
311 [TestMethod] | |
312 public void GetLocationForAddressTest() { | |
313 SymbolDatabaseConstructorTest(); | |
314 AddTestLocations(); | |
315 // If you add locations to the DB, you also need to add scope transitions | |
316 // or BuildIndices will fail. | |
317 AddTestScopeTransitions(); | |
318 target_.BuildIndices(); | |
319 var locationForAddress = | |
320 target_.GetLocationForAddress(kRecurringLocationKey + 5); | |
321 Assert.AreEqual(kRecurringLocationKey, locationForAddress.StartAddress); | |
322 } | |
323 | |
324 /// <summary> | |
325 /// A test for GetChildrenForEntry | |
326 /// </summary> | |
327 [TestMethod] | |
328 public void GetChildrenForEntryTest() { | |
329 SymbolDatabaseConstructorTest(); | |
330 AddTestDIEs(); | |
331 target_.BuildIndices(); | |
332 var children = target_.GetChildrenForEntry(parentDIE_.Key); | |
333 Assert.AreEqual(9, children.Count()); | |
334 } | |
335 | |
336 /// <summary> | |
337 /// A test for GetCallFrameForAddress | |
338 /// </summary> | |
339 [TestMethod] | |
340 public void GetCallFrameForAddressTest() { | |
341 SymbolDatabaseConstructorTest(); | |
342 var callFrameKeys = new List<ulong> { | |
343 kRecurringCallFrameKey, | |
344 kHigherRecurringCallFrameKey, | |
345 1000 | |
346 }; | |
347 | |
348 AddTestCallFrames(callFrameKeys); | |
349 | |
350 target_.BuildIndices(); | |
351 | |
352 var frameForAddress = target_.GetCallFrameForAddress(5); | |
353 Assert.AreEqual(kRecurringCallFrameKey, frameForAddress.Address); | |
354 frameForAddress = target_.GetCallFrameForAddress(50); | |
355 Assert.AreEqual(kHigherRecurringCallFrameKey, frameForAddress.Address); | |
356 } | |
357 | |
358 ///<summary> | |
359 /// A test for BuildIndices, This test makes some fairly simple | |
360 /// collections and then validates that BuildIndices creates the | |
361 /// expected associations between them. | |
362 ///</summary> | |
363 [TestMethod] | |
364 public void BuildIndicesTest() { | |
365 SymbolDatabaseConstructorTest(); | |
366 | |
367 AddTestDIEs(); | |
368 AddTestFiles(); | |
369 AddTestAttributes(); | |
370 AddTestLocations(); | |
371 AddTestRangeLists(); | |
372 AddTestScopeTransitions(); | |
373 var callFrameKeys = new List<ulong> { | |
374 kRecurringCallFrameKey, | |
375 kHigherRecurringCallFrameKey, | |
376 1000 | |
377 }; | |
378 | |
379 AddTestCallFrames(callFrameKeys); | |
380 | |
381 target_.BuildIndices(); | |
382 ValidateIndices(); | |
383 } | |
384 | |
385 /// <summary> | |
386 /// A test for SymbolDatabase Constructor. It creates a sample database | |
387 /// loading loop.nexe. | |
388 /// </summary> | |
389 [TestMethod] | |
390 public void SymbolDatabaseConstructorTest() { | |
391 if (null == target_) { | |
392 target_ = new SymbolDatabase(); | |
393 } | |
394 | |
395 Assert.IsNotNull(target_); | |
396 } | |
397 | |
398 // Constants that are used in more than one place for validation purposes | |
399 // are declared here. | |
400 | |
401 #region Private Implementation | |
402 | |
403 const ulong kEncapsulatingScopeAddress = 123400; | |
404 const ulong kFirstRangeListLowPC = 10; | |
405 const ulong kHigherRecurringCallFrameKey = 10; | |
406 const ulong kRecurringCallFrameKey = 1; | |
407 const uint kRecurringLocationKey = 123456; | |
408 const string kRecurringName = "name_1"; | |
409 const ulong kRecurringScopeKey = 123450; | |
410 | |
411 #endregion | |
412 | |
413 #region Private Implementation | |
414 | |
415 private readonly RangeListEntry firstRangeListEntry_ = new RangeListEntry { | |
416 BaseAddress = 123456, | |
417 HighPC = 20, | |
418 LowPC = kFirstRangeListLowPC, | |
419 Offset = 0 | |
420 }; | |
421 | |
422 private readonly DebugInfoEntry parentDIE_ = GenerateDIE( | |
423 290, null, 279, DwarfTag.DW_TAG_compile_unit); | |
424 | |
425 private readonly DebugInfoEntry rangeListDie0_ = GenerateDIE( | |
426 400, null, 290, DwarfTag.DW_TAG_lexical_block); | |
427 | |
428 private readonly DebugInfoEntry rangeListDie1_ = GenerateDIE( | |
429 420, null, 290, DwarfTag.DW_TAG_lexical_block); | |
430 | |
431 private SymbolDatabase target_; | |
432 | |
433 #endregion | |
434 | |
435 #region Private Implementation | |
436 | |
437 /// <summary> | |
438 /// Simple wrapper for creating a DebugInfoAttribute since the type lacks | |
439 /// a constructor. | |
440 /// </summary> | |
441 /// <param name = "key">A unique integer ID.</param> | |
442 /// <param name = "parentKey">The parent's ID.</param> | |
443 /// <param name = "tag">The tag, describing the purpose of the attribute. | |
444 /// </param> | |
445 /// <param name = "value">The attribute's value.</param> | |
446 /// <returns>An instance of a DebugInfoAttribute</returns> | |
447 private static SymbolDatabase.DebugInfoAttribute GenerateAttribute( | |
448 ulong key, | |
449 ulong parentKey, | |
450 DwarfAttribute tag, | |
451 Object value) { | |
452 return new SymbolDatabase.DebugInfoAttribute { | |
453 Key = key, | |
454 ParentKey = parentKey, | |
455 Tag = tag, | |
456 Value = value | |
457 }; | |
458 } | |
459 | |
460 /// <summary> | |
461 /// Simple wrapper for creating a CallFrame since the type lacks a | |
462 /// constructor. | |
463 /// </summary> | |
464 /// <param name = "address">The CallFrame's address.</param> | |
465 /// <param name = "rules">The rules for generating a CallFrame on the curren
t | |
466 /// platform.</param> | |
467 /// <returns>An instance of a CallFrame.</returns> | |
468 private static SymbolDatabase.CallFrame GenerateCallFrame( | |
469 ulong address, | |
470 List<SymbolDatabase.CallFrame.Rule> rules) { | |
471 return new SymbolDatabase.CallFrame { | |
472 Address = address, | |
473 Rules = rules | |
474 }; | |
475 } | |
476 | |
477 /// <summary> | |
478 /// Simple wrapper for creating a debug info entry since the aforementione
d | |
479 /// lacks a constructor. | |
480 /// </summary> | |
481 /// <returns>An instance of a debug info entry.</returns> | |
482 private static DebugInfoEntry GenerateDIE( | |
483 ulong key, | |
484 DebugInfoEntry scope, | |
485 ulong parentKey, | |
486 DwarfTag tag) { | |
487 return new DebugInfoEntry { | |
488 Key = key, | |
489 OuterScope = scope, | |
490 ParentKey = parentKey, | |
491 Tag = tag | |
492 }; | |
493 } | |
494 | |
495 /// <summary> | |
496 /// Simple wrapper for creating a SourceLocation since the type lacks a | |
497 /// constructor. | |
498 /// </summary> | |
499 /// <param name = "column">Column in the source file.</param> | |
500 /// <param name = "length">Length of the thing being referenced in | |
501 /// number of characters.</param> | |
502 /// <param name = "line">The line the file entry is on.</param> | |
503 /// <param name = "sourceFileKey">The unique ID of the file.</param> | |
504 /// <param name = "startAddress">The address in memory associated with the | |
505 /// source location</param> | |
506 /// <returns></returns> | |
507 private static SymbolDatabase.SourceLocation GenerateLocation( | |
508 uint column, | |
509 ulong length, | |
510 uint line, | |
511 ulong sourceFileKey, | |
512 ulong startAddress) { | |
513 return new SymbolDatabase.SourceLocation { | |
514 Column = column, | |
515 Length = length, | |
516 Line = line, | |
517 SourceFileKey = sourceFileKey, | |
518 StartAddress = startAddress | |
519 }; | |
520 } | |
521 | |
522 /// <summary> | |
523 /// Simple wrapper for creating a ScopeTransition since the type lacks a | |
524 /// constructor. | |
525 /// </summary> | |
526 /// <param name = "address">The address in memory associated with the scope | |
527 /// transition</param> | |
528 /// <param name = "entry">The debug information entry that describes the | |
529 /// scope transition.</param> | |
530 /// <returns></returns> | |
531 private static SymbolDatabase.ScopeTransition GenerateScopeTransition( | |
532 ulong address, | |
533 DebugInfoEntry entry) { | |
534 return new SymbolDatabase.ScopeTransition { | |
535 Address = address, | |
536 Entry = entry | |
537 }; | |
538 } | |
539 | |
540 | |
541 /// <summary> | |
542 /// Simple wrapper for creating a file entry since the type lacks a | |
543 /// constructor. | |
544 /// </summary> | |
545 /// <param name = "path">The path.</param> | |
546 /// <param name = "fileName">The file name.</param> | |
547 /// <param name = "key">The key.</param> | |
548 /// <param name = "relativePath">The relative path.</param> | |
549 /// <returns>An instance of a file entry</returns> | |
550 private static SymbolDatabase.SourceFile GenerateSourceFile( | |
551 string path, | |
552 string fileName, | |
553 ulong key, | |
554 string relativePath) { | |
555 return new SymbolDatabase.SourceFile { | |
556 CurrentAbsolutePath = path, | |
557 Filename = fileName, | |
558 Key = key, | |
559 RelativePath = relativePath | |
560 }; | |
561 } | |
562 | |
563 /// <summary> | |
564 /// Validates an individual index to ensure that it is not empty. Used to | |
565 /// ensure that BuildIndices() created all the secondary indices that it | |
566 /// was supposed to create. | |
567 /// </summary> | |
568 /// <typeparam name = "TValueType"></typeparam> | |
569 /// <param name = "index"></param> | |
570 private static void ValidateIndex<TValueType>(IEnumerable<TValueType> index)
{ | |
571 Assert.IsNotNull(index); | |
572 Assert.AreNotEqual(0, index.Count()); | |
573 } | |
574 | |
575 /// <summary> | |
576 /// Populates the "Attributes" list on the target_ SymbolDatabase. | |
577 /// </summary> | |
578 private void AddTestAttributes() { | |
579 // Here we expect BuildIndices to build 4 lists of attributes grouped | |
580 // by DwarfAttribute and 3 lists of attributes grouped by Parent Key. | |
581 var attributeList = new List<SymbolDatabase.DebugInfoAttribute> { | |
582 GenerateAttribute(1, 0, DwarfAttribute.DW_AT_start_scope, null), | |
583 GenerateAttribute(2, 1, DwarfAttribute.DW_AT_stmt_list, null), | |
584 GenerateAttribute(3, 1, DwarfAttribute.DW_AT_low_pc, null), | |
585 GenerateAttribute(4, 1, DwarfAttribute.DW_AT_high_pc, null), | |
586 GenerateAttribute(5, 0, DwarfAttribute.DW_AT_start_scope, null), | |
587 GenerateAttribute(6, 5, DwarfAttribute.DW_AT_low_pc, null), | |
588 GenerateAttribute(7, 5, DwarfAttribute.DW_AT_high_pc, null), | |
589 GenerateAttribute(8, rangeListDie0_.Key, DwarfAttribute.DW_AT_ranges,
(ulong) 0), | |
590 GenerateAttribute(9, rangeListDie1_.Key, DwarfAttribute.DW_AT_ranges,
(ulong) 12) | |
591 }; | |
592 foreach (var attribute in attributeList) { | |
593 if (target_.Entries.ContainsKey(attribute.ParentKey)) { | |
594 target_.Entries[attribute.ParentKey].Attributes.Add(attribute.Tag, att
ribute.Value); | |
595 } | |
596 TestDictionaryAccessor(attribute.Key, attribute, "Attributes"); | |
597 } | |
598 } | |
599 | |
600 /// <summary> | |
601 /// Populates the "CallFrames" list on the target_ SymbolDatabase. | |
602 /// </summary> | |
603 private void AddTestCallFrames(IEnumerable<ulong> callFrameKeys) { | |
604 var callFrameList = | |
605 callFrameKeys.Select(key => GenerateCallFrame(key, null)).ToList(); | |
606 foreach (var frame in callFrameList) { | |
607 TestDictionaryAccessor(frame.Address, frame, "CallFrames"); | |
608 } | |
609 } | |
610 | |
611 /// <summary> | |
612 /// Populates the "Entries" list on the target_ SymbolDatabase. | |
613 /// </summary> | |
614 private void AddTestDIEs() { | |
615 // Add DIEs to be indexed by parent (these are a few values captured from
a test run with a | |
616 // lot of output enabled.) The address values in this test are chosen to
create a | |
617 // parent-child relationship between die 290 and all the DIE's that follow
it. Like in real | |
618 // life, DIE address occur in ascending order. The specific numbers are u
nimportant. | |
619 var dieList = new List<DebugInfoEntry> { | |
620 GenerateDIE(11, null, 0, DwarfTag.DW_TAG_compile_unit), | |
621 GenerateDIE(155, null, 144, DwarfTag.DW_TAG_compile_unit), | |
622 parentDIE_, | |
623 GenerateDIE(324, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
624 GenerateDIE(331, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
625 GenerateDIE(334, parentDIE_, 290, DwarfTag.DW_TAG_pointer_type), | |
626 GenerateDIE(336, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
627 GenerateDIE(343, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
628 GenerateDIE(350, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
629 GenerateDIE(357, parentDIE_, 290, DwarfTag.DW_TAG_base_type), | |
630 rangeListDie0_, | |
631 rangeListDie1_, | |
632 }; | |
633 foreach (var debugInfoEntry in dieList) { | |
634 TestDictionaryAccessor(debugInfoEntry.Key, debugInfoEntry, "Entries"); | |
635 } | |
636 } | |
637 | |
638 /// <summary> | |
639 /// Populates the "Files" list on the target_ SymbolDatabase. | |
640 /// </summary> | |
641 private void AddTestFiles() { | |
642 // Add Files to be indexed by filename. | |
643 // Filelist entries that are identical often ahve different IDs which is | |
644 // why buildIndices checks the file names. | |
645 // The last entry added illustrates that path is currently not | |
646 // disambiguated when files are stored. | |
647 var fileList = new List<SymbolDatabase.SourceFile> { | |
648 GenerateSourceFile("path/1/", kRecurringName, 1111, "."), | |
649 GenerateSourceFile("path/1/", "name_2", 1112, "."), | |
650 GenerateSourceFile("path/1/", "name_3", 1113, "."), | |
651 GenerateSourceFile("path/1/", kRecurringName, 1114, "."), | |
652 GenerateSourceFile("path/2/", kRecurringName, 1115, ".") | |
653 }; | |
654 foreach (var file in fileList) { | |
655 TestDictionaryAccessor(file.Key, file, "Files"); | |
656 } | |
657 } | |
658 | |
659 /// <summary> | |
660 /// Populates the "Locations" list on the target SymbolDatabase. | |
661 /// </summary> | |
662 private void AddTestLocations() { | |
663 var locationList = new List<SymbolDatabase.SourceLocation> { | |
664 GenerateLocation(1, 10, 1, kRecurringLocationKey, 123456), | |
665 GenerateLocation(12, 1, 1, kRecurringLocationKey, 123466), | |
666 GenerateLocation(13, 1, 1, kRecurringLocationKey, 123470), | |
667 GenerateLocation(1, 4, 2, 123457, 123654) | |
668 }; | |
669 foreach (var location in locationList) { | |
670 TestDictionaryAccessor(location.StartAddress, location, "Locations"); | |
671 } | |
672 } | |
673 | |
674 /// <summary> | |
675 /// Populates the "RangeLists" list on the target SymbolDatabase. | |
676 /// </summary> | |
677 private void AddTestRangeLists() { | |
678 var rangeList0 = new Dictionary<ulong, RangeListEntry> { | |
679 {kFirstRangeListLowPC, firstRangeListEntry_}, | |
680 {20, new RangeListEntry {BaseAddress = 123456, HighPC = 40, LowPC = 20
, Offset = 0}}, | |
681 {40, new RangeListEntry {BaseAddress = 123456, HighPC = 80, LowPC = 40
, Offset = 0}} | |
682 }; | |
683 var rangeList1 = new Dictionary<ulong, RangeListEntry> { | |
684 {81, new RangeListEntry {BaseAddress = 123456, HighPC = 102, LowPC = 8
1, Offset = 12}}, | |
685 {102, new RangeListEntry {BaseAddress = 123456, HighPC = 112, LowPC =
102, Offset = 12}}, | |
686 {112, new RangeListEntry {BaseAddress = 123456, HighPC = 132, LowPC =
112, Offset = 12}} | |
687 }; | |
688 TestDictionaryAccessor(0, rangeList0, "RangeLists"); | |
689 TestDictionaryAccessor(12, rangeList1, "RangeLists"); | |
690 } | |
691 | |
692 /// <summary> | |
693 /// Populates the "ScopeTransitions" list on the target SymbolDatabase. T
hese are designed | |
694 /// to bracket the CodeLocations added by AddTestLocations. | |
695 /// </summary> | |
696 private void AddTestScopeTransitions() { | |
697 parentDIE_.Attributes.Add( | |
698 DwarfAttribute.DW_AT_low_pc, | |
699 kEncapsulatingScopeAddress); | |
700 var scopeTransitionList = new List<SymbolDatabase.ScopeTransition> { | |
701 GenerateScopeTransition(kEncapsulatingScopeAddress, parentDIE_), | |
702 GenerateScopeTransition( | |
703 234567, | |
704 GenerateDIE(234567, null, 0, DwarfTag.DW_TAG_compile_unit)) | |
705 }; | |
706 foreach (var scopeTransition in scopeTransitionList) { | |
707 TestDictionaryAccessor( | |
708 scopeTransition.Address, | |
709 scopeTransition, | |
710 "ScopeTransitions"); | |
711 } | |
712 } | |
713 | |
714 /// <summary> | |
715 /// This function can be used to ensure that modifying the item returned | |
716 /// by a symbol database accessor actually changes the state of the | |
717 /// database. | |
718 /// </summary> | |
719 private void TestDictionaryAccessor<TEntryType>(ulong keyValue, | |
720 TEntryType testEntry, | |
721 String accessorName) { | |
722 // We use PrivateObject to get call by name semantics. | |
723 var privates = new PrivateObject(target_); | |
724 var dictionary = | |
725 privates.GetProperty(accessorName) as Dictionary<ulong, TEntryType>; | |
726 Assert.IsNotNull(dictionary); | |
727 var firstCount = dictionary.Count; | |
728 dictionary.Add(keyValue, testEntry); | |
729 var dictionaryRef2 = | |
730 privates.GetProperty(accessorName) as Dictionary<ulong, TEntryType>; | |
731 Assert.IsNotNull(dictionaryRef2); | |
732 Assert.AreEqual(firstCount + 1, dictionaryRef2.Count); | |
733 } | |
734 | |
735 /// <summary> | |
736 /// Runs a set of validations to ensure all that indices were built. | |
737 /// </summary> | |
738 private void ValidateIndices() { | |
739 ValidateIndex(target_.SourceFilesByFilename); | |
740 ValidateIndex(target_.LocationsByFile); | |
741 ValidateIndex(target_.EntriesByParent); | |
742 ValidateIndex(target_.RangeListsByDIE); | |
743 } | |
744 | |
745 #endregion | |
746 } | |
747 } | |
OLD | NEW |