-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExceptionHandlerTests.cpp
More file actions
101 lines (82 loc) 路 2.61 KB
/
Copy pathExceptionHandlerTests.cpp
File metadata and controls
101 lines (82 loc) 路 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/// @file
/// @brief Unit tests for the shared crash handler (shared/ExceptionHandler.h) via WriteCrashLog.
// Unit tests for the shared crash handler (shared/ExceptionHandler.h). We can't unit test an
// actual unhandled exception (it would terminate the runner), so we drive the testable core:
// WriteCrashLog with a real context from RtlCaptureContext, pointed at a temp folder.
#include <gtest/gtest.h>
#include <Windows.h>
#include <filesystem>
#include <string>
#include "ExceptionHandler.h"
namespace
{
namespace fs = std::filesystem;
namespace EH = Shared::ExceptionHandler;
/// Fixture providing a clean temp crash directory, removed before and after each test.
class ExceptionHandlerTest : public ::testing::Test
{
protected:
fs::path crashDir;
void SetUp() override
{
crashDir = fs::temp_directory_path() / "sg_eh_tests";
std::error_code ec;
fs::remove_all(crashDir, ec);
}
void TearDown() override
{
std::error_code ec;
fs::remove_all(crashDir, ec);
}
};
TEST_F(ExceptionHandlerTest, TimestampHasExpectedShape)
{
const std::string ts = EH::CrashTimestamp(); // YYYY-MM-DD-HH-MM-SS
EXPECT_EQ(ts.size(), 19u);
EXPECT_EQ(ts[4], '-');
EXPECT_EQ(ts[7], '-');
EXPECT_EQ(ts[10], '-');
}
TEST_F(ExceptionHandlerTest, WritesReportAndRunsRecovery)
{
bool recovered = false;
int logCount = 0;
EH::Config config;
config.crashDir = crashDir;
config.exitMode = EH::ExitMode::Silent;
config.log = [&](const std::string&, const std::string&)
{ ++logCount; };
config.onCrash = [&]()
{ recovered = true; };
CONTEXT context{};
RtlCaptureContext(&context);
const LONG rc = EH::WriteCrashLog(config, 0xC0000005, &context);
EXPECT_EQ(rc, static_cast<LONG>(EH::ExitMode::Silent));
EXPECT_TRUE(recovered);
EXPECT_GE(logCount, 2);
bool wroteReport = false;
bool wroteDump = false;
for (const auto& entry : fs::recursive_directory_iterator(crashDir))
{
if (entry.path().filename() == L"StackTrace.log") wroteReport = true;
if (entry.path().filename() == L"Crash.dmp" && entry.file_size() > 0) wroteDump = true;
}
EXPECT_TRUE(wroteReport);
EXPECT_TRUE(wroteDump);
}
TEST_F(ExceptionHandlerTest, RunsWithoutCallbacksSet)
{
EH::Config config;
config.crashDir = crashDir; // no log / no onCrash
CONTEXT context{};
RtlCaptureContext(&context);
EXPECT_NO_THROW(EH::WriteCrashLog(config, 0x1, &context));
}
TEST(ExceptionHandlerInstallTest, InstallAndUninstallDoNotThrow)
{
EH::Config config;
config.crashDir = fs::temp_directory_path() / "sg_eh_install";
EXPECT_NO_THROW(EH::Install(config));
EXPECT_NO_THROW(EH::Uninstall());
}
} // namespace