PageRenderTime 43ms CodeModel.GetById 15ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/client/windows/unittests/minidump_test.cc

http://github.com/tomahawk-player/tomahawk
C++ | 332 lines | 231 code | 49 blank | 52 comment | 17 complexity | c343c061ed82137e38bbcbe77f2e098e MD5 | raw file
  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#include <windows.h>
 31#include <objbase.h>
 32#include <dbghelp.h>
 33
 34#include "../crash_generation/minidump_generator.h"
 35#include "dump_analysis.h"  // NOLINT
 36
 37#include "gtest/gtest.h"
 38
 39namespace {
 40
 41// Minidump with stacks, PEB, TEB, and unloaded module list.
 42const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
 43    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
 44    MiniDumpWithUnloadedModules);  // Get unloaded modules when available.
 45
 46// Minidump with all of the above, plus memory referenced from stack.
 47const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
 48    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
 49    MiniDumpWithUnloadedModules |  // Get unloaded modules when available.
 50    MiniDumpWithIndirectlyReferencedMemory);  // Get memory referenced by stack.
 51
 52// Large dump with all process memory.
 53const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
 54    MiniDumpWithFullMemory |  // Full memory from process.
 55    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
 56    MiniDumpWithHandleData |  // Get all handle information.
 57    MiniDumpWithUnloadedModules);  // Get unloaded modules when available.
 58
 59class MinidumpTest: public testing::Test {
 60 public:
 61  MinidumpTest() {
 62    wchar_t temp_dir_path[ MAX_PATH ] = {0};
 63    ::GetTempPath(MAX_PATH, temp_dir_path);
 64    dump_path_ = temp_dir_path;
 65  }
 66
 67  virtual void SetUp() {
 68    // Make sure URLMon isn't loaded into our process.
 69    ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll"));
 70
 71    // Then load and unload it to ensure we have something to
 72    // stock the unloaded module list with.
 73    HMODULE urlmon = ::LoadLibrary(L"urlmon.dll");
 74    ASSERT_TRUE(urlmon != NULL);
 75    ASSERT_TRUE(::FreeLibrary(urlmon));
 76  }
 77
 78  virtual void TearDown() {
 79    if (!dump_file_.empty()) {
 80      ::DeleteFile(dump_file_.c_str());
 81      dump_file_ = L"";
 82    }
 83    if (!full_dump_file_.empty()) {
 84      ::DeleteFile(full_dump_file_.c_str());
 85      full_dump_file_ = L"";
 86    }
 87  }
 88
 89  bool WriteDump(ULONG flags) {
 90    using google_breakpad::MinidumpGenerator;
 91
 92    // Fake exception is access violation on write to this.
 93    EXCEPTION_RECORD ex_record = {
 94        STATUS_ACCESS_VIOLATION,  // ExceptionCode
 95        0,  // ExceptionFlags
 96        NULL,  // ExceptionRecord;
 97        reinterpret_cast<void*>(0xCAFEBABE),  // ExceptionAddress;
 98        2,  // NumberParameters;
 99        { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) }
100    };
101    CONTEXT ctx_record = {};
102    EXCEPTION_POINTERS ex_ptrs = {
103      &ex_record,
104      &ctx_record,
105    };
106
107    MinidumpGenerator generator(dump_path_);
108
109    // And write a dump
110    bool result = generator.WriteMinidump(::GetCurrentProcess(),
111                                          ::GetCurrentProcessId(),
112                                          ::GetCurrentThreadId(),
113                                          ::GetCurrentThreadId(),
114                                          &ex_ptrs,
115                                          NULL,
116                                          static_cast<MINIDUMP_TYPE>(flags),
117                                          TRUE,
118                                          &dump_file_,
119                                          &full_dump_file_);
120    return result == TRUE;
121  }
122
123 protected:
124  std::wstring dump_file_;
125  std::wstring full_dump_file_;
126
127  std::wstring dump_path_;
128};
129
130// We need to be able to get file information from Windows
131bool HasFileInfo(const std::wstring& file_path) {
132  DWORD dummy;
133  const wchar_t* path = file_path.c_str();
134  DWORD length = ::GetFileVersionInfoSize(path, &dummy);
135  if (length == 0)
136    return NULL;
137
138  void* data = calloc(length, 1);
139  if (!data)
140    return false;
141
142  if (!::GetFileVersionInfo(path, dummy, length, data)) {
143    free(data);
144    return false;
145  }
146
147  void* translate = NULL;
148  UINT page_count;
149  BOOL query_result = VerQueryValue(
150      data,
151      L"\\VarFileInfo\\Translation",
152      static_cast<void**>(&translate),
153      &page_count);
154
155  free(data);
156  if (query_result && translate) {
157    return true;
158  } else {
159    return false;
160  }
161}
162
163TEST_F(MinidumpTest, Version) {
164  API_VERSION* version = ::ImagehlpApiVersion();
165
166  HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll");
167  ASSERT_TRUE(dbg_help != NULL);
168
169  wchar_t dbg_help_file[1024] = {};
170  ASSERT_TRUE(::GetModuleFileName(dbg_help,
171                                  dbg_help_file,
172                                  sizeof(dbg_help_file) /
173                                      sizeof(*dbg_help_file)));
174  ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL);
175
176//  LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version();
177}
178
179TEST_F(MinidumpTest, Normal) {
180  EXPECT_TRUE(WriteDump(MiniDumpNormal));
181  DumpAnalysis mini(dump_file_);
182
183  // We expect threads, modules and some memory.
184  EXPECT_TRUE(mini.HasStream(ThreadListStream));
185  EXPECT_TRUE(mini.HasStream(ModuleListStream));
186  EXPECT_TRUE(mini.HasStream(MemoryListStream));
187  EXPECT_TRUE(mini.HasStream(ExceptionStream));
188  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
189  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
190
191  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
192  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
193  EXPECT_FALSE(mini.HasStream(CommentStreamA));
194  EXPECT_FALSE(mini.HasStream(CommentStreamW));
195  EXPECT_FALSE(mini.HasStream(HandleDataStream));
196  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
197  EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream));
198  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
199  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
200  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
201  EXPECT_FALSE(mini.HasStream(TokenStream));
202
203  // We expect no PEB nor TEBs in this dump.
204  EXPECT_FALSE(mini.HasTebs());
205  EXPECT_FALSE(mini.HasPeb());
206
207  // We expect no off-stack memory in this dump.
208  EXPECT_FALSE(mini.HasMemory(this));
209}
210
211TEST_F(MinidumpTest, SmallDump) {
212  ASSERT_TRUE(WriteDump(kSmallDumpType));
213  DumpAnalysis mini(dump_file_);
214
215  EXPECT_TRUE(mini.HasStream(ThreadListStream));
216  EXPECT_TRUE(mini.HasStream(ModuleListStream));
217  EXPECT_TRUE(mini.HasStream(MemoryListStream));
218  EXPECT_TRUE(mini.HasStream(ExceptionStream));
219  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
220  EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
221  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
222
223  // We expect PEB and TEBs in this dump.
224  EXPECT_TRUE(mini.HasTebs());
225  EXPECT_TRUE(mini.HasPeb());
226
227  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
228  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
229  EXPECT_FALSE(mini.HasStream(CommentStreamA));
230  EXPECT_FALSE(mini.HasStream(CommentStreamW));
231  EXPECT_FALSE(mini.HasStream(HandleDataStream));
232  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
233  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
234  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
235  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
236  EXPECT_FALSE(mini.HasStream(TokenStream));
237
238  // We expect no off-stack memory in this dump.
239  EXPECT_FALSE(mini.HasMemory(this));
240}
241
242TEST_F(MinidumpTest, LargerDump) {
243  ASSERT_TRUE(WriteDump(kLargerDumpType));
244  DumpAnalysis mini(dump_file_);
245
246  // The dump should have all of these streams.
247  EXPECT_TRUE(mini.HasStream(ThreadListStream));
248  EXPECT_TRUE(mini.HasStream(ModuleListStream));
249  EXPECT_TRUE(mini.HasStream(MemoryListStream));
250  EXPECT_TRUE(mini.HasStream(ExceptionStream));
251  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
252  EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
253  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
254
255  // We expect memory referenced by stack in this dump.
256  EXPECT_TRUE(mini.HasMemory(this));
257
258  // We expect PEB and TEBs in this dump.
259  EXPECT_TRUE(mini.HasTebs());
260  EXPECT_TRUE(mini.HasPeb());
261
262  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
263  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
264  EXPECT_FALSE(mini.HasStream(CommentStreamA));
265  EXPECT_FALSE(mini.HasStream(CommentStreamW));
266  EXPECT_FALSE(mini.HasStream(HandleDataStream));
267  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
268  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
269  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
270  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
271  EXPECT_FALSE(mini.HasStream(TokenStream));
272}
273
274TEST_F(MinidumpTest, FullDump) {
275  ASSERT_TRUE(WriteDump(kFullDumpType));
276  ASSERT_TRUE(dump_file_ != L"");
277  ASSERT_TRUE(full_dump_file_ != L"");
278  DumpAnalysis mini(dump_file_);
279  DumpAnalysis full(full_dump_file_);
280
281  // Either dumps can contain part of the information.
282
283  // The dump should have all of these streams.
284  EXPECT_TRUE(mini.HasStream(ThreadListStream));
285  EXPECT_TRUE(full.HasStream(ThreadListStream));
286  EXPECT_TRUE(mini.HasStream(ModuleListStream));
287  EXPECT_TRUE(full.HasStream(ModuleListStream));
288  EXPECT_TRUE(mini.HasStream(ExceptionStream));
289  EXPECT_TRUE(full.HasStream(ExceptionStream));
290  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
291  EXPECT_TRUE(full.HasStream(SystemInfoStream));
292  EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
293  EXPECT_TRUE(full.HasStream(UnloadedModuleListStream));
294  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
295  EXPECT_TRUE(full.HasStream(MiscInfoStream));
296  EXPECT_TRUE(mini.HasStream(HandleDataStream));
297  EXPECT_TRUE(full.HasStream(HandleDataStream));
298
299  // We expect memory referenced by stack in this dump.
300  EXPECT_FALSE(mini.HasMemory(this));
301  EXPECT_TRUE(full.HasMemory(this));
302
303  // We expect PEB and TEBs in this dump.
304  EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
305  EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
306
307  EXPECT_TRUE(mini.HasStream(MemoryListStream));
308  EXPECT_TRUE(full.HasStream(Memory64ListStream));
309  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
310  EXPECT_FALSE(full.HasStream(MemoryListStream));
311
312  // This is the only place we don't use OR because we want both not
313  // to have the streams.
314  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
315  EXPECT_FALSE(full.HasStream(ThreadExListStream));
316  EXPECT_FALSE(mini.HasStream(CommentStreamA));
317  EXPECT_FALSE(full.HasStream(CommentStreamA));
318  EXPECT_FALSE(mini.HasStream(CommentStreamW));
319  EXPECT_FALSE(full.HasStream(CommentStreamW));
320  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
321  EXPECT_FALSE(full.HasStream(FunctionTableStream));
322  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
323  EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
324  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
325  EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
326  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
327  EXPECT_FALSE(full.HasStream(HandleOperationListStream));
328  EXPECT_FALSE(mini.HasStream(TokenStream));
329  EXPECT_FALSE(full.HasStream(TokenStream));
330}
331
332}  // namespace