stream: use async I/O to avoid real-time problems.

This commit is contained in:
Roman Zeyde
2015-02-02 21:46:53 +02:00
parent 5b6d1881ab
commit 1d5d564f4d
12 changed files with 207 additions and 23 deletions

70
tests/test_async.py Normal file
View File

@@ -0,0 +1,70 @@
import mock
import time
import pytest
from amodem import async
import logging
logging.basicConfig(format='%(message)s')
def test_async_reader():
def _read(n):
time.sleep(n * 0.1)
return b'\x00' * n
s = mock.Mock()
s.read = _read
r = async.AsyncReader(s, 1)
n = 5
assert r.read(n) == b'\x00' * n
r.close()
assert r.stream is None
r.close()
def test_async_write():
result = []
def _write(buf):
time.sleep(len(buf) * 0.1)
result.append(buf)
s = mock.Mock()
s.write = _write
w = async.AsyncWriter(s)
w.write('foo')
w.write(' ')
w.write('bar')
w.close()
assert w.stream is None
w.close()
assert result == ['foo', ' ', 'bar']
def test_async_reader_error():
s = mock.Mock()
s.read.side_effect = IOError()
r = async.AsyncReader(s, 1)
with pytest.raises(IOError):
r.read(3)
def test_async_writer_error():
s = mock.Mock()
s.write.side_effect = IOError()
w = async.AsyncWriter(s)
w.write('123')
w.thread.join()
with pytest.raises(IOError):
w.write('456')
assert s.write.mock_calls == [mock.call('123')]
def test_underflow():
s = mock.Mock()
w = async.AsyncWriter(s)
w.write('blah')
w.thread.join()
assert s.write.mock_calls == [mock.call('blah')]
with pytest.raises(IOError):
w.write('xyzw')

View File

@@ -9,6 +9,7 @@ from amodem import common
from amodem import dsp
from amodem import sampling
from amodem import config
from amodem import async
config = config.fastest()
import logging
@@ -26,7 +27,7 @@ class Args(object):
return None
def run(size, chan=None, df=0, success=True):
def run(size, chan=None, df=0, success=True, reader=None):
tx_data = os.urandom(size)
tx_audio = BytesIO()
send.main(config=config, src=BytesIO(tx_data), dst=tx_audio)
@@ -42,13 +43,19 @@ def run(size, chan=None, df=0, success=True):
data = common.dumps(data)
rx_audio = BytesIO(data)
rx_data = BytesIO()
d = BytesIO()
result = recv.main(config=config, src=rx_audio, dst=rx_data,
dump_audio=d)
dump = BytesIO()
if reader:
rx_audio = reader(rx_audio)
try:
result = recv.main(config=config, src=rx_audio, dst=rx_data,
dump_audio=dump)
finally:
rx_audio.close()
rx_data = rx_data.getvalue()
assert data.startswith(d.getvalue())
assert data.startswith(dump.getvalue())
assert result == success
if success:
@@ -64,6 +71,11 @@ def test_small(small_size):
run(small_size, chan=lambda x: x)
def test_async():
run(1024, chan=lambda x: x,
reader=lambda s: async.AsyncReader(s, 128))
def test_error():
skip = 32000 # remove trailing silence
run(1024, chan=lambda x: x[:-skip], success=False)