test_cpp.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from __future__ import print_function
  2. from __future__ import absolute_import
  3. import subprocess
  4. import unittest
  5. import greenlet
  6. from . import _test_extension_cpp
  7. from . import TestCase
  8. from . import WIN
  9. class CPPTests(TestCase):
  10. def test_exception_switch(self):
  11. greenlets = []
  12. for i in range(4):
  13. g = greenlet.greenlet(_test_extension_cpp.test_exception_switch)
  14. g.switch(i)
  15. greenlets.append(g)
  16. for i, g in enumerate(greenlets):
  17. self.assertEqual(g.switch(), i)
  18. def _do_test_unhandled_exception(self, target):
  19. import os
  20. import sys
  21. script = os.path.join(
  22. os.path.dirname(__file__),
  23. 'fail_cpp_exception.py',
  24. )
  25. args = [sys.executable, script, target.__name__ if not isinstance(target, str) else target]
  26. __traceback_info__ = args
  27. with self.assertRaises(subprocess.CalledProcessError) as exc:
  28. subprocess.check_output(
  29. args,
  30. encoding='utf-8',
  31. stderr=subprocess.STDOUT
  32. )
  33. ex = exc.exception
  34. expected_exit = self.get_expected_returncodes_for_aborted_process()
  35. self.assertIn(ex.returncode, expected_exit)
  36. self.assertIn('fail_cpp_exception is running', ex.output)
  37. return ex.output
  38. def test_unhandled_nonstd_exception_aborts(self):
  39. # verify that plain unhandled throw aborts
  40. self._do_test_unhandled_exception(_test_extension_cpp.test_exception_throw_nonstd)
  41. def test_unhandled_std_exception_aborts(self):
  42. # verify that plain unhandled throw aborts
  43. self._do_test_unhandled_exception(_test_extension_cpp.test_exception_throw_std)
  44. @unittest.skipIf(WIN, "XXX: This does not crash on Windows")
  45. # Meaning the exception is getting lost somewhere...
  46. def test_unhandled_std_exception_as_greenlet_function_aborts(self):
  47. # verify that plain unhandled throw aborts
  48. output = self._do_test_unhandled_exception('run_as_greenlet_target')
  49. self.assertIn(
  50. # We really expect this to be prefixed with "greenlet: Unhandled C++ exception:"
  51. # as added by our handler for std::exception (see TUserGreenlet.cpp), but
  52. # that's not correct everywhere --- our handler never runs before std::terminate
  53. # gets called (for example, on arm32).
  54. 'Thrown from an extension.',
  55. output
  56. )
  57. def test_unhandled_exception_in_greenlet_aborts(self):
  58. # verify that unhandled throw called in greenlet aborts too
  59. self._do_test_unhandled_exception('run_unhandled_exception_in_greenlet_aborts')
  60. if __name__ == '__main__':
  61. unittest.main()