17daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Copyright (c) 2006, Google Inc.
27daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// All rights reserved.
3cce3492afc263be86236600d41dca40be7224ee7bryner//
47daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// Redistribution and use in source and binary forms, with or without
57daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// modification, are permitted provided that the following conditions are
67daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// met:
7cce3492afc263be86236600d41dca40be7224ee7bryner//
87daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions of source code must retain the above copyright
97daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// notice, this list of conditions and the following disclaimer.
107daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Redistributions in binary form must reproduce the above
117daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// copyright notice, this list of conditions and the following disclaimer
127daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// in the documentation and/or other materials provided with the
137daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// distribution.
147daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai//     * Neither the name of Google Inc. nor the names of its
157daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// contributors may be used to endorse or promote products derived from
167daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// this software without specific prior written permission.
17cce3492afc263be86236600d41dca40be7224ee7bryner//
187daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
237daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
247daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
267daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
277daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
287daf246e4baf0837e25429668cc23e92b6afe3b3mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29cce3492afc263be86236600d41dca40be7224ee7bryner
30cce3492afc263be86236600d41dca40be7224ee7bryner// Unit test for MinidumpProcessor.  Uses a pre-generated minidump and
31cce3492afc263be86236600d41dca40be7224ee7bryner// corresponding symbol file, and checks the stack frames for correctness.
32cce3492afc263be86236600d41dca40be7224ee7bryner
33e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdlib.h>
34e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek
35cce3492afc263be86236600d41dca40be7224ee7bryner#include <string>
362ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid#include <iostream>
372ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid#include <fstream>
3819374d263649a51c8bb56f2f01d3466905847670nealsid#include <map>
39a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com#include <utility>
40e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek
41b56cfa067add059d0894433393e798fe0604970enealsid#include "breakpad_googletest_includes.h"
422cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
434e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h"
44e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/basic_source_line_resolver.h"
45e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/call_stack.h"
46e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/code_module.h"
47e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/code_modules.h"
48b56cfa067add059d0894433393e798fe0604970enealsid#include "google_breakpad/processor/minidump.h"
49e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/minidump_processor.h"
50e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/process_state.h"
51e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/stack_frame.h"
52e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/symbol_supplier.h"
5332b802dba3d49880a0414d066e71cdc20ab09901mmentovai#include "processor/logging.h"
54e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com#include "processor/stackwalker_unittest_utils.h"
55cce3492afc263be86236600d41dca40be7224ee7bryner
5619374d263649a51c8bb56f2f01d3466905847670nealsidusing std::map;
5719374d263649a51c8bb56f2f01d3466905847670nealsid
58b56cfa067add059d0894433393e798fe0604970enealsidnamespace google_breakpad {
59b56cfa067add059d0894433393e798fe0604970enealsidclass MockMinidump : public Minidump {
60b56cfa067add059d0894433393e798fe0604970enealsid public:
61b56cfa067add059d0894433393e798fe0604970enealsid  MockMinidump() : Minidump("") {
62b56cfa067add059d0894433393e798fe0604970enealsid  }
63b56cfa067add059d0894433393e798fe0604970enealsid
64cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  MOCK_METHOD0(Read, bool());
65b56cfa067add059d0894433393e798fe0604970enealsid  MOCK_CONST_METHOD0(path, string());
66cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  MOCK_CONST_METHOD0(header, const MDRawHeader*());
67cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  MOCK_METHOD0(GetThreadList, MinidumpThreadList*());
68e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetSystemInfo, MinidumpSystemInfo*());
69ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MOCK_METHOD0(GetMiscInfo, MinidumpMiscInfo*());
70e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetBreakpadInfo, MinidumpBreakpadInfo*());
71e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetException, MinidumpException*());
72e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetAssertion, MinidumpAssertion*());
73e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetModuleList, MinidumpModuleList*());
7402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MOCK_METHOD0(GetMemoryList, MinidumpMemoryList*());
75b56cfa067add059d0894433393e798fe0604970enealsid};
76e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
77e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comclass MockMinidumpThreadList : public MinidumpThreadList {
78e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com public:
79e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThreadList() : MinidumpThreadList(NULL) {}
80e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
81e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_CONST_METHOD0(thread_count, unsigned int());
82e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_CONST_METHOD1(GetThreadAtIndex, MinidumpThread*(unsigned int));
83e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com};
84e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
8502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.comclass MockMinidumpMemoryList : public MinidumpMemoryList {
8602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com public:
8702ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MockMinidumpMemoryList() : MinidumpMemoryList(NULL) {}
8802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
8902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MOCK_METHOD1(GetMemoryRegionForAddress, MinidumpMemoryRegion*(uint64_t));
9002ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com};
9102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
92e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comclass MockMinidumpThread : public MinidumpThread {
93e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com public:
94e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThread() : MinidumpThread(NULL) {}
95e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
966162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  MOCK_CONST_METHOD1(GetThreadID, bool(uint32_t*));
97e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetContext, MinidumpContext*());
98e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MOCK_METHOD0(GetMemory, MinidumpMemoryRegion*());
9902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MOCK_CONST_METHOD0(GetStartOfStackMemoryRange, uint64_t());
100e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com};
101e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
102e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// This is crappy, but MinidumpProcessor really does want a
103e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// MinidumpMemoryRegion.
104e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comclass MockMinidumpMemoryRegion : public MinidumpMemoryRegion {
105e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com public:
1066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  MockMinidumpMemoryRegion(uint64_t base, const string& contents) :
107e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      MinidumpMemoryRegion(NULL) {
108e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    region_.Init(base, contents);
109e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
110e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
1116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint64_t GetBase() const { return region_.GetBase(); }
1126162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t GetSize() const { return region_.GetSize(); }
113e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
1146162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  bool GetMemoryAtAddress(uint64_t address, uint8_t  *value) const {
115e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    return region_.GetMemoryAtAddress(address, value);
116e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
1176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
118e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    return region_.GetMemoryAtAddress(address, value);
119e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
1206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
121e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    return region_.GetMemoryAtAddress(address, value);
122e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
1236162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
124e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    return region_.GetMemoryAtAddress(address, value);
125e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
126e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
127e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMemoryRegion region_;
128e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com};
129e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
130ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org// A test miscelaneous info stream, just returns values from the
131ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org// MDRawMiscInfo fed to it.
132ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.orgclass TestMinidumpMiscInfo : public MinidumpMiscInfo {
133ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org public:
134ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  explicit TestMinidumpMiscInfo(const MDRawMiscInfo& misc_info) :
135ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org      MinidumpMiscInfo(NULL) {
136ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org    valid_ = true;
137ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org    misc_info_ = misc_info;
138ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  }
139ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org};
140ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
141e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com}  // namespace google_breakpad
142b56cfa067add059d0894433393e798fe0604970enealsid
1438647dde8cc03ef16b565dccc75574ee5f0d9cf72mmentovainamespace {
1448647dde8cc03ef16b565dccc75574ee5f0d9cf72mmentovai
145e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::BasicSourceLineResolver;
146e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::CallStack;
147e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::CodeModule;
148e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MinidumpContext;
149e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MinidumpMemoryRegion;
150ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.orgusing google_breakpad::MinidumpMiscInfo;
151e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::MinidumpProcessor;
152e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MinidumpSystemInfo;
153b56cfa067add059d0894433393e798fe0604970enealsidusing google_breakpad::MinidumpThreadList;
154b56cfa067add059d0894433393e798fe0604970enealsidusing google_breakpad::MinidumpThread;
155b56cfa067add059d0894433393e798fe0604970enealsidusing google_breakpad::MockMinidump;
15602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.comusing google_breakpad::MockMinidumpMemoryList;
157e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MockMinidumpMemoryRegion;
158e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MockMinidumpThread;
159e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing google_breakpad::MockMinidumpThreadList;
160e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::ProcessState;
161e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::scoped_ptr;
162e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::SymbolSupplier;
163e5dc60822e5938fea2ae892ccddb906641ba174emmentovaiusing google_breakpad::SystemInfo;
16419374d263649a51c8bb56f2f01d3466905847670nealsidusing ::testing::_;
16584946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.comusing ::testing::AnyNumber;
166e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing ::testing::DoAll;
16719374d263649a51c8bb56f2f01d3466905847670nealsidusing ::testing::Mock;
16819374d263649a51c8bb56f2f01d3466905847670nealsidusing ::testing::Ne;
16919374d263649a51c8bb56f2f01d3466905847670nealsidusing ::testing::Property;
170b56cfa067add059d0894433393e798fe0604970enealsidusing ::testing::Return;
171e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comusing ::testing::SetArgumentPointee;
17297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
17397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistatic const char *kSystemInfoOS = "Windows NT";
17497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistatic const char *kSystemInfoOSShort = "windows";
17597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistatic const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2";
17697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistatic const char *kSystemInfoCPU = "x86";
17797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovaistatic const char *kSystemInfoCPUInfo =
17897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    "GenuineIntel family 6 model 13 stepping 8";
179cce3492afc263be86236600d41dca40be7224ee7bryner
18097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai#define ASSERT_TRUE_ABORT(cond) \
18197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  if (!(cond)) {                                                        \
18297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \
18397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    abort(); \
18497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  }
18597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
18697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai#define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2))
18797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
188cce3492afc263be86236600d41dca40be7224ee7brynerclass TestSymbolSupplier : public SymbolSupplier {
189cce3492afc263be86236600d41dca40be7224ee7bryner public:
190f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  TestSymbolSupplier() : interrupt_(false) {}
191f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
192f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  virtual SymbolResult GetSymbolFile(const CodeModule *module,
19397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai                                     const SystemInfo *system_info,
194f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner                                     string *symbol_file);
195f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
1962ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid  virtual SymbolResult GetSymbolFile(const CodeModule *module,
1972ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid                                     const SystemInfo *system_info,
1982ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid                                     string *symbol_file,
1992ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid                                     string *symbol_data);
2002ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid
2015b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
2025b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                            const SystemInfo *system_info,
2035b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                            string *symbol_file,
2042d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                            char **symbol_data,
2052d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                            size_t *symbol_data_size);
2065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
207a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  virtual void FreeSymbolData(const CodeModule *module);
208a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
209f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  // When set to true, causes the SymbolSupplier to return INTERRUPT
210f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
211f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
212f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner private:
213f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  bool interrupt_;
214a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  map<string, char *> memory_buffers_;
215cce3492afc263be86236600d41dca40be7224ee7bryner};
216cce3492afc263be86236600d41dca40be7224ee7bryner
217f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3brynerSymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
21897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    const CodeModule *module,
21997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    const SystemInfo *system_info,
22097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai    string *symbol_file) {
22197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_TRUE_ABORT(module);
22297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_TRUE_ABORT(system_info);
22397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ_ABORT(system_info->cpu, kSystemInfoCPU);
22497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ_ABORT(system_info->cpu_info, kSystemInfoCPUInfo);
22597d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ_ABORT(system_info->os, kSystemInfoOS);
22697d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ_ABORT(system_info->os_short, kSystemInfoOSShort);
22797d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ_ABORT(system_info->os_version, kSystemInfoOSVersion);
22897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai
229f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  if (interrupt_) {
230f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner    return INTERRUPT;
231f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  }
232f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
233e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  if (module && module->code_file() == "c:\\test_app.exe") {
234f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner      *symbol_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
235f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner                     "/src/processor/testdata/symbols/test_app.pdb/" +
236f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner                     module->debug_identifier() +
237f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner                     "/test_app.sym";
238f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner    return FOUND;
239cce3492afc263be86236600d41dca40be7224ee7bryner  }
240cce3492afc263be86236600d41dca40be7224ee7bryner
241f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  return NOT_FOUND;
242cce3492afc263be86236600d41dca40be7224ee7bryner}
243cce3492afc263be86236600d41dca40be7224ee7bryner
2442ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsidSymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
2452ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    const CodeModule *module,
2462ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    const SystemInfo *system_info,
2472ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    string *symbol_file,
2482ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    string *symbol_data) {
2492ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid  SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info,
2502ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid                                                 symbol_file);
2512ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid  if (s == FOUND) {
2522ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    std::ifstream in(symbol_file->c_str());
2534e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com    std::getline(in, *symbol_data, string::traits_type::to_char_type(
2544e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com                     string::traits_type::eof()));
2552ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid    in.close();
2562ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid  }
2572ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid
2582ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid  return s;
2592ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid}
2602ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid
2615b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comSymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
2625b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const CodeModule *module,
2635b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const SystemInfo *system_info,
2645b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    string *symbol_file,
2652d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    char **symbol_data,
2662d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    size_t *symbol_data_size) {
2675b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  string symbol_data_string;
2685b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  SymbolSupplier::SymbolResult s = GetSymbolFile(module,
2695b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                                 system_info,
2705b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                                 symbol_file,
2715b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                                 &symbol_data_string);
2725b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (s == FOUND) {
2732d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    *symbol_data_size = symbol_data_string.size() + 1;
2742d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    *symbol_data = new char[*symbol_data_size];
275a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    if (*symbol_data == NULL) {
276a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com      BPLOG(ERROR) << "Memory allocation failed for module: "
2772d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                   << module->code_file() << " size: " << *symbol_data_size;
278a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com      return INTERRUPT;
279a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    }
2802d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size());
2812d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    (*symbol_data)[symbol_data_string.size()] = '\0';
282a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    memory_buffers_.insert(make_pair(module->code_file(), *symbol_data));
2835b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
2845b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2855b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return s;
2865b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
2875b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
288a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.comvoid TestSymbolSupplier::FreeSymbolData(const CodeModule *module) {
289a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  map<string, char *>::iterator it = memory_buffers_.find(module->code_file());
290a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (it != memory_buffers_.end()) {
291a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] it->second;
292a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    memory_buffers_.erase(it);
293a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
294a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com}
295a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
296e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// A test system info stream, just returns values from the
297e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// MDRawSystemInfo fed to it.
298e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comclass TestMinidumpSystemInfo : public MinidumpSystemInfo {
29919374d263649a51c8bb56f2f01d3466905847670nealsid public:
30002ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  explicit TestMinidumpSystemInfo(MDRawSystemInfo info) :
301e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      MinidumpSystemInfo(NULL) {
302e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    valid_ = true;
303e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    system_info_ = info;
304e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    csd_version_ = new string("");
305e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
306e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com};
307e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
308e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// A test minidump context, just returns the MDRawContextX86
309e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com// fed to it.
310e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comclass TestMinidumpContext : public MinidumpContext {
31102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com public:
31202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  explicit TestMinidumpContext(const MDRawContextX86& context) :
31302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      MinidumpContext(NULL) {
314e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    valid_ = true;
315c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextX86(new MDRawContextX86(context));
316c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org    SetContextFlags(MD_CONTEXT_X86);
317e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  }
31819374d263649a51c8bb56f2f01d3466905847670nealsid};
319b56cfa067add059d0894433393e798fe0604970enealsid
320b56cfa067add059d0894433393e798fe0604970enealsidclass MinidumpProcessorTest : public ::testing::Test {
321b56cfa067add059d0894433393e798fe0604970enealsid};
322b56cfa067add059d0894433393e798fe0604970enealsid
323b56cfa067add059d0894433393e798fe0604970enealsidTEST_F(MinidumpProcessorTest, TestCorruptMinidumps) {
324b56cfa067add059d0894433393e798fe0604970enealsid  MockMinidump dump;
325b56cfa067add059d0894433393e798fe0604970enealsid  TestSymbolSupplier supplier;
326b56cfa067add059d0894433393e798fe0604970enealsid  BasicSourceLineResolver resolver;
327b56cfa067add059d0894433393e798fe0604970enealsid  MinidumpProcessor processor(&supplier, &resolver);
328b56cfa067add059d0894433393e798fe0604970enealsid  ProcessState state;
329b56cfa067add059d0894433393e798fe0604970enealsid
3309fc581226040d32b6f0d6b171378d5ea0cdf8fb1jessicag.feedback@gmail.com  EXPECT_EQ(processor.Process("nonexistent minidump", &state),
331b56cfa067add059d0894433393e798fe0604970enealsid            google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND);
332b56cfa067add059d0894433393e798fe0604970enealsid
333b56cfa067add059d0894433393e798fe0604970enealsid  EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
334b56cfa067add059d0894433393e798fe0604970enealsid  EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
335b56cfa067add059d0894433393e798fe0604970enealsid
336b56cfa067add059d0894433393e798fe0604970enealsid  MDRawHeader fakeHeader;
337b56cfa067add059d0894433393e798fe0604970enealsid  fakeHeader.time_date_stamp = 0;
33802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(dump, header()).
33902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      WillOnce(Return(reinterpret_cast<MDRawHeader*>(NULL))).
340b56cfa067add059d0894433393e798fe0604970enealsid      WillRepeatedly(Return(&fakeHeader));
341e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
342b56cfa067add059d0894433393e798fe0604970enealsid  EXPECT_EQ(processor.Process(&dump, &state),
343b56cfa067add059d0894433393e798fe0604970enealsid            google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER);
344b56cfa067add059d0894433393e798fe0604970enealsid
345b56cfa067add059d0894433393e798fe0604970enealsid  EXPECT_CALL(dump, GetThreadList()).
34602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      WillOnce(Return(reinterpret_cast<MinidumpThreadList*>(NULL)));
347e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, GetSystemInfo()).
34802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      WillRepeatedly(Return(reinterpret_cast<MinidumpSystemInfo*>(NULL)));
349e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
350b56cfa067add059d0894433393e798fe0604970enealsid  EXPECT_EQ(processor.Process(&dump, &state),
351b56cfa067add059d0894433393e798fe0604970enealsid            google_breakpad::PROCESS_ERROR_NO_THREAD_LIST);
352b56cfa067add059d0894433393e798fe0604970enealsid}
353b56cfa067add059d0894433393e798fe0604970enealsid
35419374d263649a51c8bb56f2f01d3466905847670nealsid// This test case verifies that the symbol supplier is only consulted
35519374d263649a51c8bb56f2f01d3466905847670nealsid// once per minidump per module.
35619374d263649a51c8bb56f2f01d3466905847670nealsidTEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
35719374d263649a51c8bb56f2f01d3466905847670nealsid  MockSymbolSupplier supplier;
35819374d263649a51c8bb56f2f01d3466905847670nealsid  BasicSourceLineResolver resolver;
35919374d263649a51c8bb56f2f01d3466905847670nealsid  MinidumpProcessor processor(&supplier, &resolver);
36019374d263649a51c8bb56f2f01d3466905847670nealsid
36119374d263649a51c8bb56f2f01d3466905847670nealsid  string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
36219374d263649a51c8bb56f2f01d3466905847670nealsid                         "/src/processor/testdata/minidump2.dmp";
36319374d263649a51c8bb56f2f01d3466905847670nealsid  ProcessState state;
3645b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  EXPECT_CALL(supplier, GetCStringSymbolData(
36519374d263649a51c8bb56f2f01d3466905847670nealsid      Property(&google_breakpad::CodeModule::code_file,
36619374d263649a51c8bb56f2f01d3466905847670nealsid               "c:\\test_app.exe"),
3672d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
3685b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  EXPECT_CALL(supplier, GetCStringSymbolData(
36919374d263649a51c8bb56f2f01d3466905847670nealsid      Property(&google_breakpad::CodeModule::code_file,
37019374d263649a51c8bb56f2f01d3466905847670nealsid               Ne("c:\\test_app.exe")),
3712d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
37284946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  // Avoid GMOCK WARNING "Uninteresting mock function call - returning
37384946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  // directly" for FreeSymbolData().
37484946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
37519374d263649a51c8bb56f2f01d3466905847670nealsid  ASSERT_EQ(processor.Process(minidump_file, &state),
37619374d263649a51c8bb56f2f01d3466905847670nealsid            google_breakpad::PROCESS_OK);
37719374d263649a51c8bb56f2f01d3466905847670nealsid
37819374d263649a51c8bb56f2f01d3466905847670nealsid  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&supplier));
37919374d263649a51c8bb56f2f01d3466905847670nealsid
38019374d263649a51c8bb56f2f01d3466905847670nealsid  // We need to verify that across minidumps, the processor will refetch
38119374d263649a51c8bb56f2f01d3466905847670nealsid  // symbol files, even with the same symbol supplier.
3825b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  EXPECT_CALL(supplier, GetCStringSymbolData(
38319374d263649a51c8bb56f2f01d3466905847670nealsid      Property(&google_breakpad::CodeModule::code_file,
38419374d263649a51c8bb56f2f01d3466905847670nealsid               "c:\\test_app.exe"),
3852d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
3865b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  EXPECT_CALL(supplier, GetCStringSymbolData(
38719374d263649a51c8bb56f2f01d3466905847670nealsid      Property(&google_breakpad::CodeModule::code_file,
38819374d263649a51c8bb56f2f01d3466905847670nealsid               Ne("c:\\test_app.exe")),
3892d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com      _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
39084946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  // Avoid GMOCK WARNING "Uninteresting mock function call - returning
39184946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  // directly" for FreeSymbolData().
39284946cd973502ae101821c9d17d16ce1572dda00ted.mielczarek@gmail.com  EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
39319374d263649a51c8bb56f2f01d3466905847670nealsid  ASSERT_EQ(processor.Process(minidump_file, &state),
39419374d263649a51c8bb56f2f01d3466905847670nealsid            google_breakpad::PROCESS_OK);
39519374d263649a51c8bb56f2f01d3466905847670nealsid}
39619374d263649a51c8bb56f2f01d3466905847670nealsid
397b56cfa067add059d0894433393e798fe0604970enealsidTEST_F(MinidumpProcessorTest, TestBasicProcessing) {
398cce3492afc263be86236600d41dca40be7224ee7bryner  TestSymbolSupplier supplier;
399fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner  BasicSourceLineResolver resolver;
400fd38d48e6d5e56cb66b0fa0f7e25f840a83dac5cbryner  MinidumpProcessor processor(&supplier, &resolver);
401cce3492afc263be86236600d41dca40be7224ee7bryner
402cce3492afc263be86236600d41dca40be7224ee7bryner  string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
403cce3492afc263be86236600d41dca40be7224ee7bryner                         "/src/processor/testdata/minidump2.dmp";
404cce3492afc263be86236600d41dca40be7224ee7bryner
405f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ProcessState state;
406f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(processor.Process(minidump_file, &state),
407b56cfa067add059d0894433393e798fe0604970enealsid            google_breakpad::PROCESS_OK);
40897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(state.system_info()->os, kSystemInfoOS);
40997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort);
41097d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion);
41197d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU);
41297d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo);
413f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_TRUE(state.crashed());
414e4cc9b12ec2aaef10e60f50e7f55ee3881369bd6nealsid  ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
4155ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(state.crash_address(), 0x45U);
4165ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(state.threads()->size(), size_t(1));
417f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(state.requesting_thread(), 0);
418ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_EQ(1171480435U, state.time_date_stamp());
419ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_EQ(1171480435U, state.process_create_time());
420f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner
421f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  CallStack *stack = state.threads()->at(0);
422e5468b8a49ac6a4e5acb9d4003838e3e323f85e4mmentovai  ASSERT_TRUE(stack);
4235ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(stack->frames()->size(), 4U);
424cce3492afc263be86236600d41dca40be7224ee7bryner
425db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  ASSERT_TRUE(stack->frames()->at(0)->module);
4265ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000U);
427e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(0)->module->code_file(), "c:\\test_app.exe");
42897d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai  ASSERT_EQ(stack->frames()->at(0)->function_name,
42997d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai            "`anonymous namespace'::CrashFunction");
430d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(0)->source_file_name, "c:\\test_app.cc");
431e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(0)->source_line, 58);
432cce3492afc263be86236600d41dca40be7224ee7bryner
433db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  ASSERT_TRUE(stack->frames()->at(1)->module);
4345ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(stack->frames()->at(1)->module->base_address(), 0x400000U);
435e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(1)->module->code_file(), "c:\\test_app.exe");
436d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(1)->function_name, "main");
437d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(1)->source_file_name, "c:\\test_app.cc");
438e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(1)->source_line, 65);
439cce3492afc263be86236600d41dca40be7224ee7bryner
440cce3492afc263be86236600d41dca40be7224ee7bryner  // This comes from the CRT
441db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  ASSERT_TRUE(stack->frames()->at(2)->module);
4425ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(stack->frames()->at(2)->module->base_address(), 0x400000U);
443e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(2)->module->code_file(), "c:\\test_app.exe");
444d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(2)->function_name, "__tmainCRTStartup");
445d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(2)->source_file_name,
446e5dc60822e5938fea2ae892ccddb906641ba174emmentovai            "f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c");
447e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(stack->frames()->at(2)->source_line, 327);
448cce3492afc263be86236600d41dca40be7224ee7bryner
449cce3492afc263be86236600d41dca40be7224ee7bryner  // No debug info available for kernel32.dll
450db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  ASSERT_TRUE(stack->frames()->at(3)->module);
4515ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(stack->frames()->at(3)->module->base_address(), 0x7c800000U);
452db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai  ASSERT_EQ(stack->frames()->at(3)->module->code_file(),
453cce3492afc263be86236600d41dca40be7224ee7bryner            "C:\\WINDOWS\\system32\\kernel32.dll");
454d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_TRUE(stack->frames()->at(3)->function_name.empty());
455d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_TRUE(stack->frames()->at(3)->source_file_name.empty());
456d119a921ea611dc38cfcb7411759ddf2c688603fmmentovai  ASSERT_EQ(stack->frames()->at(3)->source_line, 0);
457cce3492afc263be86236600d41dca40be7224ee7bryner
4585ebd6507e3a72bba06f7e15ca4df08a6aff3fd6bjimblandy  ASSERT_EQ(state.modules()->module_count(), 13U);
459f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_TRUE(state.modules()->GetMainModule());
460e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  ASSERT_EQ(state.modules()->GetMainModule()->code_file(), "c:\\test_app.exe");
461f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_FALSE(state.modules()->GetModuleForAddress(0));
462f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(state.modules()->GetMainModule(),
463f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner            state.modules()->GetModuleForAddress(0x400000));
464f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(state.modules()->GetModuleForAddress(0x7c801234)->debug_file(),
465db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            "kernel32.pdb");
466f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(),
467db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai            "5.1.2600.2622");
468db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai
4698d2c518c0b1dd6e1c956340759983f0464d356d5nealsid  // Test that disabled exploitability engine defaults to
4708d2c518c0b1dd6e1c956340759983f0464d356d5nealsid  // EXPLOITABILITY_NOT_ANALYZED.
4718d2c518c0b1dd6e1c956340759983f0464d356d5nealsid  ASSERT_EQ(google_breakpad::EXPLOITABILITY_NOT_ANALYZED,
4728d2c518c0b1dd6e1c956340759983f0464d356d5nealsid            state.exploitability());
4738d2c518c0b1dd6e1c956340759983f0464d356d5nealsid
474f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  // Test that the symbol supplier can interrupt processing
475f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  state.Clear();
476f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  supplier.set_interrupt(true);
477f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner  ASSERT_EQ(processor.Process(minidump_file, &state),
478cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            google_breakpad::PROCESS_SYMBOL_SUPPLIER_INTERRUPTED);
479cce3492afc263be86236600d41dca40be7224ee7bryner}
480e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
481e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comTEST_F(MinidumpProcessorTest, TestThreadMissingMemory) {
482e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidump dump;
483e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
484e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
485e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
486e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MDRawHeader fake_header;
487e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  fake_header.time_date_stamp = 0;
488e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
489e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
490e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MDRawSystemInfo raw_system_info;
491e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  memset(&raw_system_info, 0, sizeof(raw_system_info));
492e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86;
493e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_system_info.platform_id = MD_OS_WIN32_NT;
494e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  TestMinidumpSystemInfo dump_system_info(raw_system_info);
495e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
496e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, GetSystemInfo()).
497e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      WillRepeatedly(Return(&dump_system_info));
498e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
499e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThreadList thread_list;
500e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, GetThreadList()).
501e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      WillOnce(Return(&thread_list));
502e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
50302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MockMinidumpMemoryList memory_list;
50402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(dump, GetMemoryList()).
50502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      WillOnce(Return(&memory_list));
50602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
507e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // Return a thread missing stack memory.
508e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThread no_memory_thread;
509e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_memory_thread, GetThreadID(_)).
510e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(DoAll(SetArgumentPointee<0>(1),
511e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com                         Return(true)));
512e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_memory_thread, GetMemory()).
51302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL)));
51402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
51502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  const uint64_t kTestStartOfMemoryRange = 0x1234;
51602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(no_memory_thread, GetStartOfStackMemoryRange()).
51702ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    WillRepeatedly(Return(kTestStartOfMemoryRange));
51802ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(memory_list, GetMemoryRegionForAddress(kTestStartOfMemoryRange)).
51902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL)));
520e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
521e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MDRawContextX86 no_memory_thread_raw_context;
522e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  memset(&no_memory_thread_raw_context, 0,
523e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com         sizeof(no_memory_thread_raw_context));
524e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  no_memory_thread_raw_context.context_flags = MD_CONTEXT_X86_FULL;
5256162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t kExpectedEIP = 0xabcd1234;
526e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  no_memory_thread_raw_context.eip = kExpectedEIP;
527e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  TestMinidumpContext no_memory_thread_context(no_memory_thread_raw_context);
528e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_memory_thread, GetContext()).
529e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(Return(&no_memory_thread_context));
530e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
531e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(thread_list, thread_count()).
532e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(Return(1));
533e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(thread_list, GetThreadAtIndex(0)).
534e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillOnce(Return(&no_memory_thread));
535e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
53602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
537e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  ProcessState state;
538e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_EQ(processor.Process(&dump, &state),
539e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com            google_breakpad::PROCESS_OK);
540e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
541e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // Should have a single thread with a single frame in it.
5422971a050754f48aaa807db47a29e0d0beddbdcf7ivan.penkov@gmail.com  ASSERT_EQ(1U, state.threads()->size());
5432971a050754f48aaa807db47a29e0d0beddbdcf7ivan.penkov@gmail.com  ASSERT_EQ(1U, state.threads()->at(0)->frames()->size());
544e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  ASSERT_EQ(kExpectedEIP, state.threads()->at(0)->frames()->at(0)->instruction);
545e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com}
546e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
547ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.orgTEST_F(MinidumpProcessorTest, GetProcessCreateTime) {
548ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  const uint32_t kProcessCreateTime = 2000;
549ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  const uint32_t kTimeDateStamp = 5000;
550ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MockMinidump dump;
551ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
552ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
553ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
554ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  // Set time of crash.
555ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MDRawHeader fake_header;
556ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  fake_header.time_date_stamp = kTimeDateStamp;
557ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
558ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
559ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  // Set process create time.
560ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MDRawMiscInfo raw_misc_info;
561ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  memset(&raw_misc_info, 0, sizeof(raw_misc_info));
562ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  raw_misc_info.process_create_time = kProcessCreateTime;
563ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  raw_misc_info.flags1 |= MD_MISCINFO_FLAGS1_PROCESS_TIMES;
564ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  google_breakpad::TestMinidumpMiscInfo dump_misc_info(raw_misc_info);
565ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(dump, GetMiscInfo()).WillRepeatedly(Return(&dump_misc_info));
566ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
567ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  // No threads
568ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MockMinidumpThreadList thread_list;
569ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(dump, GetThreadList()).WillOnce(Return(&thread_list));
570ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_CALL(thread_list, thread_count()).WillRepeatedly(Return(0));
571ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
572ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
573ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  ProcessState state;
574ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  EXPECT_EQ(google_breakpad::PROCESS_OK, processor.Process(&dump, &state));
575ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
576ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  // Verify the time stamps.
577ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  ASSERT_EQ(kTimeDateStamp, state.time_date_stamp());
578ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org  ASSERT_EQ(kProcessCreateTime, state.process_create_time());
579ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org}
580ea4b5be2a2b9a5d5e7a09150a1821b1db5698a45ivanpe@chromium.org
581e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.comTEST_F(MinidumpProcessorTest, TestThreadMissingContext) {
582e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidump dump;
583e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
584e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
585e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
586e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MDRawHeader fake_header;
587e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  fake_header.time_date_stamp = 0;
588e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
589e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
590e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MDRawSystemInfo raw_system_info;
591e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  memset(&raw_system_info, 0, sizeof(raw_system_info));
592e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86;
593e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  raw_system_info.platform_id = MD_OS_WIN32_NT;
594e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  TestMinidumpSystemInfo dump_system_info(raw_system_info);
595e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
596e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, GetSystemInfo()).
597e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      WillRepeatedly(Return(&dump_system_info));
598e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
599e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThreadList thread_list;
600e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(dump, GetThreadList()).
601e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com      WillOnce(Return(&thread_list));
602e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
60302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MockMinidumpMemoryList memory_list;
60402ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(dump, GetMemoryList()).
60502ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com      WillOnce(Return(&memory_list));
60602ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com
607e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // Return a thread missing a thread context.
608e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpThread no_context_thread;
609e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_context_thread, GetThreadID(_)).
610e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(DoAll(SetArgumentPointee<0>(1),
611e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com                         Return(true)));
612e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_context_thread, GetContext()).
61302ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    WillRepeatedly(Return(reinterpret_cast<MinidumpContext*>(NULL)));
614e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
615e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // The memory contents don't really matter here, since it won't be used.
616e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  MockMinidumpMemoryRegion no_context_thread_memory(0x1234, "xxx");
617e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(no_context_thread, GetMemory()).
618e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(Return(&no_context_thread_memory));
61902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(no_context_thread, GetStartOfStackMemoryRange()).
62002ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    Times(0);
62102ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  EXPECT_CALL(memory_list, GetMemoryRegionForAddress(_)).
62202ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com    Times(0);
623e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
624e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(thread_list, thread_count()).
625e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillRepeatedly(Return(1));
626e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_CALL(thread_list, GetThreadAtIndex(0)).
627e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com    WillOnce(Return(&no_context_thread));
628e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
62902ee17f7cf2b669ec1ee688243bcf78f8f58397bivan.penkov@gmail.com  MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
630e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  ProcessState state;
631e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  EXPECT_EQ(processor.Process(&dump, &state),
632e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com            google_breakpad::PROCESS_OK);
633e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
634e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com  // Should have a single thread with zero frames.
6352971a050754f48aaa807db47a29e0d0beddbdcf7ivan.penkov@gmail.com  ASSERT_EQ(1U, state.threads()->size());
6362971a050754f48aaa807db47a29e0d0beddbdcf7ivan.penkov@gmail.com  ASSERT_EQ(0U, state.threads()->at(0)->frames()->size());
637e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com}
638e721e628ec10381c96e38cfc82c1816983097165ted.mielczarek@gmail.com
6398647dde8cc03ef16b565dccc75574ee5f0d9cf72mmentovai}  // namespace
6408647dde8cc03ef16b565dccc75574ee5f0d9cf72mmentovai
641cce3492afc263be86236600d41dca40be7224ee7brynerint main(int argc, char *argv[]) {
642b56cfa067add059d0894433393e798fe0604970enealsid  ::testing::InitGoogleTest(&argc, argv);
643b56cfa067add059d0894433393e798fe0604970enealsid  return RUN_ALL_TESTS();
644cce3492afc263be86236600d41dca40be7224ee7bryner}
645