commit ada70d4f85ac7ce6f9847eeae832ec7620106470 Author: juga0 juga@riseup.net Date: Tue Jan 8 16:27:44 2019 +0000
scanner: check that ResultDump queue is not full
and put the result in the queue with a timeout.
Fixes bug #28866. Bugfix v0.1.0. --- sbws/core/scanner.py | 12 +++++++++++- tests/unit/conftest.py | 20 ++++++++++++++++++++ tests/unit/core/test_scanner.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/sbws/core/scanner.py b/sbws/core/scanner.py index 7246f12..4c85ee4 100644 --- a/sbws/core/scanner.py +++ b/sbws/core/scanner.py @@ -315,8 +315,18 @@ def _next_expected_amount(expected_amount, result_time, download_times, def result_putter(result_dump): ''' Create a function that takes a single argument -- the measurement result -- and return that function so it can be used by someone else ''' + def closure(measurement_result): - return result_dump.queue.put(measurement_result) + # in case the queue is full, wait until is not. + # Since result_dump thread is calling queue.get() every second, + # the queue should be full for only 1 second. + while result_dump.queue.full(): + log.info('The results queue is full, after 1 second it should ' + 'not be full.') + time.sleep(1) + # Non blocking, wait a maximum of 1 second if the queue is full. + # Because of the timeout, the previous while should not be needed. + result_dump.queue.put(measurement_result, timeout=1) return closure
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 4dd442b..ada1b9b 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -267,3 +267,23 @@ def sbwshome_success_result_two_relays(sbwshome_only_datadir, conf): write_result_to_datadir(RESULT_SUCCESS2, dd) write_result_to_datadir(RESULT_SUCCESS2, dd) return sbwshome_only_datadir + + +@pytest.fixture(scope='function') +def end_event(): + import threading + return threading.Event() + + +@pytest.fixture(scope='function') +def rd(args, conf, end_event): + from sbws.lib.resultdump import ResultDump + # in Travis the next line gives the error: + # TypeError: __init__() takes 3 positional arguments but 4 were given + # No idea why. + # Returning None to disable the test in case ResultDump can not be + # initialized. + try: + return ResultDump(args, conf, end_event) + except TypeError: + return None diff --git a/tests/unit/core/test_scanner.py b/tests/unit/core/test_scanner.py new file mode 100644 index 0000000..3f84472 --- /dev/null +++ b/tests/unit/core/test_scanner.py @@ -0,0 +1,28 @@ +"""Unit tests for scanner.py.""" +import pytest + +from sbws.core.scanner import result_putter + + +def test_result_putter(sbwshome_only_datadir, result_success, rd, end_event): + if rd is None: + pytest.skip("ResultDump is None") + # Put one item in the queue + callback = result_putter(rd) + callback(result_success) + assert rd.queue.qsize() == 1 + + # Make queue maxsize 1, so that it'll be full after the first callback. + # The second callback will wait 1 second, then the queue will be empty + # again. + rd.queue.maxsize = 1 + callback(result_success) + # after putting 1 result, the queue will be full + assert rd.queue.qsize() == 1 + assert rd.queue.full() + # it's still possible to put another results, because the callback will + # wait 1 second and the queue will be empty again. + callback(result_success) + assert rd.queue.qsize() == 1 + assert rd.queue.full() + end_event.set()