Как протестировать макрос, который убивает процесс?

У меня есть вот такой макрос (упрощенный)

struct check_error{
  check_error() = default;   

  void check(const char* file, const int line, const char* condition) {
    std::cerr << file << "(" << line << ") - " << "Check error: " << #expr;
    __debugbreak(); // Вызывает падение процесса в MSVC.
    // __builtin_trap(); // Вызывает падение процесса в clang и gnu.
  }
};

#define MI_CHECK(condition) \
if (!condition) check_error().check(__FILE__, __LINE__, #condition)

Далее с помощью gtest я пытаюсь протестировать этот макрос.

Но дело в том, что я не могу протестировать этот макрос обычным способом

int foo() { return 1; }
int boo() { return 0; }

TEST(Check, Test1){
  EXPECT_DEATH(MI_CHECK(foo() < boo()), "Check error: foo() < boo()"); // gtest выдает ошибку
  EXPECT_DEATH(MI_CHECK(1 < 0),         "Check error: 1 < 0");         // OK
}

Потому что EXPECT_DEATH почему-то не поддерживает строки, в которых есть символы ( и ).

Ошибка, если кому-то интересно:

error: Failed
Syntax error at index 20 in simple regular expression "Check failed: a < b (2 vs. 1)": '(' is unsupported.
C:\Work\MI\build\_deps\googletest-src\googletest\src/gtest-port.cc(837): error: Failed
Syntax error at index 28 in simple regular expression "Check failed: a < b (2 vs. 1)": ')' is unsupported.
Running main() from C:\Work\MI\build\_deps\googletest-src\googletest\src\gtest_main.cc
C:\Work\MI\src\Common\MI.Check_unittest.cpp(85): error: Death test: switch (0) case 0: default: if (::mi::internal::check_op_result true_if_passed = ::mi::internal::CheckLTImpl((a), (b), "a" " " "<" " " "b")) ; else ::mi::internal::check_error("C:\\Work\\MI\\src\\Common\\MI.Check_unittest.cpp", 85).check_op(&true_if_passed).stream()
    Result: died but not with expected error.
  Expected: contains regular expression "Check failed: a < b (2 vs. 1)"
Actual msg:
[  DEATH   ] [FATAL] at [31.5.2022 - 12:25:34] in ["MI.Check_unittest.cpp"(85)] - Check failed: a < b (2 vs. 1).

Tут есть похожий макрос CHECK, для тестирования которого разработчики заменяют EXPECT_DEATH на EXPECT_CHECK.

Вот его реализация:

#define EXPECT_CHECK(msg, check_expr)                          \
  do {                                                         \
    ScopedCheckExpectation check_exp(__FILE__, __LINE__, msg); \
    check_expr;                                                \
  } while (0)

У них используется супер-пупер-гиго-нано-мега умный и волшебный класс ScopedCheckExpectation, осознать реализацию которого я не в силе :(.

Как я понял, он каким-то образом отслеживает падение процесса и при таком случае проверяет сообщение в std::cerr.

Может кто-нибудь привести пример такого класса, но с более простой реализацией?

Или, может, есть другой, более простой способ протестировать этот макрос?


Ответы (0 шт):