summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/ADT/BitVectorTest.cpp184
-rw-r--r--unittests/Analysis/ProfileSummaryInfoTest.cpp8
-rw-r--r--unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp1
-rw-r--r--unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp20
-rw-r--r--unittests/Support/BinaryStreamTest.cpp29
-rw-r--r--unittests/Support/CMakeLists.txt1
-rw-r--r--unittests/Support/CrashRecoveryTest.cpp83
7 files changed, 310 insertions, 16 deletions
diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp
index faf362abc9d8c..d6a2075ca6094 100644
--- a/unittests/ADT/BitVectorTest.cpp
+++ b/unittests/ADT/BitVectorTest.cpp
@@ -182,15 +182,13 @@ TYPED_TEST(BitVectorTest, TrivialOperation) {
EXPECT_TRUE(Vec.empty());
}
-TYPED_TEST(BitVectorTest, FindOperations) {
+TYPED_TEST(BitVectorTest, SimpleFindOps) {
// Test finding in an empty BitVector.
TypeParam A;
EXPECT_EQ(-1, A.find_first());
EXPECT_EQ(-1, A.find_last());
EXPECT_EQ(-1, A.find_first_unset());
EXPECT_EQ(-1, A.find_last_unset());
- EXPECT_EQ(-1, A.find_next(0));
- EXPECT_EQ(-1, A.find_next_unset(0));
// Test finding next set and unset bits in a BitVector with multiple words
A.resize(100);
@@ -222,9 +220,10 @@ TYPED_TEST(BitVectorTest, FindOperations) {
A.set(0, 100);
EXPECT_EQ(100U, A.count());
EXPECT_EQ(0, A.find_first());
- EXPECT_EQ(99, A.find_last());
EXPECT_EQ(-1, A.find_first_unset());
EXPECT_EQ(-1, A.find_last_unset());
+ EXPECT_EQ(99, A.find_last());
+ EXPECT_EQ(99, A.find_next(98));
A.reset(0, 100);
EXPECT_EQ(0U, A.count());
@@ -232,6 +231,7 @@ TYPED_TEST(BitVectorTest, FindOperations) {
EXPECT_EQ(-1, A.find_last());
EXPECT_EQ(0, A.find_first_unset());
EXPECT_EQ(99, A.find_last_unset());
+ EXPECT_EQ(99, A.find_next_unset(98));
// Also test with a vector that is small enough to fit in 1 word.
A.resize(20);
@@ -258,6 +258,153 @@ TYPED_TEST(BitVectorTest, FindOperations) {
EXPECT_EQ(17, A.find_next_unset(15));
}
+TEST(BitVectorTest, FindInRangeMultiWord) {
+ BitVector Vec;
+
+ Vec.resize(200);
+ Vec.set(3, 7);
+ Vec.set(24, 35);
+ Vec.set(50, 70);
+ Vec.set(150);
+ Vec.set(152);
+ Vec.set(154);
+
+ // find first
+ EXPECT_EQ(-1, Vec.find_first_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_first_in(7, 24));
+
+ EXPECT_EQ(3, Vec.find_first_in(0, 10));
+ EXPECT_EQ(4, Vec.find_first_in(4, 10));
+ EXPECT_EQ(150, Vec.find_first_in(100, 200));
+ EXPECT_EQ(152, Vec.find_first_in(151, 200));
+ EXPECT_EQ(154, Vec.find_first_in(153, 200));
+
+ EXPECT_EQ(-1, Vec.find_first_in(155, 200));
+ Vec.set(199);
+ EXPECT_EQ(199, Vec.find_first_in(199, 200));
+ Vec.reset(199);
+
+ // find last
+ EXPECT_EQ(-1, Vec.find_last_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_last_in(7, 24));
+
+ EXPECT_EQ(6, Vec.find_last_in(0, 10));
+ EXPECT_EQ(5, Vec.find_last_in(0, 6));
+ EXPECT_EQ(154, Vec.find_last_in(100, 155));
+ EXPECT_EQ(152, Vec.find_last_in(100, 154));
+ EXPECT_EQ(150, Vec.find_last_in(100, 152));
+ EXPECT_EQ(-1, Vec.find_last_in(100, 150));
+ Vec.set(199);
+ EXPECT_EQ(199, Vec.find_last_in(199, 200));
+ Vec.reset(199);
+
+ // find first unset
+ EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(24, 35));
+
+ EXPECT_EQ(0, Vec.find_first_unset_in(0, 10));
+ EXPECT_EQ(1, Vec.find_first_unset_in(1, 10));
+ EXPECT_EQ(7, Vec.find_first_unset_in(5, 25));
+ EXPECT_EQ(151, Vec.find_first_unset_in(150, 200));
+ EXPECT_EQ(151, Vec.find_first_unset_in(151, 200));
+ EXPECT_EQ(153, Vec.find_first_unset_in(152, 200));
+ EXPECT_EQ(153, Vec.find_first_unset_in(153, 200));
+ EXPECT_EQ(155, Vec.find_first_unset_in(154, 200));
+ EXPECT_EQ(155, Vec.find_first_unset_in(155, 200));
+ EXPECT_EQ(199, Vec.find_first_unset_in(199, 200));
+
+ // find last unset
+ EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(24, 35));
+
+ EXPECT_EQ(9, Vec.find_last_unset_in(0, 10));
+ EXPECT_EQ(8, Vec.find_last_unset_in(0, 9));
+ EXPECT_EQ(2, Vec.find_last_unset_in(0, 7));
+ EXPECT_EQ(149, Vec.find_last_unset_in(100, 151));
+ EXPECT_EQ(151, Vec.find_last_unset_in(100, 152));
+ EXPECT_EQ(151, Vec.find_last_unset_in(100, 153));
+ EXPECT_EQ(153, Vec.find_last_unset_in(100, 154));
+ EXPECT_EQ(153, Vec.find_last_unset_in(100, 155));
+ EXPECT_EQ(155, Vec.find_last_unset_in(100, 156));
+ EXPECT_EQ(199, Vec.find_last_unset_in(199, 200));
+}
+
+TEST(BitVectorTest, FindInRangeSingleWord) {
+ // When the bit vector contains only a single word, this is slightly different
+ // than when the bit vector contains multiple words, because masks are applied
+ // to the front and back of the same word. So make sure this works.
+ BitVector Vec;
+
+ Vec.resize(25);
+ Vec.set(2, 4);
+ Vec.set(6, 9);
+ Vec.set(12, 15);
+ Vec.set(19);
+ Vec.set(21);
+ Vec.set(23);
+
+ // find first
+ EXPECT_EQ(-1, Vec.find_first_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_first_in(9, 12));
+
+ EXPECT_EQ(2, Vec.find_first_in(0, 10));
+ EXPECT_EQ(6, Vec.find_first_in(4, 10));
+ EXPECT_EQ(19, Vec.find_first_in(18, 25));
+ EXPECT_EQ(21, Vec.find_first_in(20, 25));
+ EXPECT_EQ(23, Vec.find_first_in(22, 25));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 25));
+
+ // find last
+ EXPECT_EQ(-1, Vec.find_last_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_last_in(9, 12));
+
+ EXPECT_EQ(8, Vec.find_last_in(0, 10));
+ EXPECT_EQ(3, Vec.find_last_in(0, 6));
+ EXPECT_EQ(23, Vec.find_last_in(18, 25));
+ EXPECT_EQ(21, Vec.find_last_in(18, 23));
+ EXPECT_EQ(19, Vec.find_last_in(18, 21));
+ EXPECT_EQ(-1, Vec.find_last_in(18, 19));
+
+ // find first unset
+ EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(6, 9));
+
+ EXPECT_EQ(0, Vec.find_first_unset_in(0, 6));
+ EXPECT_EQ(1, Vec.find_first_unset_in(1, 6));
+ EXPECT_EQ(9, Vec.find_first_unset_in(7, 13));
+ EXPECT_EQ(18, Vec.find_first_unset_in(18, 25));
+ EXPECT_EQ(20, Vec.find_first_unset_in(19, 25));
+ EXPECT_EQ(20, Vec.find_first_unset_in(20, 25));
+ EXPECT_EQ(22, Vec.find_first_unset_in(21, 25));
+ EXPECT_EQ(22, Vec.find_first_unset_in(22, 25));
+ EXPECT_EQ(24, Vec.find_first_unset_in(23, 25));
+ EXPECT_EQ(24, Vec.find_first_unset_in(24, 25));
+
+ // find last unset
+ EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(6, 9));
+
+ EXPECT_EQ(5, Vec.find_last_unset_in(0, 6));
+ EXPECT_EQ(4, Vec.find_last_unset_in(0, 5));
+ EXPECT_EQ(1, Vec.find_last_unset_in(0, 4));
+ EXPECT_EQ(11, Vec.find_last_unset_in(7, 13));
+ EXPECT_EQ(24, Vec.find_last_unset_in(18, 25));
+ EXPECT_EQ(22, Vec.find_last_unset_in(18, 24));
+ EXPECT_EQ(22, Vec.find_last_unset_in(18, 23));
+ EXPECT_EQ(20, Vec.find_last_unset_in(18, 22));
+ EXPECT_EQ(20, Vec.find_last_unset_in(18, 21));
+ EXPECT_EQ(18, Vec.find_last_unset_in(18, 20));
+ EXPECT_EQ(18, Vec.find_last_unset_in(18, 19));
+}
+
TYPED_TEST(BitVectorTest, CompoundAssignment) {
TypeParam A;
A.resize(10);
@@ -660,5 +807,34 @@ TYPED_TEST(BitVectorTest, EmptyVector) {
testEmpty(E);
}
+TYPED_TEST(BitVectorTest, Iterators) {
+ TypeParam Filled(10, true);
+ EXPECT_NE(Filled.set_bits_begin(), Filled.set_bits_end());
+ unsigned Counter = 0;
+ for (unsigned Bit : Filled.set_bits())
+ EXPECT_EQ(Bit, Counter++);
+
+ TypeParam Empty;
+ EXPECT_EQ(Empty.set_bits_begin(), Empty.set_bits_end());
+ for (unsigned Bit : Empty.set_bits()) {
+ (void)Bit;
+ EXPECT_TRUE(false);
+ }
+
+ TypeParam ToFill(100, false);
+ ToFill.set(0);
+ EXPECT_NE(ToFill.set_bits_begin(), ToFill.set_bits_end());
+ EXPECT_EQ(++ToFill.set_bits_begin(), ToFill.set_bits_end());
+ EXPECT_EQ(*ToFill.set_bits_begin(), 0U);
+ ToFill.reset(0);
+ EXPECT_EQ(ToFill.set_bits_begin(), ToFill.set_bits_end());
+
+ const unsigned List[] = {1, 10, 25, 99};
+ for (unsigned Num : List)
+ ToFill.set(Num);
+ unsigned i = 0;
+ for (unsigned Bit : ToFill.set_bits())
+ EXPECT_EQ(List[i++], Bit);
+}
}
#endif
diff --git a/unittests/Analysis/ProfileSummaryInfoTest.cpp b/unittests/Analysis/ProfileSummaryInfoTest.cpp
index 3454474f0376d..c9e4fc029dc01 100644
--- a/unittests/Analysis/ProfileSummaryInfoTest.cpp
+++ b/unittests/Analysis/ProfileSummaryInfoTest.cpp
@@ -102,6 +102,9 @@ TEST_F(ProfileSummaryInfoTest, TestNoProfile) {
Function *F = M->getFunction("f");
ProfileSummaryInfo PSI = buildPSI(M.get());
+ EXPECT_FALSE(PSI.hasProfileSummary());
+ EXPECT_FALSE(PSI.hasSampleProfile());
+ EXPECT_FALSE(PSI.hasInstrumentationProfile());
// In the absence of profiles, is{Hot|Cold}X methods should always return
// false.
EXPECT_FALSE(PSI.isHotCount(1000));
@@ -130,6 +133,7 @@ TEST_F(ProfileSummaryInfoTest, TestCommon) {
Function *H = M->getFunction("h");
ProfileSummaryInfo PSI = buildPSI(M.get());
+ EXPECT_TRUE(PSI.hasProfileSummary());
EXPECT_TRUE(PSI.isHotCount(400));
EXPECT_TRUE(PSI.isColdCount(2));
EXPECT_FALSE(PSI.isColdCount(100));
@@ -144,6 +148,8 @@ TEST_F(ProfileSummaryInfoTest, InstrProf) {
auto M = makeLLVMModule("InstrProf");
Function *F = M->getFunction("f");
ProfileSummaryInfo PSI = buildPSI(M.get());
+ EXPECT_TRUE(PSI.hasProfileSummary());
+ EXPECT_TRUE(PSI.hasInstrumentationProfile());
BasicBlock &BB0 = F->getEntryBlock();
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
@@ -174,6 +180,8 @@ TEST_F(ProfileSummaryInfoTest, SampleProf) {
auto M = makeLLVMModule("SampleProfile");
Function *F = M->getFunction("f");
ProfileSummaryInfo PSI = buildPSI(M.get());
+ EXPECT_TRUE(PSI.hasProfileSummary());
+ EXPECT_TRUE(PSI.hasSampleProfile());
BasicBlock &BB0 = F->getEntryBlock();
BasicBlock *BB1 = BB0.getTerminator()->getSuccessor(0);
diff --git a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
index fedb5978da816..9ff37e93b151b 100644
--- a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
+++ b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
diff --git a/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp b/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
index 6995e8f9dded2..1a30dad7b3411 100644
--- a/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
+++ b/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
@@ -126,8 +126,8 @@ TEST_F(TypeServerHandlerTest, VisitRecordNoTypeServer) {
Pipeline.addCallbackToPipeline(C1);
Pipeline.addCallbackToPipeline(C2);
- CVTypeVisitor Visitor(Pipeline);
- EXPECT_NO_ERROR(Visitor.visitTypeRecord(TypeServerRecord));
+
+ EXPECT_NO_ERROR(codeview::visitTypeRecord(TypeServerRecord, Pipeline));
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C1.S);
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C2.S);
@@ -139,16 +139,16 @@ TEST_F(TypeServerHandlerTest, VisitRecordWithTypeServerOnce) {
MockTypeServerHandler Handler(false);
MockTypeVisitorCallbacks C1;
- CVTypeVisitor Visitor(C1);
- Visitor.addTypeServerHandler(Handler);
// Our mock server returns true the first time.
- EXPECT_NO_ERROR(Visitor.visitTypeRecord(TypeServerRecord));
+ EXPECT_NO_ERROR(codeview::visitTypeRecord(
+ TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
// And false the second time.
- EXPECT_NO_ERROR(Visitor.visitTypeRecord(TypeServerRecord));
+ EXPECT_NO_ERROR(codeview::visitTypeRecord(
+ TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C1.S);
}
@@ -160,14 +160,14 @@ TEST_F(TypeServerHandlerTest, VisitRecordWithTypeServerAlways) {
MockTypeServerHandler Handler(true);
MockTypeVisitorCallbacks C1;
- CVTypeVisitor Visitor(C1);
- Visitor.addTypeServerHandler(Handler);
- EXPECT_NO_ERROR(Visitor.visitTypeRecord(TypeServerRecord));
+ EXPECT_NO_ERROR(codeview::visitTypeRecord(
+ TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
- EXPECT_NO_ERROR(Visitor.visitTypeRecord(TypeServerRecord));
+ EXPECT_NO_ERROR(codeview::visitTypeRecord(
+ TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
}
diff --git a/unittests/Support/BinaryStreamTest.cpp b/unittests/Support/BinaryStreamTest.cpp
index 41567dad62260..ec3b0effc9e9a 100644
--- a/unittests/Support/BinaryStreamTest.cpp
+++ b/unittests/Support/BinaryStreamTest.cpp
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include <unordered_map>
+#include <utility>
using namespace llvm;
using namespace llvm::support;
@@ -117,7 +118,7 @@ private:
// Buffer is organized like this:
// -------------------------------------------------
- // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N-2-1 |
+ // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N/2-1 |
// -------------------------------------------------
// So reads from the beginning actually come from the middle.
MutableArrayRef<uint8_t> Data;
@@ -348,6 +349,30 @@ TEST_F(BinaryStreamTest, FixedStreamArray) {
}
}
+// Ensure FixedStreamArrayIterator::operator-> works.
+// Added for coverage of r302257.
+TEST_F(BinaryStreamTest, FixedStreamArrayIteratorArrow) {
+ std::vector<std::pair<uint32_t, uint32_t>> Pairs = {{867, 5309}, {555, 1212}};
+ ArrayRef<uint8_t> PairBytes(reinterpret_cast<uint8_t *>(Pairs.data()),
+ Pairs.size() * sizeof(Pairs[0]));
+
+ initializeInput(PairBytes, alignof(uint32_t));
+
+ for (auto &Stream : Streams) {
+ ASSERT_EQ(InputData.size(), Stream.Input->getLength());
+
+ const FixedStreamArray<std::pair<uint32_t, uint32_t>> Array(*Stream.Input);
+ auto Iter = Array.begin();
+ ASSERT_EQ(Pairs[0].first, Iter->first);
+ ASSERT_EQ(Pairs[0].second, Iter->second);
+ ++Iter;
+ ASSERT_EQ(Pairs[1].first, Iter->first);
+ ASSERT_EQ(Pairs[1].second, Iter->second);
+ ++Iter;
+ ASSERT_EQ(Array.end(), Iter);
+ }
+}
+
// Test that VarStreamArray works correctly.
TEST_F(BinaryStreamTest, VarStreamArray) {
StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super "
@@ -686,7 +711,7 @@ TEST_F(BinaryStreamTest, BinaryItemStream) {
std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
BumpPtrAllocator Allocator;
for (const auto &F : Foos) {
- uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
+ uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
alignof(Foo)));
MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
MutableBinaryByteStream Stream(Buffer, llvm::support::big);
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index f8d3c1c9a8c77..e7f2f515d76a7 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -11,6 +11,7 @@ add_llvm_unittest(SupportTests
BlockFrequencyTest.cpp
BranchProbabilityTest.cpp
CachePruningTest.cpp
+ CrashRecoveryTest.cpp
Casting.cpp
Chrono.cpp
CommandLineTest.cpp
diff --git a/unittests/Support/CrashRecoveryTest.cpp b/unittests/Support/CrashRecoveryTest.cpp
new file mode 100644
index 0000000000000..dbb0db5767937
--- /dev/null
+++ b/unittests/Support/CrashRecoveryTest.cpp
@@ -0,0 +1,83 @@
+//===- 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/CrashRecoveryContext.h"
+#include "llvm/Support/Compiler.h"
+#include "gtest/gtest.h"
+
+#ifdef LLVM_ON_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 *)nullptr = 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 LLVM_ON_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