| //===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/Support/Compiler.h" | 
 | #include "llvm/Support/CrashRecoveryContext.h" | 
 | #include "gtest/gtest.h" | 
 |  | 
 | #ifdef _WIN32 | 
 | #define WIN32_LEAN_AND_MEAN | 
 | #define NOGDI | 
 | #include <windows.h> | 
 | #endif | 
 |  | 
 | using namespace llvm; | 
 | using namespace llvm::sys; | 
 |  | 
 | static int GlobalInt = 0; | 
 | static void nullDeref() { *(volatile int *)0x10 = 0; } | 
 | static void incrementGlobal() { ++GlobalInt; } | 
 | static void llvmTrap() { LLVM_BUILTIN_TRAP; } | 
 |  | 
 | TEST(CrashRecoveryTest, Basic) { | 
 |   llvm::CrashRecoveryContext::Enable(); | 
 |   GlobalInt = 0; | 
 |   EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal)); | 
 |   EXPECT_EQ(1, GlobalInt); | 
 |   EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref)); | 
 |   EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap)); | 
 | } | 
 |  | 
 | struct IncrementGlobalCleanup : CrashRecoveryContextCleanup { | 
 |   IncrementGlobalCleanup(CrashRecoveryContext *CRC) | 
 |       : CrashRecoveryContextCleanup(CRC) {} | 
 |   virtual void recoverResources() { ++GlobalInt; } | 
 | }; | 
 |  | 
 | static void noop() {} | 
 |  | 
 | TEST(CrashRecoveryTest, Cleanup) { | 
 |   llvm::CrashRecoveryContext::Enable(); | 
 |   GlobalInt = 0; | 
 |   { | 
 |     CrashRecoveryContext CRC; | 
 |     CRC.registerCleanup(new IncrementGlobalCleanup(&CRC)); | 
 |     EXPECT_TRUE(CRC.RunSafely(noop)); | 
 |   } // run cleanups | 
 |   EXPECT_EQ(1, GlobalInt); | 
 |  | 
 |   GlobalInt = 0; | 
 |   { | 
 |     CrashRecoveryContext CRC; | 
 |     CRC.registerCleanup(new IncrementGlobalCleanup(&CRC)); | 
 |     EXPECT_FALSE(CRC.RunSafely(nullDeref)); | 
 |   } // run cleanups | 
 |   EXPECT_EQ(1, GlobalInt); | 
 | } | 
 |  | 
 | #ifdef _WIN32 | 
 | static void raiseIt() { | 
 |   RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL); | 
 | } | 
 |  | 
 | TEST(CrashRecoveryTest, RaiseException) { | 
 |   llvm::CrashRecoveryContext::Enable(); | 
 |   EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt)); | 
 | } | 
 |  | 
 | static void outputString() { | 
 |   OutputDebugStringA("output for debugger\n"); | 
 | } | 
 |  | 
 | TEST(CrashRecoveryTest, CallOutputDebugString) { | 
 |   llvm::CrashRecoveryContext::Enable(); | 
 |   EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString)); | 
 | } | 
 |  | 
 | #endif |