Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Side by Side Diff: experimental/visual_studio_plugin/third_party/breakpad/common/stabs_reader_unittest.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // stabs_reader_unittest.cc: Unit tests for google_breakpad::StabsReader.
33
34 #include <a.out.h>
35 #include <cassert>
36 #include <cerrno>
37 #include <cstdarg>
38 #include <cstdlib>
39 #include <cstring>
40 #include <fstream>
41 #include <iomanip>
42 #include <iostream>
43 #include <map>
44 #include <sstream>
45 #include <stab.h>
46
47 #include "breakpad_googletest_includes.h"
48 #include "common/stabs_reader.h"
49
50 using std::istream;
51 using std::istringstream;
52 using std::map;
53 using std::ostream;
54 using std::ostringstream;
55 using std::string;
56
57 using ::testing::_;
58 using ::testing::Eq;
59 using ::testing::InSequence;
60 using ::testing::Return;
61 using ::testing::Sequence;
62 using ::testing::StrEq;
63
64 using google_breakpad::StabsHandler;
65 using google_breakpad::StabsReader;
66
67 namespace {
68
69 // Mock stabs file parser
70 //
71 // In order to test StabsReader, we parse a human-readable input file
72 // describing STABS entries into in-memory .stab and .stabstr
73 // sections, and then pass those to StabsReader to look at. The
74 // human-readable file is called a "mock stabs file".
75 //
76 // Except for compilation unit boundary lines (described below), each
77 // line of a mock stabs file should have the following form:
78 //
79 // TYPE OTHER DESC VALUE NAME
80 //
81 // where all data is Latin-1 bytes and fields are separated by single
82 // space characters, except for NAME, which may contain spaces and
83 // continues to the end of the line. The fields have the following
84 // meanings:
85 //
86 // - TYPE: the name of the stabs symbol type; like SO or FUN. These are
87 // the names from /usr/include/bits/stab.def, without the leading N_.
88 //
89 // - OTHER, DESC, VALUE: numeric values for the n_other, n_desc, and
90 // n_value fields of the stab. These can be decimal or hex,
91 // using C++ notation (10, 0x10)
92 //
93 // - NAME: textual data for the entry. STABS packs all kinds of
94 // interesting data into entries' NAME fields, so calling it a NAME
95 // is misleading, but that's how it is. For SO, this may be a
96 // filename; for FUN, this is the function name, plus type data; and
97 // so on.
98 //
99 // A compilation unit boundary line has the form:
100 //
101 // cu-boundary FILENAME
102
103 // I don't know if the whole parser/handler pattern is really worth
104 // the bureaucracy in this case. But just writing it out as
105 // old-fashioned functions wasn't astonishingly clear either, so it
106 // seemed worth a try.
107
108 // A handler class for mock stabs data.
109 class MockStabsHandler {
110 public:
111 MockStabsHandler() { }
112 virtual ~MockStabsHandler() { }
113 // The mock stabs parser calls this member function for each entry
114 // it parses, passing it the contents of the entry. If this function
115 // returns true, the parser continues; if it returns false, the parser
116 // stops, and its Process member function returns false.
117 virtual bool Entry(enum __stab_debug_code type, char other, short desc,
118 unsigned long value, const string &name) { return true; }
119 // Report a compilation unit boundary whose filename is FILENAME. As
120 // for the Entry function, this should return true to continue
121 // parsing, or false to stop processing.
122 virtual bool CUBoundary(const string &filename) { return true; }
123
124 // Report an error in parsing the mock stabs data. If this returns true,
125 // the parser continues; if it returns false, the parser stops and
126 // its Process member function returns false.
127 virtual bool Error(const char *format, ...) = 0;
128 };
129
130 // A class for parsing mock stabs files.
131 class MockStabsParser {
132 public:
133 // Create a parser reading input from STREAM and passing data to HANDLER.
134 // Use FILENAME when reporting errors.
135 MockStabsParser(const string &filename, istream *stream,
136 MockStabsHandler *handler);
137 // Parse data from the STREAM, invoking HANDLER->Entry for each
138 // entry we get. Return true if we parsed all the data succesfully,
139 // or false if we stopped early because Entry returned false, or if
140 // there were any errors during parsing.
141 bool Process();
142 private:
143 // A type for maps from stab type names ("SO", "SLINE", etc.) to
144 // n_type values.
145 typedef map<string, unsigned char> StabTypeNameTable;
146
147 // Initialize the table mapping STAB type names to n_type values.
148 void InitializeTypeNames();
149
150 // Parse LINE, one line of input from a mock stabs file, and pass
151 // its contents to handler_->Entry and return the boolean value that
152 // returns. If we encounter an error parsing the line, report it
153 // using handler->Error.
154 bool ParseLine(const string &line);
155
156 const string &filename_;
157 istream *stream_;
158 MockStabsHandler *handler_;
159 int line_number_;
160 StabTypeNameTable type_names_;
161 };
162
163 MockStabsParser::MockStabsParser(const string &filename, istream *stream,
164 MockStabsHandler *handler):
165 filename_(filename), stream_(stream), handler_(handler),
166 line_number_(0) {
167 InitializeTypeNames();
168 }
169
170 bool MockStabsParser::Process() {
171 // Iterate once per line, including a line at EOF without a
172 // terminating newline.
173 for(;;) {
174 string line;
175 getline(*stream_, line, '\n');
176 if (line.empty() && stream_->eof())
177 break;
178 line_number_++;
179 if (! ParseLine(line))
180 return false;
181 }
182 return true;
183 }
184
185 void MockStabsParser::InitializeTypeNames() {
186 // On GLIBC-based systems, <bits/stab.def> is a file containing a
187 // call to an unspecified macro __define_stab for each stab type.
188 // <stab.h> uses it to define the __stab_debug_code enum type. We
189 // use it here to initialize our mapping from type names to enum
190 // values.
191 //
192 // This isn't portable to non-GLIBC systems. Feel free to just
193 // hard-code the values if this becomes a problem.
194 # define __define_stab(name, code, str) type_names_[string(str)] = code;
195 # include <bits/stab.def>
196 # undef __define_stab
197 }
198
199 bool MockStabsParser::ParseLine(const string &line) {
200 istringstream linestream(line);
201 // Allow "0x" prefix for hex, and so on.
202 linestream.unsetf(istringstream::basefield);
203 // Parse and validate the stabs type.
204 string typeName;
205 linestream >> typeName;
206 if (typeName == "cu-boundary") {
207 if (linestream.peek() == ' ')
208 linestream.get();
209 string filename;
210 getline(linestream, filename, '\n');
211 return handler_->CUBoundary(filename);
212 } else {
213 StabTypeNameTable::const_iterator typeIt = type_names_.find(typeName);
214 if (typeIt == type_names_.end())
215 return handler_->Error("%s:%d: unrecognized stab type: %s\n",
216 filename_.c_str(), line_number_, typeName.c_str());
217 // These are int, not char and unsigned char, to ensure they're parsed
218 // as decimal numbers, not characters.
219 int otherInt, descInt;
220 unsigned long value;
221 linestream >> otherInt >> descInt >> value;
222 if (linestream.fail())
223 return handler_->Error("%s:%d: malformed mock stabs input line\n",
224 filename_.c_str(), line_number_);
225 if (linestream.peek() == ' ')
226 linestream.get();
227 string name;
228 getline(linestream, name, '\n');
229 return handler_->Entry(static_cast<__stab_debug_code>(typeIt->second),
230 otherInt, descInt, value, name);
231 }
232 }
233
234 // A class for constructing .stab sections.
235 //
236 // A .stab section is an array of struct nlist entries. These
237 // entries' n_un.n_strx fields are indices into an accompanying
238 // .stabstr section.
239 class StabSection {
240 public:
241 StabSection(): used_(0), size_(1) {
242 entries_ = (struct nlist *) malloc(sizeof(*entries_) * size_);
243 }
244 ~StabSection() { free(entries_); }
245
246 // Append a new 'struct nlist' entry to the end of the section, and
247 // return a pointer to it. This pointer is valid until the next
248 // call to Append. The caller should initialize the returned entry
249 // as needed.
250 struct nlist *Append();
251 // Set the first entry's n_desc field to COUNT, and set its n_value field
252 // to STRING_SIZE.
253 void SetHeader(short count, unsigned long string_size);
254 // Set SECTION to the contents of a .stab section holding the
255 // accumulated list of entries added with Append.
256 void GetSection(string *section);
257 // Clear the array, and prepare this StabSection to accumulate a fresh
258 // set of entries.
259 void Clear();
260
261 private:
262 // The array of stabs entries,
263 struct nlist *entries_;
264 // The number of elements of entries_ that are used, and the allocated size
265 // of the array.
266 size_t used_, size_;
267 };
268
269 struct nlist *StabSection::Append() {
270 if (used_ == size_) {
271 size_ *= 2;
272 entries_ = (struct nlist *) realloc(entries_, sizeof(*entries_) * size_);
273 }
274 assert(used_ < size_);
275 return &entries_[used_++];
276 }
277
278 void StabSection::SetHeader(short count, unsigned long string_size) {
279 assert(used_ >= 1);
280 entries_[0].n_desc = count;
281 entries_[0].n_value = string_size;
282 }
283
284 void StabSection::GetSection(string *section) {
285 section->assign(reinterpret_cast<char *>(entries_),
286 sizeof(*entries_) * used_);
287 }
288
289 void StabSection::Clear() {
290 used_ = 0;
291 size_ = 1;
292 entries_ = (struct nlist *) realloc(entries_, sizeof(*entries_) * size_);
293 }
294
295 // A class for building .stabstr sections.
296 //
297 // A .stabstr section is an array of characters containing a bunch of
298 // null-terminated strings. A string is identified by the index of
299 // its initial character in the array. The array always starts with a
300 // null byte, so that an index of zero refers to the empty string.
301 //
302 // This implementation also ensures that if two strings are equal, we
303 // assign them the same indices; most linkers do this, and some
304 // clients may rely upon it. (Note that this is not quite the same as
305 // ensuring that a string only appears once in the section; you could
306 // share space when one string is a suffix of another, but we don't.)
307 class StabstrSection {
308 public:
309 StabstrSection(): next_byte_(1) { string_indices_[""] = 0; }
310 // Ensure STR is present in the string section, and return its index.
311 size_t Insert(const string &str);
312 // Set SECTION to the contents of a .stabstr section in which the
313 // strings passed to Insert appear at the indices we promised.
314 void GetSection(string *section);
315 // Clear the contents of this StabstrSection, and prepare it to
316 // accumulate a new set of strings.
317 void Clear();
318 private:
319 // Maps from strings to .stabstr indices and back.
320 typedef map<string, size_t> StringToIndex;
321 typedef map<size_t, const string *> IndexToString;
322
323 // A map from strings to the indices we've assigned them.
324 StringToIndex string_indices_;
325
326 // The next unused byte in the section. The next string we add
327 // will get this index.
328 size_t next_byte_;
329 };
330
331 size_t StabstrSection::Insert(const string &str) {
332 StringToIndex::iterator it = string_indices_.find(str);
333 size_t index;
334 if (it != string_indices_.end()) {
335 index = it->second;
336 } else {
337 // This is the first time we've seen STR; add it to the table.
338 string_indices_[str] = next_byte_;
339 index = next_byte_;
340 next_byte_ += str.size() + 1;
341 }
342 return index;
343 }
344
345 void StabstrSection::GetSection(string *section) {
346 // First we have to invert the map.
347 IndexToString byIndex;
348 for (StringToIndex::const_iterator it = string_indices_.begin();
349 it != string_indices_.end(); it++)
350 byIndex[it->second] = &it->first;
351 // Now we build the .stabstr section.
352 section->clear();
353 for (IndexToString::const_iterator it = byIndex.begin();
354 it != byIndex.end(); it++) {
355 // Make sure we're actually assigning it the index we claim to be.
356 assert(it->first == section->size());
357 *section += *(it->second);
358 *section += '\0';
359 }
360 }
361
362 void StabstrSection::Clear() {
363 string_indices_.clear();
364 string_indices_[""] = 0;
365 next_byte_ = 1;
366 }
367
368 // A mock stabs parser handler class that builds .stab and .stabstr
369 // sections.
370 class StabsSectionsBuilder: public MockStabsHandler {
371 public:
372 // Construct a handler that will receive data from a MockStabsParser
373 // and construct .stab and .stabstr sections. FILENAME should be
374 // the name of the mock stabs input file; we use it in error
375 // messages.
376 StabsSectionsBuilder(const string &filename)
377 : filename_(filename), error_count_(0), has_header_(false),
378 entry_count_(0) { }
379
380 // Overridden virtual member functions.
381 bool Entry(enum __stab_debug_code type, char other, short desc,
382 unsigned long value, const string &name);
383 bool CUBoundary(const string &filename);
384 bool Error(const char *format, ...);
385
386 // Set SECTION to the contents of a .stab or .stabstr section
387 // reflecting the entries that have been passed to us via Entry.
388 void GetStab(string *section);
389 void GetStabstr(string *section);
390
391 private:
392 // Finish a compilation unit. If there are any entries accumulated in
393 // stab_ and stabstr_, add them as a new compilation unit to
394 // finished_cu_stabs_ and finished_cu_stabstr_, and then clear stab_ and
395 // stabstr_.
396 void FinishCU();
397
398 const string &filename_; // input filename, for error messages
399 int error_count_; // number of errors we've seen so far
400
401 // The following members accumulate the contents of a single compilation
402 // unit, possibly headed by an N_UNDF stab.
403 bool has_header_; // true if we have an N_UNDF header
404 int entry_count_; // the number of entries we've seen
405 StabSection stab_; // 'struct nlist' entries
406 StabstrSection stabstr_; // and the strings they love
407
408 // Accumulated .stab and .stabstr content for all compilation units.
409 string finished_cu_stab_, finished_cu_stabstr_;
410 };
411
412 bool StabsSectionsBuilder::Entry(enum __stab_debug_code type, char other,
413 short desc, unsigned long value,
414 const string &name) {
415 struct nlist *entry = stab_.Append();
416 entry->n_type = type;
417 entry->n_other = other;
418 entry->n_desc = desc;
419 entry->n_value = value;
420 entry->n_un.n_strx = stabstr_.Insert(name);
421 entry_count_++;
422 return true;
423 }
424
425 bool StabsSectionsBuilder::CUBoundary(const string &filename) {
426 FinishCU();
427 // Add a header for the compilation unit.
428 assert(!has_header_);
429 assert(entry_count_ == 0);
430 struct nlist *entry = stab_.Append();
431 entry->n_type = N_UNDF;
432 entry->n_other = 0;
433 entry->n_desc = 0; // will be set to number of entries
434 entry->n_value = 0; // will be set to size of .stabstr data
435 entry->n_un.n_strx = stabstr_.Insert(filename);
436 has_header_ = true;
437 // The N_UNDF header isn't included in the symbol count, so we
438 // shouldn't bump entry_count_ here.
439 return true;
440 }
441
442 void StabsSectionsBuilder::FinishCU() {
443 if (entry_count_ > 0) {
444 // Get the strings first, so we can record their size in the header.
445 string stabstr;
446 stabstr_.GetSection(&stabstr);
447 finished_cu_stabstr_ += stabstr;
448
449 // Initialize our header, if we have one, and extract the .stab data.
450 if (has_header_)
451 stab_.SetHeader(entry_count_, stabstr.size());
452 string stab;
453 stab_.GetSection(&stab);
454 finished_cu_stab_ += stab;
455 }
456
457 stab_.Clear();
458 stabstr_.Clear();
459 has_header_ = false;
460 entry_count_ = 0;
461 }
462
463 bool StabsSectionsBuilder::Error(const char *format, ...) {
464 va_list args;
465 va_start(args, format);
466 vfprintf(stderr, format, args);
467 va_end(args);
468 error_count_++;
469 if (error_count_ >= 20) {
470 fprintf(stderr,
471 "%s: lots of errors; is this really a mock stabs file?\n",
472 filename_.c_str());
473 return false;
474 }
475 return true;
476 }
477
478 void StabsSectionsBuilder::GetStab(string *section) {
479 FinishCU();
480 *section = finished_cu_stab_;
481 }
482
483 void StabsSectionsBuilder::GetStabstr(string *section) {
484 FinishCU();
485 *section = finished_cu_stabstr_;
486 }
487
488 class MockStabsReaderHandler: public StabsHandler {
489 public:
490 MOCK_METHOD3(StartCompilationUnit,
491 bool(const char *, uint64_t, const char *));
492 MOCK_METHOD1(EndCompilationUnit, bool(uint64_t));
493 MOCK_METHOD2(StartFunction, bool(const std::string &, uint64_t));
494 MOCK_METHOD1(EndFunction, bool(uint64_t));
495 MOCK_METHOD3(Line, bool(uint64_t, const char *, int));
496 void Warning(const char *format, ...) { MockWarning(format); }
497 MOCK_METHOD1(MockWarning, void(const char *));
498 };
499
500 // Create a StabsReader to parse the mock stabs data in INPUT_FILE,
501 // passing the parsed information to HANDLER. If all goes well, return
502 // the result of calling the reader's Process member function.
503 // Otherwise, return false. INPUT_FILE should be relative to the top
504 // of the source tree.
505 static bool ApplyHandlerToMockStabsData(StabsHandler *handler,
506 const string &input_file) {
507 string full_input_file
508 = string(getenv("srcdir") ? getenv("srcdir") : ".") + "/" + input_file;
509
510 // Open the input file.
511 std::ifstream stream(full_input_file.c_str());
512 if (stream.fail()) {
513 fprintf(stderr, "error opening mock stabs input file %s: %s\n",
514 full_input_file.c_str(), strerror(errno));
515 return false;
516 }
517
518 // Parse the mock stabs data, and produce stabs sections to use as
519 // test input to the reader.
520 StabsSectionsBuilder builder(full_input_file);
521 MockStabsParser mock_parser(full_input_file, &stream, &builder);
522 if (!mock_parser.Process())
523 return false;
524 string stab, stabstr;
525 builder.GetStab(&stab);
526 builder.GetStabstr(&stabstr);
527
528 // Run the parser on the test input, passing whatever we find to HANDLER.
529 StabsReader reader(
530 reinterpret_cast<const uint8_t *>(stab.data()), stab.size(),
531 reinterpret_cast<const uint8_t *>(stabstr.data()), stabstr.size(),
532 handler);
533 return reader.Process();
534 }
535
536 TEST(StabsReader, MockStabsInput) {
537 MockStabsReaderHandler mock_handler;
538
539 {
540 InSequence s;
541
542 EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file1.c"),
543 0x42, StrEq("builddir1/")))
544 .WillOnce(Return(true));
545 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0x62))
546 .WillOnce(Return(true));
547 EXPECT_CALL(mock_handler, Line(0xe4, StrEq("file1.c"), 91))
548 .WillOnce(Return(true));
549 EXPECT_CALL(mock_handler, Line(0x164, StrEq("header.h"), 111))
550 .WillOnce(Return(true));
551 EXPECT_CALL(mock_handler, EndFunction(0x112))
552 .WillOnce(Return(true));
553 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0x112))
554 .WillOnce(Return(true));
555 EXPECT_CALL(mock_handler, Line(0x234, StrEq("header.h"), 131))
556 .WillOnce(Return(true));
557 EXPECT_CALL(mock_handler, Line(0x254, StrEq("file1.c"), 151))
558 .WillOnce(Return(true));
559 EXPECT_CALL(mock_handler, EndFunction(0x152))
560 .WillOnce(Return(true));
561 EXPECT_CALL(mock_handler, EndCompilationUnit(0x152))
562 .WillOnce(Return(true));
563 EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"),
564 0x182, NULL))
565 .WillOnce(Return(true));
566 EXPECT_CALL(mock_handler, EndCompilationUnit(0x192))
567 .WillOnce(Return(true));
568 }
569
570 ASSERT_TRUE(ApplyHandlerToMockStabsData(
571 &mock_handler,
572 "common/testdata/stabs_reader_unittest.input1"));
573 }
574
575 TEST(StabsReader, AbruptCU) {
576 MockStabsReaderHandler mock_handler;
577
578 {
579 InSequence s;
580
581 EXPECT_CALL(mock_handler,
582 StartCompilationUnit(StrEq("file2-1.c"), 0x12, NULL))
583 .WillOnce(Return(true));
584 EXPECT_CALL(mock_handler, EndCompilationUnit(NULL))
585 .WillOnce(Return(true));
586 }
587
588 ASSERT_TRUE(ApplyHandlerToMockStabsData(
589 &mock_handler,
590 "common/testdata/stabs_reader_unittest.input2"));
591 }
592
593 TEST(StabsReader, AbruptFunction) {
594 MockStabsReaderHandler mock_handler;
595
596 {
597 InSequence s;
598
599 EXPECT_CALL(mock_handler,
600 StartCompilationUnit(StrEq("file3-1.c"), 0x12, NULL))
601 .WillOnce(Return(true));
602 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0x22))
603 .WillOnce(Return(true));
604 EXPECT_CALL(mock_handler, EndFunction(NULL))
605 .WillOnce(Return(true));
606 EXPECT_CALL(mock_handler, EndCompilationUnit(NULL))
607 .WillOnce(Return(true));
608 }
609
610 ASSERT_TRUE(ApplyHandlerToMockStabsData(
611 &mock_handler,
612 "common/testdata/stabs_reader_unittest.input3"));
613 }
614
615 TEST(StabsReader, NoCU) {
616 MockStabsReaderHandler mock_handler;
617
618 EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _))
619 .Times(0);
620 EXPECT_CALL(mock_handler, StartFunction(_, _))
621 .Times(0);
622
623 ASSERT_TRUE(ApplyHandlerToMockStabsData(
624 &mock_handler,
625 "common/testdata/stabs_reader_unittest.input4"));
626
627 }
628
629 TEST(StabsReader, NoCUEnd) {
630 MockStabsReaderHandler mock_handler;
631
632 {
633 InSequence s;
634
635 EXPECT_CALL(mock_handler,
636 StartCompilationUnit(StrEq("file5-1.c"), 0x12, NULL))
637 .WillOnce(Return(true));
638 EXPECT_CALL(mock_handler, EndCompilationUnit(NULL))
639 .WillOnce(Return(true));
640 EXPECT_CALL(mock_handler,
641 StartCompilationUnit(StrEq("file5-2.c"), 0x22, NULL))
642 .WillOnce(Return(true));
643 EXPECT_CALL(mock_handler, EndCompilationUnit(NULL))
644 .WillOnce(Return(true));
645 }
646
647 ASSERT_TRUE(ApplyHandlerToMockStabsData(
648 &mock_handler,
649 "common/testdata/stabs_reader_unittest.input5"));
650
651 }
652
653 TEST(StabsReader, MultipleCUs) {
654 MockStabsReaderHandler mock_handler;
655
656 {
657 InSequence s;
658 EXPECT_CALL(mock_handler,
659 StartCompilationUnit(StrEq("antimony"), 0x12, NULL))
660 .WillOnce(Return(true));
661 EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x22))
662 .WillOnce(Return(true));
663 EXPECT_CALL(mock_handler, EndFunction(0x32))
664 .WillOnce(Return(true));
665 EXPECT_CALL(mock_handler, EndCompilationUnit(0x32))
666 .WillOnce(Return(true));
667 EXPECT_CALL(mock_handler,
668 StartCompilationUnit(StrEq("aluminum"), 0x42, NULL))
669 .WillOnce(Return(true));
670 EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0x52))
671 .WillOnce(Return(true));
672 EXPECT_CALL(mock_handler, EndFunction(0x62))
673 .WillOnce(Return(true));
674 EXPECT_CALL(mock_handler, EndCompilationUnit(0x62))
675 .WillOnce(Return(true));
676 }
677
678 ASSERT_TRUE(ApplyHandlerToMockStabsData(
679 &mock_handler,
680 "common/testdata/stabs_reader_unittest.input6"));
681 }
682
683 // name duplication
684
685 } // anonymous namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698