commit ada70d4f85ac7ce6f9847eeae832ec7620106470
Author: juga0 <juga(a)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
+
+
+(a)pytest.fixture(scope='function')
+def end_event():
+ import threading
+ return threading.Event()
+
+
+(a)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()