Home | History | Annotate | Download | only in crash_reporting
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <atlbase.h>
      6 #include "chrome_frame/crash_reporting/veh_test.h"
      7 #include "testing/gmock/include/gmock/gmock.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 #include "chrome_frame/crash_reporting/vectored_handler-impl.h"
     10 
     11 #pragma code_seg(push, ".m$_0")
     12 static void ModuleStart() {}
     13 #pragma code_seg(pop)
     14 
     15 #pragma code_seg(push, ".m$_2")
     16 DECLSPEC_NOINLINE static void Undetectable(DWORD code) {
     17   __try {
     18     ::RaiseException(code, 0, 0, NULL);
     19   } __except(EXCEPTION_EXECUTE_HANDLER) {
     20 
     21   }
     22 };
     23 #pragma code_seg(pop)
     24 
     25 #pragma code_seg(push, ".m$_3")
     26 static void UndetectableEnd() {}
     27 #pragma code_seg(pop)
     28 
     29 #pragma code_seg(push, ".m$_4")
     30 DECLSPEC_NOINLINE static void CatchThis() {
     31   __try {
     32     ::RaiseException(STATUS_ACCESS_VIOLATION, 0, 0, NULL);
     33   } __except(EXCEPTION_EXECUTE_HANDLER) {
     34 
     35   }
     36 
     37   // this will be detected since we are on the stack!
     38   Undetectable(STATUS_ILLEGAL_INSTRUCTION);
     39 }
     40 #pragma code_seg(pop)
     41 
     42 #pragma code_seg(push, ".m$_9")
     43 static void ModuleEnd() {}
     44 #pragma code_seg(pop)
     45 
     46 using testing::_;
     47 namespace {
     48 MATCHER_P(ExceptionCodeIs, code, "") {
     49   return (arg->ExceptionRecord->ExceptionCode == code);
     50 }
     51 
     52 class MockApi : public Win32VEHTraits,
     53                 public ModuleOfInterestWithExcludedRegion {
     54  public:
     55   MockApi() {
     56     ModuleOfInterestWithExcludedRegion::SetModule(&ModuleStart, &ModuleEnd);
     57     ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&Undetectable,
     58         &UndetectableEnd);
     59   }
     60 
     61   MOCK_METHOD1(WriteDump, void(const EXCEPTION_POINTERS*));
     62   MOCK_METHOD0(RtlpGetExceptionList, const EXCEPTION_REGISTRATION_RECORD*());
     63 };
     64 };  // namespace
     65 
     66 typedef VectoredHandlerT<MockApi> VectoredHandlerMock;
     67 
     68 #pragma optimize("y", off)
     69 static VectoredHandlerMock* g_mock_veh = NULL;
     70 static LONG WINAPI VEH(EXCEPTION_POINTERS* exptrs) {
     71   return g_mock_veh->Handler(exptrs);
     72 }
     73 #pragma optimize("y", on)
     74 
     75 TEST(ChromeFrame, ExceptionExcludedCode) {
     76   MockApi api;
     77   VectoredHandlerMock veh(&api);
     78 
     79   g_mock_veh = &veh;
     80   void* id = ::AddVectoredExceptionHandler(FALSE, VEH);
     81 
     82   EXPECT_CALL(api, RtlpGetExceptionList())
     83       .WillRepeatedly(testing::Return(EXCEPTION_CHAIN_END));
     84 
     85   testing::Sequence s;
     86 
     87   EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ACCESS_VIOLATION)))
     88     .Times(1);
     89 
     90   EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ILLEGAL_INSTRUCTION)))
     91       .Times(1);
     92 
     93   CatchThis();
     94   EXPECT_EQ(2, veh.get_exceptions_seen());
     95 
     96   // Not detected since we are not on the stack.
     97   Undetectable(STATUS_INTEGER_DIVIDE_BY_ZERO);
     98   EXPECT_EQ(3, veh.get_exceptions_seen());
     99 
    100   ::RemoveVectoredExceptionHandler(id);
    101   g_mock_veh = NULL;
    102 }
    103