From 91e04296035c9bcd8d148eb33b6c77b373baf17a Mon Sep 17 00:00:00 2001
From: Jon Turney <jon.turney@dronecode.org.uk>
Date: Tue, 11 Feb 2014 23:48:28 +0000
Subject: [PATCH 12/29] Fix Windows client unit-tests with gcc

- MinGW doesn't have _CrtSetReportMode

- Trying to call PureVirtual() on a base class object give a linker error

Use more elaborate contortions to write a pure virtual call that gcc doesn't
spot at compile-time, to provoke a run-time failure (copied from
crash_generation_app)

Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
---
 .../unittests/exception_handler_death_test.cc      | 28 +++++++++++++++-------
 .../windows/unittests/exception_handler_test.cc    | 28 +++++++++++++++-------
 2 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/src/client/windows/unittests/exception_handler_death_test.cc b/src/client/windows/unittests/exception_handler_death_test.cc
index 5ef9e64d..530f05d8 100644
--- a/src/client/windows/unittests/exception_handler_death_test.cc
+++ b/src/client/windows/unittests/exception_handler_death_test.cc
@@ -242,29 +242,37 @@ TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) {
   ExceptionHandler handler(temp_path_, NULL, NULL, NULL,
                            ExceptionHandler::HANDLER_INVALID_PARAMETER);
 
+#ifdef _MSC_VER
   // Disable the message box for assertions
   _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
 
   // Call with a bad argument. The invalid parameter will be swallowed
   // and a dump will be generated, the process will exit(0).
   ASSERT_EXIT(printf(NULL), ::testing::ExitedWithCode(0), "");
 }
 
+struct PureVirtualCall;
 
 struct PureVirtualCallBase {
-  PureVirtualCallBase() {
-    // We have to reinterpret so the linker doesn't get confused because the
-    // method isn't defined.
-    reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
-  }
-  virtual ~PureVirtualCallBase() {}
-  virtual void PureFunction() const = 0;
+  PureVirtualCallBase(PureVirtualCall* derived) : derived_(derived) {}
+  virtual ~PureVirtualCallBase();
+  virtual void DoSomething() = 0;
+
+ private:
+  PureVirtualCall* derived_;
 };
+
 struct PureVirtualCall : public PureVirtualCallBase {
-  PureVirtualCall() { PureFunction(); }
-  virtual void PureFunction() const {}
+  PureVirtualCall() : PureVirtualCallBase(this) {}
+  virtual void DoSomething() {}
 };
 
+PureVirtualCallBase:: ~PureVirtualCallBase()
+{
+  derived_->DoSomething();
+}
+
 void ExceptionHandlerDeathTest::DoCrashPureVirtualCall() {
   PureVirtualCall instance;
 }
@@ -276,8 +284,10 @@ TEST_F(ExceptionHandlerDeathTest, PureVirtualCallTest) {
   ExceptionHandler handler(temp_path_, NULL, NULL, NULL,
                            ExceptionHandler::HANDLER_PURECALL);
 
+#ifdef _MSC_VER
   // Disable the message box for assertions
   _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
 
   // Calls a pure virtual function.
   EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
diff --git a/src/client/windows/unittests/exception_handler_test.cc b/src/client/windows/unittests/exception_handler_test.cc
index a4ce12a8..0f5801b1 100644
--- a/src/client/windows/unittests/exception_handler_test.cc
+++ b/src/client/windows/unittests/exception_handler_test.cc
@@ -180,8 +180,10 @@ void ExceptionHandlerTest::DoCrashInvalidParameter() {
           google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER,
           kFullDumpType, kPipeName, NULL);
 
+#ifdef _MSC_VER
   // Disable the message box for assertions
   _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
 
   // Although this is executing in the child process of the death test,
   // if it's not true we'll still get an error rather than the crash
@@ -190,21 +192,27 @@ void ExceptionHandlerTest::DoCrashInvalidParameter() {
   printf(NULL);
 }
 
+struct PureVirtualCall;
 
 struct PureVirtualCallBase {
-  PureVirtualCallBase() {
-    // We have to reinterpret so the linker doesn't get confused because the
-    // method isn't defined.
-    reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
-  }
-  virtual ~PureVirtualCallBase() {}
-  virtual void PureFunction() const = 0;
+  PureVirtualCallBase(PureVirtualCall* derived) : derived_(derived) {}
+  virtual ~PureVirtualCallBase();
+  virtual void DoSomething() = 0;
+
+ private:
+  PureVirtualCall* derived_;
 };
+
 struct PureVirtualCall : public PureVirtualCallBase {
-  PureVirtualCall() { PureFunction(); }
-  virtual void PureFunction() const {}
+  PureVirtualCall() : PureVirtualCallBase(this) {}
+  virtual void DoSomething() {}
 };
 
+PureVirtualCallBase:: ~PureVirtualCallBase()
+{
+  derived_->DoSomething();
+}
+
 void ExceptionHandlerTest::DoCrashPureVirtualCall() {
   google_breakpad::ExceptionHandler *exc =
       new google_breakpad::ExceptionHandler(
@@ -212,8 +220,10 @@ void ExceptionHandlerTest::DoCrashPureVirtualCall() {
           google_breakpad::ExceptionHandler::HANDLER_PURECALL,
           kFullDumpType, kPipeName, NULL);
 
+#ifdef _MSC_VER
   // Disable the message box for assertions
   _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
 
   // Although this is executing in the child process of the death test,
   // if it's not true we'll still get an error rather than the crash
-- 
2.15.0

