1f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// Copyright 2009, Google Inc.
2f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// All rights reserved.
3f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//
4f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// Redistribution and use in source and binary forms, with or without
5f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// modification, are permitted provided that the following conditions are
6f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// met:
7f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//
8f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//     * Redistributions of source code must retain the above copyright
9f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// notice, this list of conditions and the following disclaimer.
10f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//     * Redistributions in binary form must reproduce the above
11f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// copyright notice, this list of conditions and the following disclaimer
12f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// in the documentation and/or other materials provided with the
13f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// distribution.
14f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//     * Neither the name of Google Inc. nor the names of its
15f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// contributors may be used to endorse or promote products derived from
16f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// this software without specific prior written permission.
17f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid//
18f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
30cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "client/windows/unittests/exception_handler_test.h"
31cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
32f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <windows.h>
33f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <dbghelp.h>
34f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <strsafe.h>
35f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <objbase.h>
36f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <shellapi.h>
37f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
389220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include <string>
399220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
40cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "breakpad_googletest_includes.h"
41cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "client/windows/crash_generation/crash_generation_server.h"
42cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "client/windows/handler/exception_handler.h"
43cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "client/windows/unittests/dump_analysis.h"  // NOLINT
44cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "common/windows/string_utils-inl.h"
45cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com#include "google_breakpad/processor/minidump.h"
46cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
47cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.comnamespace testing {
48cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
49cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.comDisableExceptionHandlerInScope::DisableExceptionHandlerInScope() {
50cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  catch_exceptions_ = GTEST_FLAG(catch_exceptions);
51cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  GTEST_FLAG(catch_exceptions) = false;
52cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com}
53cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
54cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.comDisableExceptionHandlerInScope::~DisableExceptionHandlerInScope() {
55cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  GTEST_FLAG(catch_exceptions) = catch_exceptions_;
56cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com}
57cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
58cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com}  // namespace testing
59ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com
60f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidnamespace {
619220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
629220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing std::wstring;
639220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing namespace google_breakpad;
649220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
65f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
66f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kSuccessIndicator[] = "success";
67f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kFailureIndicator[] = "failure";
68f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
698cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comconst MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
708cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithFullMemory |  // Full memory from process.
718cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
728cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithHandleData);  // Get all handle information.
73f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
748cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comclass ExceptionHandlerTest : public ::testing::Test {
75ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com protected:
76f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Member variable for each test that they can use
77f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // for temporary storage.
78f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR temp_path_[MAX_PATH];
798cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
80f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Actually constructs a temp path name.
81f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  virtual void SetUp();
828cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
838cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Deletes temporary files.
848cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  virtual void TearDown();
858cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
86bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  void DoCrashInvalidParameter();
87bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  void DoCrashPureVirtualCall();
888cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
898cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Utility function to test for a path's existence.
908cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static BOOL DoesPathExist(const TCHAR *path_name);
918cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
928cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Client callback.
938cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static void ClientDumpCallback(
948cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      void *dump_context,
958cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      const google_breakpad::ClientInfo *client_info,
968cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      const std::wstring *dump_path);
978cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
989220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  static bool DumpCallback(const wchar_t* dump_path,
999220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           const wchar_t* minidump_id,
1009220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           void* context,
1019220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           EXCEPTION_POINTERS* exinfo,
1029220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           MDRawAssertionInfo* assertion,
1039220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           bool succeeded);
1049220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
1058cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static std::wstring dump_file;
1068cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static std::wstring full_dump_file;
107f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid};
108f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1098cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::dump_file;
1108cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::full_dump_file;
1118cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
1128cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::SetUp() {
113f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  const ::testing::TestInfo* const test_info =
114f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    ::testing::UnitTest::GetInstance()->current_test_info();
115f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR temp_path[MAX_PATH] = { '\0' };
116f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR test_name_wide[MAX_PATH] = { '\0' };
117f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // We want the temporary directory to be what the OS returns
118ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  // to us, + the test case name.
119f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  GetTempPath(MAX_PATH, temp_path);
120f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // THe test case name is exposed to use as a c-style string,
121f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // But we might be working in UNICODE here on Windows.
122ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
123ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  strlen(test_info->name()),
124ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  test_name_wide,
125ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  MAX_PATH);
126f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  if (!dwRet) {
127f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    assert(false);
128f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  }
129f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
130f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  CreateDirectory(temp_path_, NULL);
131f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
132f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1338cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::TearDown() {
1348cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  if (!dump_file.empty()) {
1358cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    ::DeleteFile(dump_file.c_str());
1368cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    dump_file = L"";
1378cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  }
1388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  if (!full_dump_file.empty()) {
1398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    ::DeleteFile(full_dump_file.c_str());
1408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    full_dump_file = L"";
1418cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  }
1428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com}
1438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
1448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comBOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) {
145f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  DWORD flags = GetFileAttributes(path_name);
146f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  if (flags == INVALID_FILE_ATTRIBUTES) {
147f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    return FALSE;
148f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  }
149f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  return TRUE;
150f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
151f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1529220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static
1538cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::ClientDumpCallback(
1548cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    void *dump_context,
1558cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    const google_breakpad::ClientInfo *client_info,
1569220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek    const wstring *dump_path) {
1578cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  dump_file = *dump_path;
1588cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Create the full dump file name from the dump path.
1598cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp";
160f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
161f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1629220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static
1639220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekbool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path,
1649220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    const wchar_t* minidump_id,
1659220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    void* context,
1669220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    EXCEPTION_POINTERS* exinfo,
1679220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    MDRawAssertionInfo* assertion,
1689220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    bool succeeded) {
1699220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file = dump_path;
1709220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += L"\\";
1719220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += minidump_id;
1729220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += L".dmp";
1739220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek    return succeeded;
1749220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek}
1759220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
176bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashInvalidParameter() {
177ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  google_breakpad::ExceptionHandler *exc =
1788cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      new google_breakpad::ExceptionHandler(
1798cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          temp_path_, NULL, NULL, NULL,
1808cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER,
1818cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          kFullDumpType, kPipeName, NULL);
182f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1838cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Disable the message box for assertions
1848cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  _CrtSetReportMode(_CRT_ASSERT, 0);
185f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
186f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Although this is executing in the child process of the death test,
187ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  // if it's not true we'll still get an error rather than the crash
188f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // being expected.
189f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  ASSERT_TRUE(exc->IsOutOfProcess());
1908cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  printf(NULL);
191f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
192f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
193bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
194bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCallBase {
195bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  PureVirtualCallBase() {
196bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    // We have to reinterpret so the linker doesn't get confused because the
197bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    // method isn't defined.
198bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
199bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  }
200bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual ~PureVirtualCallBase() {}
201bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual void PureFunction() const = 0;
202bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com};
203bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCall : public PureVirtualCallBase {
204bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  PureVirtualCall() { PureFunction(); }
205bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual void PureFunction() const {}
206bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com};
207bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
208bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashPureVirtualCall() {
209bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  google_breakpad::ExceptionHandler *exc =
210bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com      new google_breakpad::ExceptionHandler(
211bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          temp_path_, NULL, NULL, NULL,
212bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          google_breakpad::ExceptionHandler::HANDLER_PURECALL,
213bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          kFullDumpType, kPipeName, NULL);
214bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
215bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Disable the message box for assertions
216bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  _CrtSetReportMode(_CRT_ASSERT, 0);
217bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
218bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Although this is executing in the child process of the death test,
219bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // if it's not true we'll still get an error rather than the crash
220bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // being expected.
221bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(exc->IsOutOfProcess());
222bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
223bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Create a new frame to ensure PureVirtualCall is not optimized to some
224bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // other line in this function.
225bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  {
226bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    PureVirtualCall instance;
227bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  }
228bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}
229bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
2308cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com// This test validates that the minidump is written correctly.
2318cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comTEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) {
2328cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
233f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
2348cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Call with a bad argument
235f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  ASSERT_TRUE(DoesPathExist(temp_path_));
2369220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  wstring dump_path(temp_path_);
237f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  google_breakpad::CrashGenerationServer server(
238eb991531e31b7c001200cf23ce07efc5a32b41aecdn@chromium.org      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
239eb991531e31b7c001200cf23ce07efc5a32b41aecdn@chromium.org      NULL, true, &dump_path);
2408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
2418cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
242ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com
243f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // This HAS to be EXPECT_, because when this test case is executed in the
244f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // child process, the server registration will fail due to the named pipe
245f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // being the same.
246f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  EXPECT_TRUE(server.Start());
247bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), "");
248bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
249bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
250bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
251bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Verify the dump for infos.
252bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  DumpAnalysis mini(dump_file);
253bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  DumpAnalysis full(full_dump_file);
254bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
255bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // The dump should have all of these streams.
256bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ThreadListStream));
257bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ThreadListStream));
258bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ModuleListStream));
259bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ModuleListStream));
260bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ExceptionStream));
261bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ExceptionStream));
262bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
263bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(SystemInfoStream));
264bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
265bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(MiscInfoStream));
266bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(HandleDataStream));
267bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(HandleDataStream));
268bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
269bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // We expect PEB and TEBs in this dump.
270bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
271bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
272bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
273bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Minidump should have a memory listing, but no 64-bit memory.
274bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(MemoryListStream));
275bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
276bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
277bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryListStream));
278bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(Memory64ListStream));
279bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
280bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // This is the only place we don't use OR because we want both not
281bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // to have the streams.
282bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
283bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadExListStream));
284bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamA));
285bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamA));
286bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamW));
287bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamW));
288bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
289bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(FunctionTableStream));
290bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
291bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
292bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
293bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
294bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
295bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(HandleOperationListStream));
296bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(TokenStream));
297bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(TokenStream));
298bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}
299bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
300bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
301bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com// This test validates that the minidump is written correctly.
302bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comTEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) {
303bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
304bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
305bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Call with a bad argument
306bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
3079220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  wstring dump_path(temp_path_);
308bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  google_breakpad::CrashGenerationServer server(
309eb991531e31b7c001200cf23ce07efc5a32b41aecdn@chromium.org      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
310eb991531e31b7c001200cf23ce07efc5a32b41aecdn@chromium.org      NULL, true, &dump_path);
311bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
312bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
313bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
314bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // This HAS to be EXPECT_, because when this test case is executed in the
315bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // child process, the server registration will fail due to the named pipe
316bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // being the same.
317bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(server.Start());
318bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
3198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
3208cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
3218cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3228cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Verify the dump for infos.
3238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  DumpAnalysis mini(dump_file);
3248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  DumpAnalysis full(full_dump_file);
3258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // The dump should have all of these streams.
3278cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ThreadListStream));
3288cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ThreadListStream));
3298cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ModuleListStream));
3308cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ModuleListStream));
3318cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ExceptionStream));
3328cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ExceptionStream));
3338cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
3348cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(SystemInfoStream));
3358cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
3368cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(MiscInfoStream));
3378cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(HandleDataStream));
3388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(HandleDataStream));
3398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // We expect PEB and TEBs in this dump.
3418cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
3428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
3438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Minidump should have a memory listing, but no 64-bit memory.
3458cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(MemoryListStream));
3468cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
3478cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3488cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryListStream));
3498cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(Memory64ListStream));
3508cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3518cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // This is the only place we don't use OR because we want both not
3528cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // to have the streams.
3538cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
3548cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadExListStream));
3558cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamA));
3568cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamA));
3578cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamW));
3588cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamW));
3598cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
3608cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(FunctionTableStream));
3618cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
3628cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
3638cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
3648cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
3658cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
3668cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(HandleOperationListStream));
3678cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(TokenStream));
3688cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(TokenStream));
369f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
3709220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3719220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// Test that writing a minidump produces a valid minidump containing
3729220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// some expected structures.
3739220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekTEST_F(ExceptionHandlerTest, WriteMinidumpTest) {
3749220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ExceptionHandler handler(temp_path_,
3759220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           NULL,
3769220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           DumpCallback,
3779220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           NULL,
3789220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           ExceptionHandler::HANDLER_ALL);
379cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
380cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  // Disable GTest SEH handler
381cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  testing::DisableExceptionHandlerInScope disable_exception_handler;
382cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
3839220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(handler.WriteMinidump());
3849220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_FALSE(dump_file.empty());
3859220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3869220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  string minidump_filename;
3879220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
3889220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                                                &minidump_filename));
3899220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3909220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  // Read the minidump and verify some info.
3919220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  Minidump minidump(minidump_filename);
3929220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(minidump.Read());
393f7838a8665eb5e46f2eb136679b27707d6adb523ivan.penkov@gmail.com  // TODO(ted): more comprehensive tests...
394ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com}
3959220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
39686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com// Test that an additional memory region can be included in the minidump.
39786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.comTEST_F(ExceptionHandlerTest, AdditionalMemory) {
39886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  SYSTEM_INFO si;
39986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  GetSystemInfo(&si);
4006162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t kMemorySize = si.dwPageSize;
40186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
40286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Get some heap memory.
4036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint8_t* memory = new uint8_t[kMemorySize];
40486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
40586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(memory);
40686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
40786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Stick some data into the memory so the contents can be verified.
4086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  for (uint32_t i = 0; i < kMemorySize; ++i) {
40986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com    memory[i] = i % 255;
41086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  }
41186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
41286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ExceptionHandler handler(temp_path_,
41386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           NULL,
41486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           DumpCallback,
41586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           NULL,
41686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           ExceptionHandler::HANDLER_ALL);
41786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
418cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  // Disable GTest SEH handler
419cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  testing::DisableExceptionHandlerInScope disable_exception_handler;
420cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
42186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Add the memory region to the list of memory to be included.
42286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  handler.RegisterAppMemory(memory, kMemorySize);
42386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(handler.WriteMinidump());
42486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_FALSE(dump_file.empty());
42586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
42686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  string minidump_filename;
42786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
42886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                                                &minidump_filename));
42986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
43086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Read the minidump. Ensure that the memory region is present
43186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  Minidump minidump(minidump_filename);
43286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(minidump.Read());
43386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
43486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
43586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(dump_memory_list);
43686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  const MinidumpMemoryRegion* region =
43786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com    dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
43886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(region);
43986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
44086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  EXPECT_EQ(kMemoryAddress, region->GetBase());
44186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  EXPECT_EQ(kMemorySize, region->GetSize());
44286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
44386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Verify memory contents.
44486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
44586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
44686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  delete[] memory;
44786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com}
44886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
44986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com// Test that a memory region that was previously registered
45086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com// can be unregistered.
45186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.comTEST_F(ExceptionHandlerTest, AdditionalMemoryRemove) {
45286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  SYSTEM_INFO si;
45386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  GetSystemInfo(&si);
4546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  const uint32_t kMemorySize = si.dwPageSize;
45586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
45686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Get some heap memory.
4576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint8_t* memory = new uint8_t[kMemorySize];
45886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
45986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(memory);
46086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
46186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Stick some data into the memory so the contents can be verified.
4626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  for (uint32_t i = 0; i < kMemorySize; ++i) {
46386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com    memory[i] = i % 255;
46486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  }
46586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
46686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ExceptionHandler handler(temp_path_,
46786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           NULL,
46886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           DumpCallback,
46986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           NULL,
47086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                           ExceptionHandler::HANDLER_ALL);
47186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
472cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  // Disable GTest SEH handler
473cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com  testing::DisableExceptionHandlerInScope disable_exception_handler;
474cc95c874b64b4f55bb8c4997a54b6ee1e2d2e9b7ivan.penkov@gmail.com
47586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Add the memory region to the list of memory to be included.
47686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  handler.RegisterAppMemory(memory, kMemorySize);
47786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
47886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // ...and then remove it
47986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  handler.UnregisterAppMemory(memory);
48086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
48186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(handler.WriteMinidump());
48286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_FALSE(dump_file.empty());
48386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
48486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  string minidump_filename;
48586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
48686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com                                                &minidump_filename));
48786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
48886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  // Read the minidump. Ensure that the memory region is not present.
48986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  Minidump minidump(minidump_filename);
49086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(minidump.Read());
49186f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
49286f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
49386f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  ASSERT_TRUE(dump_memory_list);
49486f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  const MinidumpMemoryRegion* region =
49586f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com    dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
49686f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  EXPECT_FALSE(region);
49786f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
49886f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com  delete[] memory;
49986f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com}
50086f79a00ae0829dae0136f758eafbe7c220e0c0dted.mielczarek@gmail.com
5019220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek}  // namespace
502