diff --git a/Userland/Libraries/LibTest/CrashTest.cpp b/Userland/Libraries/LibTest/CrashTest.cpp index fcdb3ffc6f..a6e1f3ae61 100644 --- a/Userland/Libraries/LibTest/CrashTest.cpp +++ b/Userland/Libraries/LibTest/CrashTest.cpp @@ -13,16 +13,16 @@ namespace Test { Crash::Crash(String test_type, Function crash_function) - : m_type(test_type) + : m_type(move(test_type)) , m_crash_function(move(crash_function)) { } -void Crash::run(RunType run_type = RunType::UsingChildProcess) +bool Crash::run(RunType run_type) { printf("\x1B[33mTesting\x1B[0m: \"%s\"\n", m_type.characters()); - auto run_crash_and_print_if_error = [this]() { + auto run_crash_and_print_if_error = [this]() -> bool { auto failure = m_crash_function(); // If we got here something went wrong @@ -37,10 +37,11 @@ void Crash::run(RunType run_type = RunType::UsingChildProcess) default: VERIFY_NOT_REACHED(); } + return false; }; if (run_type == RunType::UsingCurrentProcess) { - run_crash_and_print_if_error(); + return run_crash_and_print_if_error(); } else { // Run the test in a child process so that we do not crash the crash program :^) @@ -55,8 +56,11 @@ void Crash::run(RunType run_type = RunType::UsingChildProcess) int status; waitpid(pid, &status, 0); - if (WIFSIGNALED(status)) + if (WIFSIGNALED(status)) { printf("\x1B[32mPASS\x1B[0m: Terminated with signal %d\n", WTERMSIG(status)); + return true; + } + return false; } } diff --git a/Userland/Libraries/LibTest/CrashTest.h b/Userland/Libraries/LibTest/CrashTest.h index 40bc7f5727..f7dbf1f217 100644 --- a/Userland/Libraries/LibTest/CrashTest.h +++ b/Userland/Libraries/LibTest/CrashTest.h @@ -27,7 +27,7 @@ public: Crash(String test_type, Function crash_function); - void run(RunType run_type); + bool run(RunType run_type = RunType::UsingChildProcess); private: String m_type; diff --git a/Userland/Libraries/LibTest/Macros.h b/Userland/Libraries/LibTest/Macros.h index 64322d5adf..b0d9722764 100644 --- a/Userland/Libraries/LibTest/Macros.h +++ b/Userland/Libraries/LibTest/Macros.h @@ -9,6 +9,7 @@ #include #include +#include namespace AK { template @@ -101,3 +102,14 @@ void current_test_case_did_fail(); ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: {}", __FILE__, __LINE__, message); \ ::Test::current_test_case_did_fail(); \ } while (false) + +// To use, specify the lambda to execute in a sub process and verify it exits: +// EXPECT_CRASH("This should fail", []{ +// return Test::Crash::Failure::DidNotCrash; +// }); +#define EXPECT_CRASH(test_message, test_func) \ + do { \ + Test::Crash crash(test_message, test_func); \ + if (!crash.run()) \ + ::Test::current_test_case_did_fail(); \ + } while (false)