exception_handler_test.cc revision 9220e0baf1f59c067e82495d697306cc460c4e8c
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
30f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <windows.h>
31f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <dbghelp.h>
32f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <strsafe.h>
33f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <objbase.h>
34f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <shellapi.h>
35f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
369220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include <string>
379220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
38ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../../../breakpad_googletest_includes.h"
399220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include "../../../../common/windows/string_utils-inl.h"
409220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include "../../../../google_breakpad/processor/minidump.h"
41ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../crash_generation/crash_generation_server.h"
42ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../handler/exception_handler.h"
438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com#include "dump_analysis.h"  // NOLINT
44ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com
45f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidnamespace {
469220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
479220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing std::wstring;
489220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing namespace google_breakpad;
499220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
50f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
51f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kSuccessIndicator[] = "success";
52f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kFailureIndicator[] = "failure";
53f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
548cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comconst MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
558cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithFullMemory |  // Full memory from process.
568cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithProcessThreadData |  // Get PEB and TEB.
578cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    MiniDumpWithHandleData);  // Get all handle information.
58f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
598cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comclass ExceptionHandlerTest : public ::testing::Test {
60ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com protected:
61f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Member variable for each test that they can use
62f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // for temporary storage.
63f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR temp_path_[MAX_PATH];
648cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
65f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Actually constructs a temp path name.
66f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  virtual void SetUp();
678cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
688cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Deletes temporary files.
698cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  virtual void TearDown();
708cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
71bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  void DoCrashInvalidParameter();
72bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  void DoCrashPureVirtualCall();
738cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
748cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Utility function to test for a path's existence.
758cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static BOOL DoesPathExist(const TCHAR *path_name);
768cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
778cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Client callback.
788cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static void ClientDumpCallback(
798cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      void *dump_context,
808cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      const google_breakpad::ClientInfo *client_info,
818cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      const std::wstring *dump_path);
828cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
839220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  static bool DumpCallback(const wchar_t* dump_path,
849220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           const wchar_t* minidump_id,
859220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           void* context,
869220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           EXCEPTION_POINTERS* exinfo,
879220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           MDRawAssertionInfo* assertion,
889220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           bool succeeded);
899220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
908cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static std::wstring dump_file;
918cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  static std::wstring full_dump_file;
92f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid};
93f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
948cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::dump_file;
958cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::full_dump_file;
968cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
978cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::SetUp() {
98f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  const ::testing::TestInfo* const test_info =
99f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    ::testing::UnitTest::GetInstance()->current_test_info();
100f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR temp_path[MAX_PATH] = { '\0' };
101f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  TCHAR test_name_wide[MAX_PATH] = { '\0' };
102f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // We want the temporary directory to be what the OS returns
103ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  // to us, + the test case name.
104f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  GetTempPath(MAX_PATH, temp_path);
105f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // THe test case name is exposed to use as a c-style string,
106f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // But we might be working in UNICODE here on Windows.
107ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
108ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  strlen(test_info->name()),
109ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  test_name_wide,
110ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com                                  MAX_PATH);
111f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  if (!dwRet) {
112f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    assert(false);
113f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  }
114f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
115f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  CreateDirectory(temp_path_, NULL);
116f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
117f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1188cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::TearDown() {
1198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  if (!dump_file.empty()) {
1208cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    ::DeleteFile(dump_file.c_str());
1218cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    dump_file = L"";
1228cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  }
1238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  if (!full_dump_file.empty()) {
1248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    ::DeleteFile(full_dump_file.c_str());
1258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    full_dump_file = L"";
1268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  }
1278cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com}
1288cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
1298cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comBOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) {
130f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  DWORD flags = GetFileAttributes(path_name);
131f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  if (flags == INVALID_FILE_ATTRIBUTES) {
132f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid    return FALSE;
133f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  }
134f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  return TRUE;
135f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
136f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1379220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static
1388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::ClientDumpCallback(
1398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    void *dump_context,
1408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com    const google_breakpad::ClientInfo *client_info,
1419220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek    const wstring *dump_path) {
1428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  dump_file = *dump_path;
1438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Create the full dump file name from the dump path.
1448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp";
145f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
146f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1479220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static
1489220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekbool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path,
1499220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    const wchar_t* minidump_id,
1509220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    void* context,
1519220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    EXCEPTION_POINTERS* exinfo,
1529220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    MDRawAssertionInfo* assertion,
1539220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                    bool succeeded) {
1549220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file = dump_path;
1559220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += L"\\";
1569220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += minidump_id;
1579220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  dump_file += L".dmp";
1589220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek    return succeeded;
1599220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek}
1609220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
161bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashInvalidParameter() {
162ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  google_breakpad::ExceptionHandler *exc =
1638cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      new google_breakpad::ExceptionHandler(
1648cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          temp_path_, NULL, NULL, NULL,
1658cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER,
1668cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com          kFullDumpType, kPipeName, NULL);
167f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
1688cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Disable the message box for assertions
1698cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  _CrtSetReportMode(_CRT_ASSERT, 0);
170f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
171f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // Although this is executing in the child process of the death test,
172ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com  // if it's not true we'll still get an error rather than the crash
173f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // being expected.
174f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  ASSERT_TRUE(exc->IsOutOfProcess());
1758cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  printf(NULL);
176f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
177f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
178bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
179bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCallBase {
180bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  PureVirtualCallBase() {
181bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    // We have to reinterpret so the linker doesn't get confused because the
182bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    // method isn't defined.
183bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
184bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  }
185bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual ~PureVirtualCallBase() {}
186bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual void PureFunction() const = 0;
187bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com};
188bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCall : public PureVirtualCallBase {
189bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  PureVirtualCall() { PureFunction(); }
190bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  virtual void PureFunction() const {}
191bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com};
192bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
193bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashPureVirtualCall() {
194bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  google_breakpad::ExceptionHandler *exc =
195bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com      new google_breakpad::ExceptionHandler(
196bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          temp_path_, NULL, NULL, NULL,
197bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          google_breakpad::ExceptionHandler::HANDLER_PURECALL,
198bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com          kFullDumpType, kPipeName, NULL);
199bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
200bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Disable the message box for assertions
201bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  _CrtSetReportMode(_CRT_ASSERT, 0);
202bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
203bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Although this is executing in the child process of the death test,
204bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // if it's not true we'll still get an error rather than the crash
205bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // being expected.
206bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(exc->IsOutOfProcess());
207bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
208bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Create a new frame to ensure PureVirtualCall is not optimized to some
209bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // other line in this function.
210bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  {
211bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com    PureVirtualCall instance;
212bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  }
213bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}
214bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
2158cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com// This test validates that the minidump is written correctly.
2168cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comTEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) {
2178cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
218f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid
2198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Call with a bad argument
220f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  ASSERT_TRUE(DoesPathExist(temp_path_));
2219220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  wstring dump_path(temp_path_);
222f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  google_breakpad::CrashGenerationServer server(
2238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true,
2248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com      &dump_path);
2258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
2268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
227ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com
228f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // This HAS to be EXPECT_, because when this test case is executed in the
229f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // child process, the server registration will fail due to the named pipe
230f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  // being the same.
231f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid  EXPECT_TRUE(server.Start());
232bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), "");
233bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
234bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
235bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
236bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Verify the dump for infos.
237bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  DumpAnalysis mini(dump_file);
238bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  DumpAnalysis full(full_dump_file);
239bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
240bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // The dump should have all of these streams.
241bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ThreadListStream));
242bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ThreadListStream));
243bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ModuleListStream));
244bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ModuleListStream));
245bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(ExceptionStream));
246bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(ExceptionStream));
247bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
248bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(SystemInfoStream));
249bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
250bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(MiscInfoStream));
251bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(HandleDataStream));
252bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(HandleDataStream));
253bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
254bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // We expect PEB and TEBs in this dump.
255bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
256bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
257bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
258bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Minidump should have a memory listing, but no 64-bit memory.
259bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(mini.HasStream(MemoryListStream));
260bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
261bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
262bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryListStream));
263bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(full.HasStream(Memory64ListStream));
264bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
265bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // This is the only place we don't use OR because we want both not
266bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // to have the streams.
267bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
268bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadExListStream));
269bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamA));
270bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamA));
271bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamW));
272bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamW));
273bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
274bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(FunctionTableStream));
275bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
276bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
277bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
278bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
279bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
280bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(HandleOperationListStream));
281bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(mini.HasStream(TokenStream));
282bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_FALSE(full.HasStream(TokenStream));
283bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}
284bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
285bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
286bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com// This test validates that the minidump is written correctly.
287bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comTEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) {
288bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
289bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
290bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // Call with a bad argument
291bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(DoesPathExist(temp_path_));
2929220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  wstring dump_path(temp_path_);
293bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  google_breakpad::CrashGenerationServer server(
294bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com      kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true,
295bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com      &dump_path);
296bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
297bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
298bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com
299bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // This HAS to be EXPECT_, because when this test case is executed in the
300bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // child process, the server registration will fail due to the named pipe
301bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  // being the same.
302bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_TRUE(server.Start());
303bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com  EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
3048cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
3058cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
3068cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3078cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Verify the dump for infos.
3088cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  DumpAnalysis mini(dump_file);
3098cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  DumpAnalysis full(full_dump_file);
3108cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3118cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // The dump should have all of these streams.
3128cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ThreadListStream));
3138cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ThreadListStream));
3148cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ModuleListStream));
3158cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ModuleListStream));
3168cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(ExceptionStream));
3178cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(ExceptionStream));
3188cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(SystemInfoStream));
3198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(SystemInfoStream));
3208cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(MiscInfoStream));
3218cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(MiscInfoStream));
3228cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(HandleDataStream));
3238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(HandleDataStream));
3248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // We expect PEB and TEBs in this dump.
3268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
3278cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
3288cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3298cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // Minidump should have a memory listing, but no 64-bit memory.
3308cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(mini.HasStream(MemoryListStream));
3318cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(Memory64ListStream));
3328cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3338cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryListStream));
3348cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_TRUE(full.HasStream(Memory64ListStream));
3358cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com
3368cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // This is the only place we don't use OR because we want both not
3378cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  // to have the streams.
3388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadExListStream));
3398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadExListStream));
3408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamA));
3418cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamA));
3428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(CommentStreamW));
3438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(CommentStreamW));
3448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(FunctionTableStream));
3458cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(FunctionTableStream));
3468cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
3478cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
3488cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
3498cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
3508cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
3518cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(HandleOperationListStream));
3528cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(mini.HasStream(TokenStream));
3538cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com  EXPECT_FALSE(full.HasStream(TokenStream));
354f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}
3559220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3569220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// Test that writing a minidump produces a valid minidump containing
3579220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// some expected structures.
3589220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekTEST_F(ExceptionHandlerTest, WriteMinidumpTest) {
3599220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ExceptionHandler handler(temp_path_,
3609220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           NULL,
3619220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           DumpCallback,
3629220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           NULL,
3639220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                           ExceptionHandler::HANDLER_ALL);
3649220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(handler.WriteMinidump());
3659220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_FALSE(dump_file.empty());
3669220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3679220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  string minidump_filename;
3689220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
3699220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek                                                &minidump_filename));
3709220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3719220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  // Read the minidump and verify some info.
3729220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  Minidump minidump(minidump_filename);
3739220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  ASSERT_TRUE(minidump.Read());
3749220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek  //TODO(ted): more comprehensive tests...
375ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com}
3769220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek
3779220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek}  // namespace
378