From 77ef9491336f71f16a82f9528367b980ff143912 Mon Sep 17 00:00:00 2001 From: Blind4Basics <32236948+Blind4Basics@users.noreply.github.com> Date: Tue, 29 Jun 2021 21:39:19 +0200 Subject: [PATCH] handling memory error * removed the use of `test.expect_no_error` inside the timeout utility: - done "manually", allowing to handle data passed to the thread - consequence: DOCS need an update because there isn't any extra assertion anymore, now. * tested on cw with 3.6, 3.8 wihtout imports, 3.8 with imports: work as expected. * removed a comment in the framework about the timeout (deprecated info) * added the default message for timeout ssertion (https://github.com/codewars/python-test-framework/issues/4) Still need to upddate the tests output (and maybe the tests files) --- codewars_test/test_framework.py | 51 +++++++++++---------- tests/fixtures/timeout_passing.expected.txt | 2 - 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/codewars_test/test_framework.py b/codewars_test/test_framework.py index cbe0993..b76af94 100644 --- a/codewars_test/test_framework.py +++ b/codewars_test/test_framework.py @@ -85,14 +85,7 @@ def assert_approx_equals( expect(abs((actual - expected) / div) < margin, message, allow_raise) -''' -Usage: -@describe('describe text') -def describe1(): - @it('it text') - def it1(): - # some test cases... -''' + def _timed_block_factory(opening_text): @@ -126,28 +119,38 @@ def wrapper(func): it = _timed_block_factory('IT') -''' -Timeout utility -Usage: -@timeout(sec) -def some_tests(): - any code block... -Note: Timeout value can be a float. -''' - -def timeout(sec): +def timeout(sec, user_msg=""): + def wrapper(func): - from multiprocessing import Process + from multiprocessing import Process, Value msg = 'Should not throw any exceptions inside timeout' - def wrapped(): - expect_no_error(msg, func) - process = Process(target=wrapped) + def wrapped(finished): + try: + func() + finished.value = 1.0 + except BaseException as e: + finished.value = 1.0 + fail("{}: {}".format(msg or "Unexpected exception", repr(e))) + + finished = Value('d',0.0) + # needed to know if the process crashed without any "feedback" and before any + # assertion has been done in the wrapped function or the wrapper (happens if + # the heap memory explodes) + + process = Process(target=wrapped, args=(finished,)) process.start() process.join(sec) + if process.is_alive(): - fail('Exceeded time limit of {:.3f} seconds'.format(sec)) + msg = 'Exceeded time limit of {:.3f} seconds'.format(sec) + if user_msg: + msg += ': ' + user_msg + fail(msg) process.terminate() process.join() - return wrapper + elif not finished.value: + fail('Something went wrong: the process running the function crashed without feedback (probably saturating the available memory)') + + return wrapper \ No newline at end of file diff --git a/tests/fixtures/timeout_passing.expected.txt b/tests/fixtures/timeout_passing.expected.txt index a0894ac..eed4f76 100644 --- a/tests/fixtures/timeout_passing.expected.txt +++ b/tests/fixtures/timeout_passing.expected.txt @@ -3,6 +3,4 @@ Test Passed -Test Passed - 17.19