1 //===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/Compiler.h"
11 #include "llvm/Support/CrashRecoveryContext.h"
12 #include "gtest/gtest.h"
13
14 #ifdef _WIN32
15 #define WIN32_LEAN_AND_MEAN
16 #define NOGDI
17 #include <windows.h>
18 #endif
19
20 using namespace llvm;
21 using namespace llvm::sys;
22
23 static int GlobalInt = 0;
nullDeref()24 static void nullDeref() { *(volatile int *)0x10 = 0; }
incrementGlobal()25 static void incrementGlobal() { ++GlobalInt; }
llvmTrap()26 static void llvmTrap() { LLVM_BUILTIN_TRAP; }
27
TEST(CrashRecoveryTest,Basic)28 TEST(CrashRecoveryTest, Basic) {
29 llvm::CrashRecoveryContext::Enable();
30 GlobalInt = 0;
31 EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal));
32 EXPECT_EQ(1, GlobalInt);
33 EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref));
34 EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap));
35 }
36
37 struct IncrementGlobalCleanup : CrashRecoveryContextCleanup {
IncrementGlobalCleanupIncrementGlobalCleanup38 IncrementGlobalCleanup(CrashRecoveryContext *CRC)
39 : CrashRecoveryContextCleanup(CRC) {}
recoverResourcesIncrementGlobalCleanup40 virtual void recoverResources() { ++GlobalInt; }
41 };
42
noop()43 static void noop() {}
44
TEST(CrashRecoveryTest,Cleanup)45 TEST(CrashRecoveryTest, Cleanup) {
46 llvm::CrashRecoveryContext::Enable();
47 GlobalInt = 0;
48 {
49 CrashRecoveryContext CRC;
50 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
51 EXPECT_TRUE(CRC.RunSafely(noop));
52 } // run cleanups
53 EXPECT_EQ(1, GlobalInt);
54
55 GlobalInt = 0;
56 {
57 CrashRecoveryContext CRC;
58 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
59 EXPECT_FALSE(CRC.RunSafely(nullDeref));
60 } // run cleanups
61 EXPECT_EQ(1, GlobalInt);
62 }
63
64 #ifdef _WIN32
raiseIt()65 static void raiseIt() {
66 RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL);
67 }
68
TEST(CrashRecoveryTest,RaiseException)69 TEST(CrashRecoveryTest, RaiseException) {
70 llvm::CrashRecoveryContext::Enable();
71 EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt));
72 }
73
outputString()74 static void outputString() {
75 OutputDebugStringA("output for debugger\n");
76 }
77
TEST(CrashRecoveryTest,CallOutputDebugString)78 TEST(CrashRecoveryTest, CallOutputDebugString) {
79 llvm::CrashRecoveryContext::Enable();
80 EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString));
81 }
82
83 #endif
84