|
1 // -*- mode: C++ -*- |
|
2 |
|
3 // Copyright (c) 2010, Google Inc. |
|
4 // All rights reserved. |
|
5 // |
|
6 // Redistribution and use in source and binary forms, with or without |
|
7 // modification, are permitted provided that the following conditions are |
|
8 // met: |
|
9 // |
|
10 // * Redistributions of source code must retain the above copyright |
|
11 // notice, this list of conditions and the following disclaimer. |
|
12 // * Redistributions in binary form must reproduce the above |
|
13 // copyright notice, this list of conditions and the following disclaimer |
|
14 // in the documentation and/or other materials provided with the |
|
15 // distribution. |
|
16 // * Neither the name of Google Inc. nor the names of its |
|
17 // contributors may be used to endorse or promote products derived from |
|
18 // this software without specific prior written permission. |
|
19 // |
|
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
31 |
|
32 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
|
33 |
|
34 // Mock classes for writing stackwalker tests, shared amongst architectures. |
|
35 |
|
36 #ifndef PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ |
|
37 #define PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ |
|
38 |
|
39 #include <stdlib.h> |
|
40 #include <string> |
|
41 #include <vector> |
|
42 |
|
43 #include "common/using_std_string.h" |
|
44 #include "google_breakpad/common/breakpad_types.h" |
|
45 #include "google_breakpad/processor/code_module.h" |
|
46 #include "google_breakpad/processor/code_modules.h" |
|
47 #include "google_breakpad/processor/memory_region.h" |
|
48 #include "google_breakpad/processor/symbol_supplier.h" |
|
49 #include "google_breakpad/processor/system_info.h" |
|
50 |
|
51 class MockMemoryRegion: public google_breakpad::MemoryRegion { |
|
52 public: |
|
53 MockMemoryRegion(): base_address_(0) { } |
|
54 |
|
55 // Set this region's address and contents. If we have placed an |
|
56 // instance of this class in a test fixture class, individual tests |
|
57 // can use this to provide the region's contents. |
|
58 void Init(uint64_t base_address, const string &contents) { |
|
59 base_address_ = base_address; |
|
60 contents_ = contents; |
|
61 } |
|
62 |
|
63 uint64_t GetBase() const { return base_address_; } |
|
64 uint32_t GetSize() const { return contents_.size(); } |
|
65 |
|
66 bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { |
|
67 return GetMemoryLittleEndian(address, value); |
|
68 } |
|
69 bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { |
|
70 return GetMemoryLittleEndian(address, value); |
|
71 } |
|
72 bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { |
|
73 return GetMemoryLittleEndian(address, value); |
|
74 } |
|
75 bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { |
|
76 return GetMemoryLittleEndian(address, value); |
|
77 } |
|
78 |
|
79 private: |
|
80 // Fetch a little-endian value from ADDRESS in contents_ whose size |
|
81 // is BYTES, and store it in *VALUE. Return true on success. |
|
82 template<typename ValueType> |
|
83 bool GetMemoryLittleEndian(uint64_t address, ValueType *value) const { |
|
84 if (address < base_address_ || |
|
85 address - base_address_ + sizeof(ValueType) > contents_.size()) |
|
86 return false; |
|
87 ValueType v = 0; |
|
88 int start = address - base_address_; |
|
89 // The loop condition is odd, but it's correct for size_t. |
|
90 for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--) |
|
91 v = (v << 8) | static_cast<unsigned char>(contents_[start + i]); |
|
92 *value = v; |
|
93 return true; |
|
94 } |
|
95 |
|
96 uint64_t base_address_; |
|
97 string contents_; |
|
98 }; |
|
99 |
|
100 class MockCodeModule: public google_breakpad::CodeModule { |
|
101 public: |
|
102 MockCodeModule(uint64_t base_address, uint64_t size, |
|
103 const string &code_file, const string &version) |
|
104 : base_address_(base_address), size_(size), code_file_(code_file) { } |
|
105 |
|
106 uint64_t base_address() const { return base_address_; } |
|
107 uint64_t size() const { return size_; } |
|
108 string code_file() const { return code_file_; } |
|
109 string code_identifier() const { return code_file_; } |
|
110 string debug_file() const { return code_file_; } |
|
111 string debug_identifier() const { return code_file_; } |
|
112 string version() const { return version_; } |
|
113 const google_breakpad::CodeModule *Copy() const { |
|
114 abort(); // Tests won't use this. |
|
115 } |
|
116 |
|
117 private: |
|
118 uint64_t base_address_; |
|
119 uint64_t size_; |
|
120 string code_file_; |
|
121 string version_; |
|
122 }; |
|
123 |
|
124 class MockCodeModules: public google_breakpad::CodeModules { |
|
125 public: |
|
126 typedef google_breakpad::CodeModule CodeModule; |
|
127 typedef google_breakpad::CodeModules CodeModules; |
|
128 |
|
129 void Add(const MockCodeModule *module) { |
|
130 modules_.push_back(module); |
|
131 } |
|
132 |
|
133 unsigned int module_count() const { return modules_.size(); } |
|
134 |
|
135 const CodeModule *GetModuleForAddress(uint64_t address) const { |
|
136 for (ModuleVector::const_iterator i = modules_.begin(); |
|
137 i != modules_.end(); i++) { |
|
138 const MockCodeModule *module = *i; |
|
139 if (module->base_address() <= address && |
|
140 address - module->base_address() < module->size()) |
|
141 return module; |
|
142 } |
|
143 return NULL; |
|
144 }; |
|
145 |
|
146 const CodeModule *GetMainModule() const { return modules_[0]; } |
|
147 |
|
148 const CodeModule *GetModuleAtSequence(unsigned int sequence) const { |
|
149 return modules_.at(sequence); |
|
150 } |
|
151 |
|
152 const CodeModule *GetModuleAtIndex(unsigned int index) const { |
|
153 return modules_.at(index); |
|
154 } |
|
155 |
|
156 const CodeModules *Copy() const { abort(); } // Tests won't use this. |
|
157 |
|
158 private: |
|
159 typedef std::vector<const MockCodeModule *> ModuleVector; |
|
160 ModuleVector modules_; |
|
161 }; |
|
162 |
|
163 class MockSymbolSupplier: public google_breakpad::SymbolSupplier { |
|
164 public: |
|
165 typedef google_breakpad::CodeModule CodeModule; |
|
166 typedef google_breakpad::SystemInfo SystemInfo; |
|
167 MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module, |
|
168 const SystemInfo *system_info, |
|
169 string *symbol_file)); |
|
170 MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module, |
|
171 const SystemInfo *system_info, |
|
172 string *symbol_file, |
|
173 string *symbol_data)); |
|
174 MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module, |
|
175 const SystemInfo *system_info, |
|
176 string *symbol_file, |
|
177 char **symbol_data)); |
|
178 MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module)); |
|
179 |
|
180 // Copies the passed string contents into a newly allocated buffer. |
|
181 // The newly allocated buffer will be freed during destruction. |
|
182 char* CopySymbolDataAndOwnTheCopy(const std::string &info) { |
|
183 unsigned int buffer_size = info.size() + 1; |
|
184 char *symbol_data = new char [buffer_size]; |
|
185 strcpy(symbol_data, info.c_str()); |
|
186 symbol_data_to_free_.push_back(symbol_data); |
|
187 return symbol_data; |
|
188 } |
|
189 |
|
190 virtual ~MockSymbolSupplier() { |
|
191 for (SymbolDataVector::const_iterator i = symbol_data_to_free_.begin(); |
|
192 i != symbol_data_to_free_.end(); i++) { |
|
193 char* symbol_data = *i; |
|
194 delete [] symbol_data; |
|
195 } |
|
196 } |
|
197 |
|
198 private: |
|
199 // List of symbol data to be freed upon destruction |
|
200 typedef std::vector<char*> SymbolDataVector; |
|
201 SymbolDataVector symbol_data_to_free_; |
|
202 }; |
|
203 |
|
204 #endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ |