PageRenderTime 54ms CodeModel.GetById 7ms app.highlight 42ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/common/dwarf/dwarf2diehandler_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 579 lines | 430 code | 65 blank | 84 comment | 0 complexity | c13d872901f58aea86490e3664c2bd09 MD5 | raw file
  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 <string>
 36#include <utility>
 37
 38#include "breakpad_googletest_includes.h"
 39
 40#include "common/dwarf/dwarf2diehandler.h"
 41
 42using std::make_pair;
 43using std::string;
 44
 45using ::testing::_;
 46using ::testing::ContainerEq;
 47using ::testing::ElementsAreArray;
 48using ::testing::Eq;
 49using ::testing::InSequence;
 50using ::testing::Return;
 51using ::testing::Sequence;
 52using ::testing::StrEq;
 53
 54using dwarf2reader::AttributeList;
 55using dwarf2reader::DIEDispatcher;
 56using dwarf2reader::DIEHandler;
 57using dwarf2reader::DwarfAttribute;
 58using dwarf2reader::DwarfForm;
 59using dwarf2reader::DwarfTag;
 60using dwarf2reader::RootDIEHandler;
 61
 62class MockDIEHandler: public DIEHandler {
 63 public:
 64  MOCK_METHOD3(ProcessAttributeUnsigned,
 65               void(DwarfAttribute, DwarfForm, uint64));
 66  MOCK_METHOD3(ProcessAttributeSigned,
 67               void(DwarfAttribute, DwarfForm, int64));
 68  MOCK_METHOD3(ProcessAttributeReference,
 69               void(DwarfAttribute, DwarfForm, uint64));
 70  MOCK_METHOD4(ProcessAttributeBuffer,
 71               void(DwarfAttribute, DwarfForm, const char *, uint64));
 72  MOCK_METHOD3(ProcessAttributeString,
 73               void(DwarfAttribute, DwarfForm, const string &));
 74  MOCK_METHOD3(ProcessAttributeSignature,
 75               void(DwarfAttribute, DwarfForm, uint64));
 76  MOCK_METHOD0(EndAttributes, bool());
 77  MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
 78                                              const AttributeList &));
 79  MOCK_METHOD0(Finish, void());
 80};
 81
 82class MockRootDIEHandler: public RootDIEHandler {
 83 public:
 84  MOCK_METHOD3(ProcessAttributeUnsigned,
 85               void(DwarfAttribute, DwarfForm, uint64));
 86  MOCK_METHOD3(ProcessAttributeSigned,
 87               void(DwarfAttribute, DwarfForm, int64));
 88  MOCK_METHOD3(ProcessAttributeReference,
 89               void(DwarfAttribute, DwarfForm, uint64));
 90  MOCK_METHOD4(ProcessAttributeBuffer,
 91               void(DwarfAttribute, DwarfForm, const char *, uint64));
 92  MOCK_METHOD3(ProcessAttributeString,
 93               void(DwarfAttribute, DwarfForm, const string &));
 94  MOCK_METHOD3(ProcessAttributeSignature,
 95               void(DwarfAttribute, DwarfForm, uint64));
 96  MOCK_METHOD0(EndAttributes, bool());
 97  MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
 98                                              const AttributeList &));
 99  MOCK_METHOD0(Finish, void());
100  MOCK_METHOD5(StartCompilationUnit, bool(uint64, uint8, uint8, uint64, uint8));
101  MOCK_METHOD3(StartRootDIE, bool(uint64, DwarfTag, const AttributeList &));
102};
103
104// If the handler elects to skip the compilation unit, the dispatcher
105// should tell the reader so.
106TEST(Dwarf2DIEHandler, SkipCompilationUnit) {
107  Sequence s;
108  MockRootDIEHandler mock_root_handler;
109  DIEDispatcher die_dispatcher(&mock_root_handler);
110
111  EXPECT_CALL(mock_root_handler,
112              StartCompilationUnit(0x8d42aed77cfccf3eLL,
113                                   0x89, 0xdc,
114                                   0x2ecb4dc778a80f21LL,
115                                   0x66))
116      .InSequence(s)
117      .WillOnce(Return(false));
118
119  EXPECT_FALSE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL,
120                                                   0x89, 0xdc,
121                                                   0x2ecb4dc778a80f21LL,
122                                                   0x66));
123}
124
125// If the handler elects to skip the root DIE, the dispatcher should
126// tell the reader so.
127TEST(Dwarf2DIEHandler, SkipRootDIE) {
128  Sequence s;
129  MockRootDIEHandler mock_root_handler;
130  DIEDispatcher die_dispatcher(&mock_root_handler);
131
132  AttributeList mock_attribute_list;
133  mock_attribute_list.push_back(make_pair(dwarf2reader::DW_AT_name,
134                                          dwarf2reader::DW_FORM_string));
135
136  EXPECT_CALL(mock_root_handler,
137              StartCompilationUnit(0xde8994029fc8b999LL, 0xf4, 0x02,
138                                   0xb00febffa76e2b2bLL, 0x5c))
139      .InSequence(s)
140      .WillOnce(Return(true));
141  EXPECT_CALL(mock_root_handler,
142              StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6,
143                           ContainerEq(mock_attribute_list)))
144      .InSequence(s)
145      .WillOnce(Return(false));
146
147  EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0xde8994029fc8b999LL, 
148                                                  0xf4, 0x02,
149                                                  0xb00febffa76e2b2bLL, 0x5c));
150  EXPECT_FALSE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL,
151                                       (DwarfTag) 0xb4f98da6,
152                                       mock_attribute_list));
153  die_dispatcher.EndDIE(0x7d08242b4b510cf2LL);
154}
155
156// If the handler elects to skip the root DIE's children, the
157// dispatcher should tell the reader so --- and avoid deleting the
158// root handler.
159TEST(Dwarf2DIEHandler, SkipRootDIEChildren) {
160  MockRootDIEHandler mock_root_handler;
161  DIEDispatcher die_dispatcher(&mock_root_handler);
162
163  AttributeList mock_attribute_list;
164
165  {
166    InSequence s;
167
168    EXPECT_CALL(mock_root_handler,
169                StartCompilationUnit(0x15d6897480cc65a7LL, 0x26, 0xa0,
170                                     0x09f8bf0767f91675LL, 0xdb))
171      .WillOnce(Return(true));
172    EXPECT_CALL(mock_root_handler,
173                StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6,
174                             ContainerEq(mock_attribute_list)))
175      .WillOnce(Return(true));
176    // Please don't tell me about my children.
177    EXPECT_CALL(mock_root_handler, EndAttributes())
178      .WillOnce(Return(false));
179    EXPECT_CALL(mock_root_handler, Finish())
180      .WillOnce(Return());
181  }
182
183  EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x15d6897480cc65a7LL,
184                                                  0x26, 0xa0,
185                                                  0x09f8bf0767f91675LL, 0xdb));
186  EXPECT_TRUE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL,
187                                      (DwarfTag) 0xb4f98da6,
188                                      mock_attribute_list));
189  EXPECT_FALSE(die_dispatcher.StartDIE(0x435150ceedccda18LL,
190                                       (DwarfTag) 0xc3a17bba,
191                                       mock_attribute_list));
192  die_dispatcher.EndDIE(0x435150ceedccda18LL);
193  die_dispatcher.EndDIE(0x7d08242b4b510cf2LL);
194}
195
196// The dispatcher should pass attribute values through to the die
197// handler accurately.
198TEST(Dwarf2DIEHandler, PassAttributeValues) {
199  MockRootDIEHandler mock_root_handler;
200  DIEDispatcher die_dispatcher(&mock_root_handler);
201
202  AttributeList mock_attribute_list;
203  mock_attribute_list.push_back(make_pair(dwarf2reader::DW_AT_name,
204                                          dwarf2reader::DW_FORM_string));
205  const char buffer[10] = { 0x24, 0x24, 0x35, 0x9a, 0xca,
206                            0xcf, 0xa8, 0x84, 0xa7, 0x18 };
207  string str = "\xc8\x26\x2e\x0d\xa4\x9c\x37\xd6\xfb\x1d";
208
209  // Set expectations.
210  {
211    InSequence s;
212
213    // We'll like the compilation unit header.
214    EXPECT_CALL(mock_root_handler,
215                StartCompilationUnit(0x8d42aed77cfccf3eLL, 0x89, 0xdc,
216                                     0x2ecb4dc778a80f21LL, 0x66))
217      .WillOnce(Return(true));
218
219    // We'll like the root DIE.
220    EXPECT_CALL(mock_root_handler,
221                StartRootDIE(0xe2222da01e29f2a9LL, (DwarfTag) 0x9829445c,
222                             ContainerEq(mock_attribute_list)))
223      .WillOnce(Return(true));
224
225    // Expect some attribute values.
226    EXPECT_CALL(mock_root_handler,
227                ProcessAttributeUnsigned((DwarfAttribute) 0x1cc0bfed,
228                                         (DwarfForm) 0x424f1468,
229                                         0xa592571997facda1ULL))
230      .WillOnce(Return());
231    EXPECT_CALL(mock_root_handler,
232                ProcessAttributeSigned((DwarfAttribute) 0x43694dc9,
233                                       (DwarfForm) 0xf6f78901L,
234                                       0x92602a4e3bf1f446LL))
235      .WillOnce(Return());
236    EXPECT_CALL(mock_root_handler,
237                ProcessAttributeReference((DwarfAttribute) 0x4033e8cL,
238                                          (DwarfForm) 0xf66fbe0bL,
239                                          0x50fddef44734fdecULL))
240      .WillOnce(Return());
241    EXPECT_CALL(mock_root_handler,
242                ProcessAttributeBuffer((DwarfAttribute) 0x25d7e0af,
243                                       (DwarfForm) 0xe99a539a,
244                                       buffer, sizeof(buffer)))
245      .WillOnce(Return());
246    EXPECT_CALL(mock_root_handler,
247                ProcessAttributeString((DwarfAttribute) 0x310ed065,
248                                       (DwarfForm) 0x15762fec,
249                                       StrEq(str)))
250      .WillOnce(Return());
251    EXPECT_CALL(mock_root_handler,
252                ProcessAttributeSignature((DwarfAttribute) 0x58790d72,
253                                          (DwarfForm) 0x4159f138,
254                                          0x94682463613e6a5fULL))
255      .WillOnce(Return());
256    EXPECT_CALL(mock_root_handler, EndAttributes())
257      .WillOnce(Return(true));
258    EXPECT_CALL(mock_root_handler, FindChildHandler(_, _, _))
259      .Times(0);
260    EXPECT_CALL(mock_root_handler, Finish())
261      .WillOnce(Return());
262  }
263
264  // Drive the dispatcher.
265
266  // Report the CU header.
267  EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL,
268                                                  0x89, 0xdc,
269                                                  0x2ecb4dc778a80f21LL,
270                                                  0x66));
271  // Report the root DIE.
272  EXPECT_TRUE(die_dispatcher.StartDIE(0xe2222da01e29f2a9LL,
273                                      (DwarfTag) 0x9829445c,
274                                      mock_attribute_list));
275
276  // Report some attribute values.
277  die_dispatcher.ProcessAttributeUnsigned(0xe2222da01e29f2a9LL,
278                                          (DwarfAttribute) 0x1cc0bfed,
279                                          (DwarfForm) 0x424f1468,
280                                          0xa592571997facda1ULL);
281  die_dispatcher.ProcessAttributeSigned(0xe2222da01e29f2a9LL,
282                                        (DwarfAttribute) 0x43694dc9,
283                                        (DwarfForm) 0xf6f78901,
284                                        0x92602a4e3bf1f446LL);
285  die_dispatcher.ProcessAttributeReference(0xe2222da01e29f2a9LL,
286                                           (DwarfAttribute) 0x4033e8c,
287                                           (DwarfForm) 0xf66fbe0b,
288                                           0x50fddef44734fdecULL);
289  die_dispatcher.ProcessAttributeBuffer(0xe2222da01e29f2a9LL,
290                                        (DwarfAttribute) 0x25d7e0af,
291                                        (DwarfForm) 0xe99a539a,
292                                        buffer, sizeof(buffer));
293  die_dispatcher.ProcessAttributeString(0xe2222da01e29f2a9LL,
294                                        (DwarfAttribute) 0x310ed065,
295                                        (DwarfForm) 0x15762fec,
296                                        str);
297  die_dispatcher.ProcessAttributeSignature(0xe2222da01e29f2a9LL,
298                                           (DwarfAttribute) 0x58790d72,
299                                           (DwarfForm) 0x4159f138,
300                                           0x94682463613e6a5fULL);
301
302  // Finish the root DIE (and thus the CU).
303  die_dispatcher.EndDIE(0xe2222da01e29f2a9LL);
304}
305
306TEST(Dwarf2DIEHandler, FindAndSkipChildren) {
307  MockRootDIEHandler mock_root_handler;
308  MockDIEHandler *mock_child1_handler = new(MockDIEHandler);
309  MockDIEHandler *mock_child3_handler = new(MockDIEHandler);
310  DIEDispatcher die_dispatcher(&mock_root_handler);
311
312  AttributeList root_attribute_list;
313  root_attribute_list.push_back(make_pair((DwarfAttribute) 0xb01185df,
314                                          (DwarfForm) 0xbc97cee8));
315  AttributeList child1_attribute_list;
316  child1_attribute_list.push_back(make_pair((DwarfAttribute) 0x41014e43,
317                                            (DwarfForm) 0x63155f4c));
318  AttributeList grandchild1_attribute_list;
319  grandchild1_attribute_list.push_back(make_pair((DwarfAttribute) 0xf72f823c,
320                                                 (DwarfForm) 0x0ff6a201));
321  AttributeList greatgrandchild1_attribute_list;
322  greatgrandchild1_attribute_list
323    .push_back(make_pair((DwarfAttribute) 0xbe66e5f0, (DwarfForm) 0xb4b24ff7));
324  AttributeList child2_attribute_list;
325  child1_attribute_list.push_back(make_pair((DwarfAttribute) 0xf22df14c,
326                                            (DwarfForm) 0x20676e7d));
327  AttributeList child3_attribute_list;
328  child3_attribute_list.push_back(make_pair((DwarfAttribute) 0xe8bf1201,
329                                            (DwarfForm) 0x53a5b7a8));
330
331  {
332    InSequence s;
333
334    // We'll like the compilation unit header.
335    EXPECT_CALL(mock_root_handler,
336                StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21,
337                                     0x47dd3c764275a216LL, 0xa5))
338      .WillOnce(Return(true));
339
340    // Root DIE.
341    {
342      EXPECT_CALL(mock_root_handler,
343                  StartRootDIE(0x15f0e06bdfe3c372LL, (DwarfTag) 0xf5d60c59,
344                               ContainerEq(root_attribute_list)))
345        .WillOnce(Return(true));
346      EXPECT_CALL(mock_root_handler,
347                  ProcessAttributeSigned((DwarfAttribute) 0xf779a642,
348                                         (DwarfForm) 0x2cb63027,
349                                         0x18e744661769d08fLL))
350        .WillOnce(Return());
351      EXPECT_CALL(mock_root_handler, EndAttributes())
352        .WillOnce(Return(true));
353
354      // First child DIE.
355      EXPECT_CALL(mock_root_handler,
356                  FindChildHandler(0x149f644f8116fe8cLL,
357                                   (DwarfTag) 0xac2cbd8c,
358                                   ContainerEq(child1_attribute_list)))
359        .WillOnce(Return(mock_child1_handler));
360      {
361        EXPECT_CALL(*mock_child1_handler,
362                    ProcessAttributeSigned((DwarfAttribute) 0xa6fd6f65,
363                                           (DwarfForm) 0xe4f64c41,
364                                           0x1b04e5444a55fe67LL))
365          .WillOnce(Return());
366        EXPECT_CALL(*mock_child1_handler, EndAttributes())
367          .WillOnce(Return(false));
368        // Skip first grandchild DIE and first great-grandchild DIE.
369        EXPECT_CALL(*mock_child1_handler, Finish())
370          .WillOnce(Return());
371      }
372
373      // Second child DIE.  Root handler will decline to return a handler
374      // for this child.
375      EXPECT_CALL(mock_root_handler,
376                  FindChildHandler(0x97412be24875de9dLL,
377                                   (DwarfTag) 0x505a068b,
378                                   ContainerEq(child2_attribute_list)))
379        .WillOnce(Return((DIEHandler *) NULL));
380
381      // Third child DIE.
382      EXPECT_CALL(mock_root_handler,
383                  FindChildHandler(0x753c964c8ab538aeLL,
384                                   (DwarfTag) 0x8c22970e,
385                                   ContainerEq(child3_attribute_list)))
386        .WillOnce(Return(mock_child3_handler));
387      {
388        EXPECT_CALL(*mock_child3_handler,
389                    ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb,
390                                           (DwarfForm) 0x610b7ae1,
391                                           0x3ea5c609d7d7560fLL))
392          .WillOnce(Return());
393        EXPECT_CALL(*mock_child3_handler, EndAttributes())
394          .WillOnce(Return(true));
395        EXPECT_CALL(*mock_child3_handler, Finish())
396          .WillOnce(Return());
397      }
398
399      EXPECT_CALL(mock_root_handler, Finish())
400        .WillOnce(Return());
401    }
402  }
403
404    
405  // Drive the dispatcher.
406
407  // Report the CU header.
408  EXPECT_TRUE(die_dispatcher
409              .StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21,
410                                    0x47dd3c764275a216LL, 0xa5));
411  // Report the root DIE.
412  {
413    EXPECT_TRUE(die_dispatcher.StartDIE(0x15f0e06bdfe3c372LL,
414                                        (DwarfTag) 0xf5d60c59,
415                                        root_attribute_list));
416    die_dispatcher.ProcessAttributeSigned(0x15f0e06bdfe3c372LL,
417                                          (DwarfAttribute) 0xf779a642,
418                                          (DwarfForm) 0x2cb63027,
419                                          0x18e744661769d08fLL);
420
421    // First child DIE.
422    {
423      EXPECT_TRUE(die_dispatcher.StartDIE(0x149f644f8116fe8cLL,
424                                          (DwarfTag) 0xac2cbd8c,
425                                          child1_attribute_list));
426      die_dispatcher.ProcessAttributeSigned(0x149f644f8116fe8cLL,
427                                            (DwarfAttribute) 0xa6fd6f65,
428                                            (DwarfForm) 0xe4f64c41,
429                                            0x1b04e5444a55fe67LL);
430
431      // First grandchild DIE.  Will be skipped.
432      {
433        EXPECT_FALSE(die_dispatcher.StartDIE(0xd68de1ee0bd29419LL,
434                                            (DwarfTag) 0x22f05a15,
435                                            grandchild1_attribute_list));
436        // First great-grandchild DIE.  Will be skipped without being
437        // mentioned to any handler.
438        {
439          EXPECT_FALSE(die_dispatcher
440                       .StartDIE(0xb3076285d25cac25LL,
441                                 (DwarfTag) 0xcff4061b,
442                                 greatgrandchild1_attribute_list));
443          die_dispatcher.EndDIE(0xb3076285d25cac25LL);          
444        }
445        die_dispatcher.EndDIE(0xd68de1ee0bd29419LL);
446      }
447      die_dispatcher.EndDIE(0x149f644f8116fe8cLL);
448    }
449
450    // Second child DIE.  Root handler will decline to find a handler for it.
451    {
452      EXPECT_FALSE(die_dispatcher.StartDIE(0x97412be24875de9dLL,
453                                           (DwarfTag) 0x505a068b,
454                                           child2_attribute_list));
455      die_dispatcher.EndDIE(0x97412be24875de9dLL);
456    }
457    
458    // Third child DIE.
459    {
460      EXPECT_TRUE(die_dispatcher.StartDIE(0x753c964c8ab538aeLL,
461                                          (DwarfTag) 0x8c22970e,
462                                          child3_attribute_list));
463      die_dispatcher.ProcessAttributeSigned(0x753c964c8ab538aeLL,
464                                            (DwarfAttribute) 0x4e2b7cfb,
465                                            (DwarfForm) 0x610b7ae1,
466                                            0x3ea5c609d7d7560fLL);
467      die_dispatcher.EndDIE(0x753c964c8ab538aeLL);
468    }
469    
470    // Finish the root DIE (and thus the CU).
471    die_dispatcher.EndDIE(0x15f0e06bdfe3c372LL);
472  }
473}
474
475// The DIEDispatcher destructor is supposed to delete all handlers on
476// the stack, except for the root.
477TEST(Dwarf2DIEHandler, FreeHandlersOnStack) {
478  MockRootDIEHandler mock_root_handler;
479  MockDIEHandler *mock_child_handler = new(MockDIEHandler);
480  MockDIEHandler *mock_grandchild_handler = new(MockDIEHandler);
481  AttributeList empty_attribute_list;
482
483  {
484    InSequence s;
485
486    // We'll like the compilation unit header.
487    EXPECT_CALL(mock_root_handler,
488                StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89,
489                                     0x76d392ff393ddda2LL, 0xbf))
490      .WillOnce(Return(true));
491
492    // Root DIE.
493    {
494      EXPECT_CALL(mock_root_handler,
495                  StartRootDIE(0xbf13b761691ddc91LL, (DwarfTag) 0x98980361,
496                               ContainerEq(empty_attribute_list)))
497        .WillOnce(Return(true));
498      EXPECT_CALL(mock_root_handler, EndAttributes())
499        .WillOnce(Return(true));
500      
501      // Child DIE.
502      EXPECT_CALL(mock_root_handler,
503                  FindChildHandler(0x058f09240c5fc8c9LL,
504                                   (DwarfTag) 0x898bf0d0,
505                                   ContainerEq(empty_attribute_list)))
506        .WillOnce(Return(mock_child_handler));
507      {
508        EXPECT_CALL(*mock_child_handler, EndAttributes())
509          .WillOnce(Return(true));
510
511        // Grandchild DIE.
512        EXPECT_CALL(*mock_child_handler,
513                    FindChildHandler(0x32dc00c9945dc0c8LL,
514                                     (DwarfTag) 0x2802d007,
515                                     ContainerEq(empty_attribute_list)))
516          .WillOnce(Return(mock_grandchild_handler));
517        {
518          EXPECT_CALL(*mock_grandchild_handler,
519                      ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb,
520                                             (DwarfForm) 0x610b7ae1,
521                                             0x3ea5c609d7d7560fLL))
522            .WillOnce(Return());
523
524          // At this point, we abandon the traversal, so none of the
525          // usual stuff should get called.
526          EXPECT_CALL(*mock_grandchild_handler, EndAttributes())
527            .Times(0);
528          EXPECT_CALL(*mock_grandchild_handler, Finish())
529            .Times(0);
530        }
531
532        EXPECT_CALL(*mock_child_handler, Finish())
533          .Times(0);
534      }
535
536      EXPECT_CALL(mock_root_handler, Finish())
537        .Times(0);
538    }
539  }
540
541  // The dispatcher.
542  DIEDispatcher die_dispatcher(&mock_root_handler);
543  
544  // Report the CU header.
545  EXPECT_TRUE(die_dispatcher
546              .StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89,
547                                    0x76d392ff393ddda2LL, 0xbf));
548  // Report the root DIE.
549  {
550    EXPECT_TRUE(die_dispatcher.StartDIE(0xbf13b761691ddc91LL,
551                                        (DwarfTag) 0x98980361,
552                                        empty_attribute_list));
553
554    // Child DIE.
555    {
556      EXPECT_TRUE(die_dispatcher.StartDIE(0x058f09240c5fc8c9LL,
557                                          (DwarfTag) 0x898bf0d0,
558                                          empty_attribute_list));
559
560      // Grandchild DIE.
561      {
562        EXPECT_TRUE(die_dispatcher.StartDIE(0x32dc00c9945dc0c8LL,
563                                            (DwarfTag) 0x2802d007,
564                                            empty_attribute_list));
565        die_dispatcher.ProcessAttributeSigned(0x32dc00c9945dc0c8LL,
566                                              (DwarfAttribute) 0x4e2b7cfb,
567                                              (DwarfForm) 0x610b7ae1,
568                                              0x3ea5c609d7d7560fLL);
569
570        // Stop the traversal abruptly, so that there will still be
571        // handlers on the stack when the dispatcher is destructed.
572
573        // No EndDIE call...
574      }
575      // No EndDIE call...
576    }
577    // No EndDIE call...
578  }
579}