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 LLVM_ON_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; 24 static void nullDeref() { *(volatile int *)0x10 = 0; } 25 static void incrementGlobal() { ++GlobalInt; } 26 static void llvmTrap() { LLVM_BUILTIN_TRAP; } 27 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 { 38 IncrementGlobalCleanup(CrashRecoveryContext *CRC) 39 : CrashRecoveryContextCleanup(CRC) {} 40 virtual void recoverResources() { ++GlobalInt; } 41 }; 42 43 static void noop() {} 44 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 LLVM_ON_WIN32 65 static void raiseIt() { 66 RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL); 67 } 68 69 TEST(CrashRecoveryTest, RaiseException) { 70 llvm::CrashRecoveryContext::Enable(); 71 EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt)); 72 } 73 74 static void outputString() { 75 OutputDebugStringA("output for debugger\n"); 76 } 77 78 TEST(CrashRecoveryTest, CallOutputDebugString) { 79 llvm::CrashRecoveryContext::Enable(); 80 EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString)); 81 } 82 83 #endif 84