blob: d863dd06f09189b71c48ff04a687ef4e932c08c0 [file] [log] [blame]
Reid Kleckner710c1ce2017-05-17 18:16:17 +00001//===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Reid Kleckner710c1ce2017-05-17 18:16:17 +00006//
7//===----------------------------------------------------------------------===//
8
Reid Kleckner710c1ce2017-05-17 18:16:17 +00009#include "llvm/Support/Compiler.h"
Chandler Carruth9a67b072017-06-06 11:06:56 +000010#include "llvm/Support/CrashRecoveryContext.h"
Reid Kleckner710c1ce2017-05-17 18:16:17 +000011#include "gtest/gtest.h"
12
Nico Weber712e8d22018-04-29 00:45:03 +000013#ifdef _WIN32
Reid Kleckner710c1ce2017-05-17 18:16:17 +000014#define WIN32_LEAN_AND_MEAN
15#define NOGDI
16#include <windows.h>
17#endif
18
19using namespace llvm;
20using namespace llvm::sys;
21
22static int GlobalInt = 0;
Vitaly Buka1887dd82017-05-24 18:11:57 +000023static void nullDeref() { *(volatile int *)0x10 = 0; }
Reid Kleckner710c1ce2017-05-17 18:16:17 +000024static void incrementGlobal() { ++GlobalInt; }
25static void llvmTrap() { LLVM_BUILTIN_TRAP; }
26
27TEST(CrashRecoveryTest, Basic) {
28 llvm::CrashRecoveryContext::Enable();
29 GlobalInt = 0;
30 EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal));
31 EXPECT_EQ(1, GlobalInt);
32 EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref));
33 EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap));
34}
35
36struct IncrementGlobalCleanup : CrashRecoveryContextCleanup {
37 IncrementGlobalCleanup(CrashRecoveryContext *CRC)
38 : CrashRecoveryContextCleanup(CRC) {}
39 virtual void recoverResources() { ++GlobalInt; }
40};
41
42static void noop() {}
43
44TEST(CrashRecoveryTest, Cleanup) {
45 llvm::CrashRecoveryContext::Enable();
46 GlobalInt = 0;
47 {
48 CrashRecoveryContext CRC;
49 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
50 EXPECT_TRUE(CRC.RunSafely(noop));
51 } // run cleanups
52 EXPECT_EQ(1, GlobalInt);
53
54 GlobalInt = 0;
55 {
56 CrashRecoveryContext CRC;
57 CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
58 EXPECT_FALSE(CRC.RunSafely(nullDeref));
59 } // run cleanups
60 EXPECT_EQ(1, GlobalInt);
61}
62
Nico Weber712e8d22018-04-29 00:45:03 +000063#ifdef _WIN32
Reid Kleckner710c1ce2017-05-17 18:16:17 +000064static void raiseIt() {
65 RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL);
66}
67
68TEST(CrashRecoveryTest, RaiseException) {
69 llvm::CrashRecoveryContext::Enable();
70 EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt));
71}
72
73static void outputString() {
74 OutputDebugStringA("output for debugger\n");
75}
76
77TEST(CrashRecoveryTest, CallOutputDebugString) {
78 llvm::CrashRecoveryContext::Enable();
79 EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString));
80}
81
82#endif