summaryrefslogtreecommitdiffstats
path: root/chrome_frame/crash_reporting/veh_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome_frame/crash_reporting/veh_test.cc')
-rw-r--r--chrome_frame/crash_reporting/veh_test.cc104
1 files changed, 104 insertions, 0 deletions
diff --git a/chrome_frame/crash_reporting/veh_test.cc b/chrome_frame/crash_reporting/veh_test.cc
new file mode 100644
index 0000000..7f844e9
--- /dev/null
+++ b/chrome_frame/crash_reporting/veh_test.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <atlbase.h>
+#include "chrome_frame/crash_reporting/veh_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "chrome_frame/crash_reporting/vectored_handler-impl.h"
+
+#pragma code_seg(push, ".m$_0")
+static void ModuleStart() {}
+#pragma code_seg(pop)
+
+#pragma code_seg(push, ".m$_2")
+static void Undetectable(DWORD code) {
+ __try {
+ ::RaiseException(code, 0, 0, NULL);
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ }
+};
+#pragma code_seg(pop)
+
+#pragma code_seg(push, ".m$_3")
+static void UndetectableEnd() {}
+#pragma code_seg(pop)
+
+#pragma code_seg(push, ".m$_4")
+static void CatchThis() {
+ __try {
+ ::RaiseException(STATUS_ACCESS_VIOLATION, 0, 0, NULL);
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ }
+
+ // this will be detected since we are on the stack!
+ Undetectable(STATUS_ILLEGAL_INSTRUCTION);
+}
+
+#pragma code_seg(pop)
+
+#pragma code_seg(push, ".m$_9")
+static void ModuleEnd() {}
+#pragma code_seg(pop)
+
+using testing::_;
+namespace {
+MATCHER_P(ExceptionCodeIs, code, "") {
+ return (arg->ExceptionRecord->ExceptionCode == code);
+}
+
+class MockApi : public Win32VEHTraits,
+ public ModuleOfInterestWithExcludedRegion {
+ public:
+ MockApi() {
+ Win32VEHTraits::InitializeIgnoredBlocks();
+ ModuleOfInterestWithExcludedRegion::SetModule(&ModuleStart, &ModuleEnd);
+ ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&Undetectable,
+ &UndetectableEnd);
+ }
+
+ MOCK_METHOD1(WriteDump, void(const EXCEPTION_POINTERS*));
+ MOCK_METHOD0(RtlpGetExceptionList, const EXCEPTION_REGISTRATION_RECORD*());
+};
+}; // namespace
+
+typedef VectoredHandlerT<MockApi> VectoredHandlerMock;
+
+static VectoredHandlerMock* g_mock_veh = NULL;
+static LONG WINAPI VEH(EXCEPTION_POINTERS* exptrs) {
+ return g_mock_veh->Handler(exptrs);
+}
+
+TEST(ChromeFrame, ExceptionExcludedCode) {
+ MockApi api;
+ VectoredHandlerMock veh(&api);
+
+ g_mock_veh = &veh;
+ void* id = ::AddVectoredExceptionHandler(FALSE, VEH);
+
+ EXPECT_CALL(api, RtlpGetExceptionList())
+ .WillRepeatedly(testing::Return(EXCEPTION_CHAIN_END));
+
+ testing::Sequence s;
+
+ EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ACCESS_VIOLATION)))
+ .Times(1);
+
+ EXPECT_CALL(api, WriteDump(ExceptionCodeIs(STATUS_ILLEGAL_INSTRUCTION)))
+ .Times(1);
+
+ CatchThis();
+ EXPECT_EQ(2, veh.get_exceptions_seen());
+
+ // Not detected since we are not on the stack.
+ Undetectable(STATUS_INTEGER_DIVIDE_BY_ZERO);
+ EXPECT_EQ(3, veh.get_exceptions_seen());
+
+ ::RemoveVectoredExceptionHandler(id);
+ g_mock_veh = NULL;
+}
+
+