OLD | NEW |
| (Empty) |
1 // -*- mode: c++ -*- | |
2 | |
3 // Copyright (c) 2010 Google Inc. All Rights Reserved. | |
4 // | |
5 // Redistribution and use in source and binary forms, with or without | |
6 // modification, are permitted provided that the following conditions are | |
7 // met: | |
8 // | |
9 // * Redistributions of source code must retain the above copyright | |
10 // notice, this list of conditions and the following disclaimer. | |
11 // * Redistributions in binary form must reproduce the above | |
12 // copyright notice, this list of conditions and the following disclaimer | |
13 // in the documentation and/or other materials provided with the | |
14 // distribution. | |
15 // * Neither the name of Google Inc. nor the names of its | |
16 // contributors may be used to endorse or promote products derived from | |
17 // this software without specific prior written permission. | |
18 // | |
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> | |
32 | |
33 // dwarf2diehander_unittest.cc: Unit tests for google_breakpad::DIEDispatcher. | |
34 | |
35 #include "breakpad_googletest_includes.h" | |
36 | |
37 #include "common/dwarf/dwarf2diehandler.h" | |
38 | |
39 using ::testing::_; | |
40 using ::testing::ContainerEq; | |
41 using ::testing::ElementsAreArray; | |
42 using ::testing::Eq; | |
43 using ::testing::InSequence; | |
44 using ::testing::Return; | |
45 using ::testing::Sequence; | |
46 using ::testing::StrEq; | |
47 | |
48 using dwarf2reader::AttributeList; | |
49 using dwarf2reader::DIEDispatcher; | |
50 using dwarf2reader::DIEHandler; | |
51 using dwarf2reader::DwarfAttribute; | |
52 using dwarf2reader::DwarfForm; | |
53 using dwarf2reader::DwarfTag; | |
54 using dwarf2reader::RootDIEHandler; | |
55 | |
56 class MockDIEHandler: public DIEHandler { | |
57 public: | |
58 MOCK_METHOD3(ProcessAttributeUnsigned, | |
59 void(DwarfAttribute, DwarfForm, uint64)); | |
60 MOCK_METHOD3(ProcessAttributeSigned, | |
61 void(DwarfAttribute, DwarfForm, int64)); | |
62 MOCK_METHOD3(ProcessAttributeReference, | |
63 void(DwarfAttribute, DwarfForm, uint64)); | |
64 MOCK_METHOD4(ProcessAttributeBuffer, | |
65 void(DwarfAttribute, DwarfForm, const char *, uint64)); | |
66 MOCK_METHOD3(ProcessAttributeString, | |
67 void(DwarfAttribute, DwarfForm, const string &)); | |
68 MOCK_METHOD0(EndAttributes, bool()); | |
69 MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag, | |
70 const AttributeList &)); | |
71 MOCK_METHOD0(Finish, void()); | |
72 }; | |
73 | |
74 class MockRootDIEHandler: public RootDIEHandler { | |
75 public: | |
76 MOCK_METHOD3(ProcessAttributeUnsigned, | |
77 void(DwarfAttribute, DwarfForm, uint64)); | |
78 MOCK_METHOD3(ProcessAttributeSigned, | |
79 void(DwarfAttribute, DwarfForm, int64)); | |
80 MOCK_METHOD3(ProcessAttributeReference, | |
81 void(DwarfAttribute, DwarfForm, uint64)); | |
82 MOCK_METHOD4(ProcessAttributeBuffer, | |
83 void(DwarfAttribute, DwarfForm, const char *, uint64)); | |
84 MOCK_METHOD3(ProcessAttributeString, | |
85 void(DwarfAttribute, DwarfForm, const string &)); | |
86 MOCK_METHOD0(EndAttributes, bool()); | |
87 MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag, | |
88 const AttributeList &)); | |
89 MOCK_METHOD0(Finish, void()); | |
90 MOCK_METHOD5(StartCompilationUnit, bool(uint64, uint8, uint8, uint64, uint8)); | |
91 MOCK_METHOD3(StartRootDIE, bool(uint64, DwarfTag, const AttributeList &)); | |
92 }; | |
93 | |
94 // If the handler elects to skip the compilation unit, the dispatcher | |
95 // should tell the reader so. | |
96 TEST(Dwarf2DIEHandler, SkipCompilationUnit) { | |
97 Sequence s; | |
98 MockRootDIEHandler mock_root_handler; | |
99 DIEDispatcher die_dispatcher(&mock_root_handler); | |
100 | |
101 EXPECT_CALL(mock_root_handler, | |
102 StartCompilationUnit(0x8d42aed77cfccf3eLL, | |
103 0x89, 0xdc, | |
104 0x2ecb4dc778a80f21LL, | |
105 0x66)) | |
106 .InSequence(s) | |
107 .WillOnce(Return(false)); | |
108 | |
109 EXPECT_FALSE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL, | |
110 0x89, 0xdc, | |
111 0x2ecb4dc778a80f21LL, | |
112 0x66)); | |
113 } | |
114 | |
115 // If the handler elects to skip the root DIE, the dispatcher should | |
116 // tell the reader so. | |
117 TEST(Dwarf2DIEHandler, SkipRootDIE) { | |
118 Sequence s; | |
119 MockRootDIEHandler mock_root_handler; | |
120 DIEDispatcher die_dispatcher(&mock_root_handler); | |
121 | |
122 AttributeList mock_attribute_list; | |
123 mock_attribute_list.push_back(make_pair(dwarf2reader::DW_AT_name, | |
124 dwarf2reader::DW_FORM_string)); | |
125 | |
126 EXPECT_CALL(mock_root_handler, | |
127 StartCompilationUnit(0xde8994029fc8b999LL, 0xf4, 0x02, | |
128 0xb00febffa76e2b2bLL, 0x5c)) | |
129 .InSequence(s) | |
130 .WillOnce(Return(true)); | |
131 EXPECT_CALL(mock_root_handler, | |
132 StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6, | |
133 ContainerEq(mock_attribute_list))) | |
134 .InSequence(s) | |
135 .WillOnce(Return(false)); | |
136 | |
137 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0xde8994029fc8b999LL, | |
138 0xf4, 0x02, | |
139 0xb00febffa76e2b2bLL, 0x5c)); | |
140 EXPECT_FALSE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL, | |
141 (DwarfTag) 0xb4f98da6, | |
142 mock_attribute_list)); | |
143 die_dispatcher.EndDIE(0x7d08242b4b510cf2LL); | |
144 } | |
145 | |
146 // If the handler elects to skip the root DIE's children, the | |
147 // dispatcher should tell the reader so --- and avoid deleting the | |
148 // root handler. | |
149 TEST(Dwarf2DIEHandler, SkipRootDIEChildren) { | |
150 MockRootDIEHandler mock_root_handler; | |
151 DIEDispatcher die_dispatcher(&mock_root_handler); | |
152 | |
153 AttributeList mock_attribute_list; | |
154 | |
155 { | |
156 InSequence s; | |
157 | |
158 EXPECT_CALL(mock_root_handler, | |
159 StartCompilationUnit(0x15d6897480cc65a7LL, 0x26, 0xa0, | |
160 0x09f8bf0767f91675LL, 0xdb)) | |
161 .WillOnce(Return(true)); | |
162 EXPECT_CALL(mock_root_handler, | |
163 StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6, | |
164 ContainerEq(mock_attribute_list))) | |
165 .WillOnce(Return(true)); | |
166 // Please don't tell me about my children. | |
167 EXPECT_CALL(mock_root_handler, EndAttributes()) | |
168 .WillOnce(Return(false)); | |
169 EXPECT_CALL(mock_root_handler, Finish()) | |
170 .WillOnce(Return()); | |
171 } | |
172 | |
173 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x15d6897480cc65a7LL, | |
174 0x26, 0xa0, | |
175 0x09f8bf0767f91675LL, 0xdb)); | |
176 EXPECT_TRUE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL, | |
177 (DwarfTag) 0xb4f98da6, | |
178 mock_attribute_list)); | |
179 EXPECT_FALSE(die_dispatcher.StartDIE(0x435150ceedccda18LL, | |
180 (DwarfTag) 0xc3a17bba, | |
181 mock_attribute_list)); | |
182 die_dispatcher.EndDIE(0x435150ceedccda18LL); | |
183 die_dispatcher.EndDIE(0x7d08242b4b510cf2LL); | |
184 } | |
185 | |
186 // The dispatcher should pass attribute values through to the die | |
187 // handler accurately. | |
188 TEST(Dwarf2DIEHandler, PassAttributeValues) { | |
189 MockRootDIEHandler mock_root_handler; | |
190 DIEDispatcher die_dispatcher(&mock_root_handler); | |
191 | |
192 AttributeList mock_attribute_list; | |
193 mock_attribute_list.push_back(make_pair(dwarf2reader::DW_AT_name, | |
194 dwarf2reader::DW_FORM_string)); | |
195 const char buffer[10] = { 0x24, 0x24, 0x35, 0x9a, 0xca, | |
196 0xcf, 0xa8, 0x84, 0xa7, 0x18 }; | |
197 string str = "\xc8\x26\x2e\x0d\xa4\x9c\x37\xd6\xfb\x1d"; | |
198 | |
199 // Set expectations. | |
200 { | |
201 InSequence s; | |
202 | |
203 // We'll like the compilation unit header. | |
204 EXPECT_CALL(mock_root_handler, | |
205 StartCompilationUnit(0x8d42aed77cfccf3eLL, 0x89, 0xdc, | |
206 0x2ecb4dc778a80f21LL, 0x66)) | |
207 .WillOnce(Return(true)); | |
208 | |
209 // We'll like the root DIE. | |
210 EXPECT_CALL(mock_root_handler, | |
211 StartRootDIE(0xe2222da01e29f2a9LL, (DwarfTag) 0x9829445c, | |
212 ContainerEq(mock_attribute_list))) | |
213 .WillOnce(Return(true)); | |
214 | |
215 // Expect some attribute values. | |
216 EXPECT_CALL(mock_root_handler, | |
217 ProcessAttributeUnsigned((DwarfAttribute) 0x1cc0bfed, | |
218 (DwarfForm) 0x424f1468, | |
219 0xa592571997facda1ULL)) | |
220 .WillOnce(Return()); | |
221 EXPECT_CALL(mock_root_handler, | |
222 ProcessAttributeSigned((DwarfAttribute) 0x43694dc9, | |
223 (DwarfForm) 0xf6f78901L, | |
224 0x92602a4e3bf1f446LL)) | |
225 .WillOnce(Return()); | |
226 EXPECT_CALL(mock_root_handler, | |
227 ProcessAttributeReference((DwarfAttribute) 0x4033e8cL, | |
228 (DwarfForm) 0xf66fbe0bL, | |
229 0x50fddef44734fdecULL)) | |
230 .WillOnce(Return()); | |
231 EXPECT_CALL(mock_root_handler, | |
232 ProcessAttributeBuffer((DwarfAttribute) 0x25d7e0af, | |
233 (DwarfForm) 0xe99a539a, | |
234 buffer, sizeof(buffer))) | |
235 .WillOnce(Return()); | |
236 EXPECT_CALL(mock_root_handler, | |
237 ProcessAttributeString((DwarfAttribute) 0x310ed065, | |
238 (DwarfForm) 0x15762fec, | |
239 StrEq(str))) | |
240 .WillOnce(Return()); | |
241 EXPECT_CALL(mock_root_handler, EndAttributes()) | |
242 .WillOnce(Return(true)); | |
243 EXPECT_CALL(mock_root_handler, FindChildHandler(_, _, _)) | |
244 .Times(0); | |
245 EXPECT_CALL(mock_root_handler, Finish()) | |
246 .WillOnce(Return()); | |
247 } | |
248 | |
249 // Drive the dispatcher. | |
250 | |
251 // Report the CU header. | |
252 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL, | |
253 0x89, 0xdc, | |
254 0x2ecb4dc778a80f21LL, | |
255 0x66)); | |
256 // Report the root DIE. | |
257 EXPECT_TRUE(die_dispatcher.StartDIE(0xe2222da01e29f2a9LL, | |
258 (DwarfTag) 0x9829445c, | |
259 mock_attribute_list)); | |
260 | |
261 // Report some attribute values. | |
262 die_dispatcher.ProcessAttributeUnsigned(0xe2222da01e29f2a9LL, | |
263 (DwarfAttribute) 0x1cc0bfed, | |
264 (DwarfForm) 0x424f1468, | |
265 0xa592571997facda1ULL); | |
266 die_dispatcher.ProcessAttributeSigned(0xe2222da01e29f2a9LL, | |
267 (DwarfAttribute) 0x43694dc9, | |
268 (DwarfForm) 0xf6f78901, | |
269 0x92602a4e3bf1f446LL); | |
270 die_dispatcher.ProcessAttributeReference(0xe2222da01e29f2a9LL, | |
271 (DwarfAttribute) 0x4033e8c, | |
272 (DwarfForm) 0xf66fbe0b, | |
273 0x50fddef44734fdecULL); | |
274 die_dispatcher.ProcessAttributeBuffer(0xe2222da01e29f2a9LL, | |
275 (DwarfAttribute) 0x25d7e0af, | |
276 (DwarfForm) 0xe99a539a, | |
277 buffer, sizeof(buffer)); | |
278 die_dispatcher.ProcessAttributeString(0xe2222da01e29f2a9LL, | |
279 (DwarfAttribute) 0x310ed065, | |
280 (DwarfForm) 0x15762fec, | |
281 str); | |
282 | |
283 // Finish the root DIE (and thus the CU). | |
284 die_dispatcher.EndDIE(0xe2222da01e29f2a9LL); | |
285 } | |
286 | |
287 TEST(Dwarf2DIEHandler, FindAndSkipChildren) { | |
288 MockRootDIEHandler mock_root_handler; | |
289 MockDIEHandler *mock_child1_handler = new(MockDIEHandler); | |
290 MockDIEHandler *mock_child3_handler = new(MockDIEHandler); | |
291 DIEDispatcher die_dispatcher(&mock_root_handler); | |
292 | |
293 AttributeList root_attribute_list; | |
294 root_attribute_list.push_back(make_pair((DwarfAttribute) 0xb01185df, | |
295 (DwarfForm) 0xbc97cee8)); | |
296 AttributeList child1_attribute_list; | |
297 child1_attribute_list.push_back(make_pair((DwarfAttribute) 0x41014e43, | |
298 (DwarfForm) 0x63155f4c)); | |
299 AttributeList grandchild1_attribute_list; | |
300 grandchild1_attribute_list.push_back(make_pair((DwarfAttribute) 0xf72f823c, | |
301 (DwarfForm) 0x0ff6a201)); | |
302 AttributeList greatgrandchild1_attribute_list; | |
303 greatgrandchild1_attribute_list | |
304 .push_back(make_pair((DwarfAttribute) 0xbe66e5f0, (DwarfForm) 0xb4b24ff7)); | |
305 AttributeList child2_attribute_list; | |
306 child1_attribute_list.push_back(make_pair((DwarfAttribute) 0xf22df14c, | |
307 (DwarfForm) 0x20676e7d)); | |
308 AttributeList child3_attribute_list; | |
309 child3_attribute_list.push_back(make_pair((DwarfAttribute) 0xe8bf1201, | |
310 (DwarfForm) 0x53a5b7a8)); | |
311 | |
312 { | |
313 InSequence s; | |
314 | |
315 // We'll like the compilation unit header. | |
316 EXPECT_CALL(mock_root_handler, | |
317 StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21, | |
318 0x47dd3c764275a216LL, 0xa5)) | |
319 .WillOnce(Return(true)); | |
320 | |
321 // Root DIE. | |
322 { | |
323 EXPECT_CALL(mock_root_handler, | |
324 StartRootDIE(0x15f0e06bdfe3c372LL, (DwarfTag) 0xf5d60c59, | |
325 ContainerEq(root_attribute_list))) | |
326 .WillOnce(Return(true)); | |
327 EXPECT_CALL(mock_root_handler, | |
328 ProcessAttributeSigned((DwarfAttribute) 0xf779a642, | |
329 (DwarfForm) 0x2cb63027, | |
330 0x18e744661769d08fLL)) | |
331 .WillOnce(Return()); | |
332 EXPECT_CALL(mock_root_handler, EndAttributes()) | |
333 .WillOnce(Return(true)); | |
334 | |
335 // First child DIE. | |
336 EXPECT_CALL(mock_root_handler, | |
337 FindChildHandler(0x149f644f8116fe8cLL, | |
338 (DwarfTag) 0xac2cbd8c, | |
339 ContainerEq(child1_attribute_list))) | |
340 .WillOnce(Return(mock_child1_handler)); | |
341 { | |
342 EXPECT_CALL(*mock_child1_handler, | |
343 ProcessAttributeSigned((DwarfAttribute) 0xa6fd6f65, | |
344 (DwarfForm) 0xe4f64c41, | |
345 0x1b04e5444a55fe67LL)) | |
346 .WillOnce(Return()); | |
347 EXPECT_CALL(*mock_child1_handler, EndAttributes()) | |
348 .WillOnce(Return(false)); | |
349 // Skip first grandchild DIE and first great-grandchild DIE. | |
350 EXPECT_CALL(*mock_child1_handler, Finish()) | |
351 .WillOnce(Return()); | |
352 } | |
353 | |
354 // Second child DIE. Root handler will decline to return a handler | |
355 // for this child. | |
356 EXPECT_CALL(mock_root_handler, | |
357 FindChildHandler(0x97412be24875de9dLL, | |
358 (DwarfTag) 0x505a068b, | |
359 ContainerEq(child2_attribute_list))) | |
360 .WillOnce(Return((DIEHandler *) NULL)); | |
361 | |
362 // Third child DIE. | |
363 EXPECT_CALL(mock_root_handler, | |
364 FindChildHandler(0x753c964c8ab538aeLL, | |
365 (DwarfTag) 0x8c22970e, | |
366 ContainerEq(child3_attribute_list))) | |
367 .WillOnce(Return(mock_child3_handler)); | |
368 { | |
369 EXPECT_CALL(*mock_child3_handler, | |
370 ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb, | |
371 (DwarfForm) 0x610b7ae1, | |
372 0x3ea5c609d7d7560fLL)) | |
373 .WillOnce(Return()); | |
374 EXPECT_CALL(*mock_child3_handler, EndAttributes()) | |
375 .WillOnce(Return(true)); | |
376 EXPECT_CALL(*mock_child3_handler, Finish()) | |
377 .WillOnce(Return()); | |
378 } | |
379 | |
380 EXPECT_CALL(mock_root_handler, Finish()) | |
381 .WillOnce(Return()); | |
382 } | |
383 } | |
384 | |
385 | |
386 // Drive the dispatcher. | |
387 | |
388 // Report the CU header. | |
389 EXPECT_TRUE(die_dispatcher | |
390 .StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21, | |
391 0x47dd3c764275a216LL, 0xa5)); | |
392 // Report the root DIE. | |
393 { | |
394 EXPECT_TRUE(die_dispatcher.StartDIE(0x15f0e06bdfe3c372LL, | |
395 (DwarfTag) 0xf5d60c59, | |
396 root_attribute_list)); | |
397 die_dispatcher.ProcessAttributeSigned(0x15f0e06bdfe3c372LL, | |
398 (DwarfAttribute) 0xf779a642, | |
399 (DwarfForm) 0x2cb63027, | |
400 0x18e744661769d08fLL); | |
401 | |
402 // First child DIE. | |
403 { | |
404 EXPECT_TRUE(die_dispatcher.StartDIE(0x149f644f8116fe8cLL, | |
405 (DwarfTag) 0xac2cbd8c, | |
406 child1_attribute_list)); | |
407 die_dispatcher.ProcessAttributeSigned(0x149f644f8116fe8cLL, | |
408 (DwarfAttribute) 0xa6fd6f65, | |
409 (DwarfForm) 0xe4f64c41, | |
410 0x1b04e5444a55fe67LL); | |
411 | |
412 // First grandchild DIE. Will be skipped. | |
413 { | |
414 EXPECT_FALSE(die_dispatcher.StartDIE(0xd68de1ee0bd29419LL, | |
415 (DwarfTag) 0x22f05a15, | |
416 grandchild1_attribute_list)); | |
417 // First great-grandchild DIE. Will be skipped without being | |
418 // mentioned to any handler. | |
419 { | |
420 EXPECT_FALSE(die_dispatcher | |
421 .StartDIE(0xb3076285d25cac25LL, | |
422 (DwarfTag) 0xcff4061b, | |
423 greatgrandchild1_attribute_list)); | |
424 die_dispatcher.EndDIE(0xb3076285d25cac25LL); | |
425 } | |
426 die_dispatcher.EndDIE(0xd68de1ee0bd29419LL); | |
427 } | |
428 die_dispatcher.EndDIE(0x149f644f8116fe8cLL); | |
429 } | |
430 | |
431 // Second child DIE. Root handler will decline to find a handler for it. | |
432 { | |
433 EXPECT_FALSE(die_dispatcher.StartDIE(0x97412be24875de9dLL, | |
434 (DwarfTag) 0x505a068b, | |
435 child2_attribute_list)); | |
436 die_dispatcher.EndDIE(0x97412be24875de9dLL); | |
437 } | |
438 | |
439 // Third child DIE. | |
440 { | |
441 EXPECT_TRUE(die_dispatcher.StartDIE(0x753c964c8ab538aeLL, | |
442 (DwarfTag) 0x8c22970e, | |
443 child3_attribute_list)); | |
444 die_dispatcher.ProcessAttributeSigned(0x753c964c8ab538aeLL, | |
445 (DwarfAttribute) 0x4e2b7cfb, | |
446 (DwarfForm) 0x610b7ae1, | |
447 0x3ea5c609d7d7560fLL); | |
448 die_dispatcher.EndDIE(0x753c964c8ab538aeLL); | |
449 } | |
450 | |
451 // Finish the root DIE (and thus the CU). | |
452 die_dispatcher.EndDIE(0x15f0e06bdfe3c372LL); | |
453 } | |
454 } | |
455 | |
456 // The DIEDispatcher destructor is supposed to delete all handlers on | |
457 // the stack, except for the root. | |
458 TEST(Dwarf2DIEHandler, FreeHandlersOnStack) { | |
459 MockRootDIEHandler mock_root_handler; | |
460 MockDIEHandler *mock_child_handler = new(MockDIEHandler); | |
461 MockDIEHandler *mock_grandchild_handler = new(MockDIEHandler); | |
462 AttributeList empty_attribute_list; | |
463 | |
464 { | |
465 InSequence s; | |
466 | |
467 // We'll like the compilation unit header. | |
468 EXPECT_CALL(mock_root_handler, | |
469 StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89, | |
470 0x76d392ff393ddda2LL, 0xbf)) | |
471 .WillOnce(Return(true)); | |
472 | |
473 // Root DIE. | |
474 { | |
475 EXPECT_CALL(mock_root_handler, | |
476 StartRootDIE(0xbf13b761691ddc91LL, (DwarfTag) 0x98980361, | |
477 ContainerEq(empty_attribute_list))) | |
478 .WillOnce(Return(true)); | |
479 EXPECT_CALL(mock_root_handler, EndAttributes()) | |
480 .WillOnce(Return(true)); | |
481 | |
482 // Child DIE. | |
483 EXPECT_CALL(mock_root_handler, | |
484 FindChildHandler(0x058f09240c5fc8c9LL, | |
485 (DwarfTag) 0x898bf0d0, | |
486 ContainerEq(empty_attribute_list))) | |
487 .WillOnce(Return(mock_child_handler)); | |
488 { | |
489 EXPECT_CALL(*mock_child_handler, EndAttributes()) | |
490 .WillOnce(Return(true)); | |
491 | |
492 // Grandchild DIE. | |
493 EXPECT_CALL(*mock_child_handler, | |
494 FindChildHandler(0x32dc00c9945dc0c8LL, | |
495 (DwarfTag) 0x2802d007, | |
496 ContainerEq(empty_attribute_list))) | |
497 .WillOnce(Return(mock_grandchild_handler)); | |
498 { | |
499 EXPECT_CALL(*mock_grandchild_handler, | |
500 ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb, | |
501 (DwarfForm) 0x610b7ae1, | |
502 0x3ea5c609d7d7560fLL)) | |
503 .WillOnce(Return()); | |
504 | |
505 // At this point, we abandon the traversal, so none of the | |
506 // usual stuff should get called. | |
507 EXPECT_CALL(*mock_grandchild_handler, EndAttributes()) | |
508 .Times(0); | |
509 EXPECT_CALL(*mock_grandchild_handler, Finish()) | |
510 .Times(0); | |
511 } | |
512 | |
513 EXPECT_CALL(*mock_child_handler, Finish()) | |
514 .Times(0); | |
515 } | |
516 | |
517 EXPECT_CALL(mock_root_handler, Finish()) | |
518 .Times(0); | |
519 } | |
520 } | |
521 | |
522 // The dispatcher. | |
523 DIEDispatcher die_dispatcher(&mock_root_handler); | |
524 | |
525 // Report the CU header. | |
526 EXPECT_TRUE(die_dispatcher | |
527 .StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89, | |
528 0x76d392ff393ddda2LL, 0xbf)); | |
529 // Report the root DIE. | |
530 { | |
531 EXPECT_TRUE(die_dispatcher.StartDIE(0xbf13b761691ddc91LL, | |
532 (DwarfTag) 0x98980361, | |
533 empty_attribute_list)); | |
534 | |
535 // Child DIE. | |
536 { | |
537 EXPECT_TRUE(die_dispatcher.StartDIE(0x058f09240c5fc8c9LL, | |
538 (DwarfTag) 0x898bf0d0, | |
539 empty_attribute_list)); | |
540 | |
541 // Grandchild DIE. | |
542 { | |
543 EXPECT_TRUE(die_dispatcher.StartDIE(0x32dc00c9945dc0c8LL, | |
544 (DwarfTag) 0x2802d007, | |
545 empty_attribute_list)); | |
546 die_dispatcher.ProcessAttributeSigned(0x32dc00c9945dc0c8LL, | |
547 (DwarfAttribute) 0x4e2b7cfb, | |
548 (DwarfForm) 0x610b7ae1, | |
549 0x3ea5c609d7d7560fLL); | |
550 | |
551 // Stop the traversal abruptly, so that there will still be | |
552 // handlers on the stack when the dispatcher is destructed. | |
553 | |
554 // No EndDIE call... | |
555 } | |
556 // No EndDIE call... | |
557 } | |
558 // No EndDIE call... | |
559 } | |
560 } | |
OLD | NEW |