Могу ли я обойти обработчик SystemExit UnitTest?

Я переписываю afl-fuzz (приложение C) на Python. Поскольку у меня недостаточно понимания его внутренней работы, я хотел бы воспроизвести его функциональность как можно ближе.

Я пытаюсь запустить функциональный тест подпрограммы, которая разветвляет интерпретатор Python, запускает execve и, если он терпит неудачу, сообщает об ошибке вызывающей стороне, возвращая 42. Тест работает хорошо вне unittest, но терпит неудачу, когда его помещают в него:

#!/usr/bin/env python

import os
import sys
import unittest


def run_test():
    x = os.fork()
    if not x:
        sys.exit(42)
    waitpid_result, status = os.waitpid(x, os.WUNTRACED)
    print(os.WEXITSTATUS(status))


class ForkFunctionalTest(unittest.TestCase):

    def test_exercise_fork(self):
        run_test()


if __name__ == '__main__':
    print('Expecting "42" as output:')
    run_test()
    print('\nAnd here goes unexpected SystemExit error:')
    unittest.main()

Вот как это не удается:

Expecting "42" as output:
42

And here goes unexpected SystemExit error:
E
======================================================================
ERROR: test_exercise_fork (__main__.ForkFunctionalTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "afl-fuzz2.py", line 23, in test_exercise_fork
    run_test()
  File "afl-fuzz2.py", line 15, in run_test
    sys.exit(42)
SystemExit: 42

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)
1
.
----------------------------------------------------------------------
Ran 1 test in 0.014s

OK

Есть ли способ заставить unittest работать с этой функцией без изменения run_test? Я попробовал os._exit вместо sys.exit(), но это привело к тому, что программа умерла в обоих процессах.


person d33tah    schedule 27.05.2017    source источник


Ответы (2)


Оказывается, os._exit действительно работал, но в моих модульных тестах мне нужно было смоделировать его, учитывая, что я смоделировал os.fork. Глупая ошибка.

person d33tah    schedule 27.05.2017

sys.exit() вызывает исключение класса SystemExit, которое, если его не поймать, завершает работу программы. Вы можете попытаться поймать исключение:

def text_exercise_fork(self):
    try:
        run_test()
    except SystemExit as e:
        print(e.args[0])
person Fulgen    schedule 27.05.2017
comment
Спасибо. Дело в том, что я не хочу его ловить, я хочу, чтобы разветвленный процесс умер с кодом выхода = 42. - person d33tah; 27.05.2017