Можно ли проверить, что процедура прерывания не возвращается? - PullRequest
6 голосов
/ 19 апреля 2019

Мне нужно протестировать библиотеку, которая предоставляет свою собственную функцию abort_routine () (которая вызывает abort () внутри, но реализация может измениться).

Одно из требований для этой функции abort_routine () заключается в том, что онаможет не вернуться.

Мне интересно, можно ли проверить это требование?

ОБНОВЛЕНИЕ: Я не пользуюсь gtest, только горит llvm и тому подобное: вернуть 0, вернуть 1, подтвердить (ложь).

Ответы [ 3 ]

6 голосов
/ 19 апреля 2019

Это хороший вариант использования для fork, и я сам использую его в своих тестах.

Вы можете просто fork(), запустить функцию в дочернем элементе, _exit() дочерний элемент, получить результат, и, если он указывает, что процессу было сообщено с помощью SIGABRT, дочерний элемент прервался, в противном случае это не так.

Пример кода:

#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

int fork_and_reap(int *Ws, void Fn(void *), void *Arg)
{
    pid_t pid; if (0>(pid=fork())) return -1;
    if(0==pid) (void)Fn(Arg), _exit(0);
    else for(;;){
        if(0>waitpid(pid,Ws,WUNTRACED)){
            if(EINTR==errno) continue;
            else abort();
        }else if(!WIFEXITED(*Ws)&&!WIFSIGNALED(*Ws)){ //shouldn't have stopped
            if(0>kill(pid,SIGTERM) ||0>kill(pid,SIGCONT)) abort();
        }else break;
    }
    return 0;
}
void aborting(void *A){ (void)A; abort(); }
void not_aborting(void *A){ (void)A; }

int main()
{
    int ws;
    if(0<=fork_and_reap(&ws, aborting, 0) && WIFSIGNALED(ws) && WTERMSIG(SIGABRT)) puts("aborted"); else puts("didn't abort");
    if(0<=fork_and_reap(&ws, not_aborting, 0) && WIFSIGNALED(ws) && WTERMSIG(SIGABRT)) puts("aborted"); else puts("didn't abort");
}
1 голос
/ 19 апреля 2019

См. Ключевое слово _Noreturn:

"Ключевое слово _Noreturn появляется в объявлении функции и указывает, что функция не возвращается, выполнив оператор return или достигнув конца тела функции (он может вернуться, выполнив longjmp.) Если функция, объявленная _Noreturn, возвращает значение, поведение не определено. Рекомендуется диагностика компилятора, если ее можно обнаружить . "

Если функцияобъявленный как таковой, компилятор должен выдать диагностическое сообщение.Таким образом, вам не нужно тестировать его, но вы можете проверить сообщения компилятора и выполнить проверку кода

https://en.cppreference.com/w/c/language/_Noreturn

1 голос
/ 19 апреля 2019

Как общее решение, вы можете протестировать его, запустив как отдельный процесс, например:

int main()
{
    abort_routine();
    printf("Didn't abort\n");
    return 0;
}

Вы сможете увидеть, когда вы запустите его как дочерний процесс, если он был прерван (напечатал некоторый вывод прерывания вместо ненулевого выхода) или нет (напечатал этот вывод и завершился с нулем).

Примерно так работают "тесты на смерть" в gtest, https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#how-it-works

Под капотом ASSERT_EXIT () запускает новый процесс и выполняет в этом процессе оператор теста на смерть. Детали того, как именно это происходит, зависят от платформы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...