Как запустить Boost Test и создать минидампы?

В нашем проекте для модульных тестов используется Boost.Test. Мы также хотели бы получать минидампы при возникновении непредвиденных исключений во время наших тестовых случаев, поэтому мы начали интегрировать Google Breakpad для написания минидампов.

Похоже, что Boost.Test перехватывает все выброшенные исключения из пользовательских тестов - я предполагаю, потому что тестовые примеры Boost оборачивают каждую функцию с помощью try / catch, а модульный тест просто терпит неудачу, если возникает неожиданное исключение. Это предотвращает запуск и запись минидампов обработчиком исключений Breakpad.

Возможно ли, чтобы Boost.Test не просто отлавливал неожиданные исключения в модульных тестах и ​​не завершал их работу? И вместо этого позволить исключениям оставаться необработанными (или повторно генерировать), чтобы Breakpad или другой обработчик исключений мог быть запущен для записи минидампа?


person mbradber    schedule 04.10.2017    source источник


Ответы (2)


Boost.Test предназначен для перехвата всех исключений из тестового примера, чтобы продолжить выполнение других тестовых примеров. Я не думаю, что вы можете отключить это поведение, но вы всегда можете обратиться к исходному коду.

Чтобы достичь того, что вам нужно, я бы сам обернул тело тестовых примеров и перехватил исключения и выписал мини-дампы прерывания, когда генерируются неожиданные исключения. Вы можете обобщить это, написав обработчик catch / dump как функцию, которая принимает функтор, который является телом вашего тестового примера, и вызывает ваш обработчик с телом тестового примера в лямбда-выражении:

void handler(std::function<void()> test_case)
{
  try {
    test_case();
  } catch (...) {
    write_minidump();
  }
}

BOOST_AUTO_TEST_CASE(doit)
{
  handler([] {
    // do testing here
  });
}

Это будет более сложным, если вы используете приспособления, но применима та же идея.

person legalize    schedule 04.10.2017
comment
Мне нравится это предложение, однако к тому времени, когда минидамп записывается в блок catch, стек вызовов, который сохраняется в минидампе, просто показывает «обработчик» наверху стека. Однако, когда срабатывает «фильтр необработанных исключений» и записывается дамп, вызывающий ошибку стек вызовов сохраняется. - person mbradber; 04.10.2017
comment
Как панель управления настраивает обработчик исключений? - person legalize; 04.10.2017
comment
chromium.googlesource.com/breakpad/breakpad/+/master/ docs / Я создал ExceptionHandler на основе этого документа. Только с этим Breakpad устанавливает собственный обратный вызов фильтра необработанных исключений, а необработанные исключения прекрасно создают минидампы. Однако я использую API «WriteMinidump» явно в блоке catch, аналогичном тому, что вы опубликовали. - person mbradber; 04.10.2017
comment
Да, если вы напишете минидамп, захваченный в точке catch, тогда в вашем стеке будет только handler. Каким-то образом вам нужно захватить стек вызовов в момент выброса исключения. Я не уверен, как это делает брейкпад. Я знаю, что в Windows SEH вы можете запрашивать эту информацию из обработчика catch. - person legalize; 05.10.2017

Я пробовал несколько разных подходов, но следующее решение дает лучший результат. Определение макроса для обертывания макроса BOOST_AUTO_TEST_CASE и окружение вызывающего кода с помощью SEH __try / __ except и передача данных исключения в Breakpad.

#define CUSTOM_AUTO_TEST_CASE( test_name )                                                                  \
void test_name##_custom_wrapper();                                                                          \
                                                                                                            \
BOOST_AUTO_TEST_CASE( test_name )                                                                           \
{                                                                                                           \
    __try                                                                                                   \
    {                                                                                                       \
        test_name##_custom_wrapper();                                                                       \
    }                                                                                                       \
    __except(pHandler->WriteMinidumpForException(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {}  \
}                                                                                                           \
                                                                                                            \
void test_name##_custom_wrapper()                                                                           \

Где pHandler - указатель на Breakpad ExceptionHandler.

Обратной стороной является необходимость заменять каждое вхождение BOOST_AUTO_TEST_CAST макросом оболочки. Но это своеобразный трюк.

person mbradber    schedule 06.10.2017