we generally do not want to catch or throw these. catching them to print and discard is fine, tests are largely exempt, and cases in which we can be certain where the exception came from are also fine to *catch*. we'll try to never *throw* (or rethrow) these if possible though because doing so will make it impossible to construct async traces for the exceptions. Change-Id: I3b71c32ecd16afc2246c946472f5629a1fa31f2c
59 lines
1.2 KiB
C++
59 lines
1.2 KiB
C++
#include <gtest/gtest.h>
|
|
#include "lix/libmain/crash-handler.hh"
|
|
|
|
namespace nix {
|
|
|
|
class OopsException : public std::exception
|
|
{
|
|
const char * msg;
|
|
|
|
public:
|
|
OopsException(const char * msg) : msg(msg) {}
|
|
const char * what() const noexcept override
|
|
{
|
|
return msg;
|
|
}
|
|
};
|
|
|
|
void causeCrashForTesting(std::function<void()> fixture)
|
|
{
|
|
registerCrashHandler();
|
|
std::cerr << "time to crash\n";
|
|
try {
|
|
fixture();
|
|
} catch (...) {
|
|
std::terminate();
|
|
}
|
|
}
|
|
|
|
TEST(CrashHandler, exceptionName)
|
|
{
|
|
ASSERT_DEATH(
|
|
causeCrashForTesting([]() {
|
|
throw OopsException{"lol oops"}; // NOLINT(lix-foreign-exceptions)
|
|
}),
|
|
"time to crash\nLix crashed.*OopsException: lol oops"
|
|
);
|
|
}
|
|
|
|
TEST(CrashHandler, unknownTerminate)
|
|
{
|
|
ASSERT_DEATH(
|
|
causeCrashForTesting([]() { std::terminate(); }),
|
|
"time to crash\nLix crashed.*std::terminate\\(\\) called without exception"
|
|
);
|
|
}
|
|
|
|
TEST(CrashHandler, nonStdException)
|
|
{
|
|
ASSERT_DEATH(
|
|
causeCrashForTesting([]() {
|
|
// NOLINTNEXTLINE(hicpp-exception-baseclass, lix-foreign-exceptions): intentional
|
|
throw 4;
|
|
}),
|
|
"time to crash\nLix crashed.*Unknown exception! Spooky\\."
|
|
);
|
|
}
|
|
|
|
}
|