tests: Switch to pytest, remove devnull hack
This commit is contained in:
parent
0cda09c628
commit
7459d3df04
1 changed files with 18 additions and 54 deletions
|
|
@ -16,58 +16,28 @@ import time
|
||||||
import io
|
import io
|
||||||
import platform
|
import platform
|
||||||
import ctypes
|
import ctypes
|
||||||
|
from concurrent.futures import Future
|
||||||
|
|
||||||
import mpv
|
import mpv
|
||||||
|
|
||||||
from xvfbwrapper import Xvfb
|
from xvfbwrapper import Xvfb
|
||||||
|
|
||||||
|
|
||||||
# stdout magic to suppress useless libmpv warning messages in unittest output
|
|
||||||
# See https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/
|
|
||||||
@contextmanager
|
|
||||||
def devnull_libmpv():
|
|
||||||
""" Redirect libmpv stdout into /dev/null while still allowing python to print to stdout as usual """
|
|
||||||
if platform.system() != 'Linux':
|
|
||||||
# This is only a linux-specific convenience function.
|
|
||||||
yield
|
|
||||||
return
|
|
||||||
|
|
||||||
libc = ctypes.CDLL("libc.so.6")
|
|
||||||
|
|
||||||
stderr_fd, stdout_fd = sys.stderr.fileno(), sys.stdout.fileno()
|
|
||||||
sys.stderr.flush()
|
|
||||||
sys.stdout.flush()
|
|
||||||
libc.fflush(None)
|
|
||||||
|
|
||||||
# Preserve a copy so python can continue printing
|
|
||||||
stderr_copy, stdout_copy = os.dup(stderr_fd), os.dup(stdout_fd)
|
|
||||||
sys.stderr = io.TextIOWrapper(open(stderr_copy, 'wb', closefd=False), write_through=True)
|
|
||||||
sys.stdout = io.TextIOWrapper(open(stdout_copy, 'wb', closefd=False))
|
|
||||||
with open(os.devnull, 'w') as devnull:
|
|
||||||
os.dup2(devnull.fileno(), stderr_fd) # closes old stderr
|
|
||||||
os.dup2(devnull.fileno(), stdout_fd) # closes old stdout
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
sys.stderr.flush()
|
|
||||||
sys.stdout.flush()
|
|
||||||
libc.fflush(None)
|
|
||||||
os.dup2(stderr_copy, stderr_fd)
|
|
||||||
os.dup2(stdout_copy, stdout_fd)
|
|
||||||
os.close(stderr_copy)
|
|
||||||
os.close(stdout_copy)
|
|
||||||
sys.stderr = io.TextIOWrapper(open(stderr_fd, 'wb', closefd=False), write_through=True)
|
|
||||||
sys.stdout = io.TextIOWrapper(open(stdout_fd, 'wb', closefd=False))
|
|
||||||
|
|
||||||
TESTVID = os.path.join(os.path.dirname(__file__), 'test.webm')
|
TESTVID = os.path.join(os.path.dirname(__file__), 'test.webm')
|
||||||
TESTSRT = os.path.join(os.path.dirname(__file__), 'sub_test.srt')
|
TESTSRT = os.path.join(os.path.dirname(__file__), 'sub_test.srt')
|
||||||
MPV_ERRORS = [ l(ec) for ec, l in mpv.ErrorCode.EXCEPTION_DICT.items() if l ]
|
MPV_ERRORS = [ l(ec) for ec, l in mpv.ErrorCode.EXCEPTION_DICT.items() if l ]
|
||||||
|
|
||||||
|
def timed_print():
|
||||||
|
start_time = time.time()
|
||||||
|
def do_print(level, prefix, text):
|
||||||
|
td = time.time() - start_time
|
||||||
|
print('{:.3f} [{}] {}: {}'.format(td, level, prefix, text), flush=True)
|
||||||
|
|
||||||
class MpvTestCase(unittest.TestCase):
|
class MpvTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
self.m = mpv.MPV(vo='x11')
|
self.m = mpv.MPV(vo='x11', loglevel='debug', log_handler=timed_print())
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.m.terminate()
|
self.m.terminate()
|
||||||
|
|
@ -85,7 +55,6 @@ class TestProperties(MpvTestCase):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_read(self):
|
def test_read(self):
|
||||||
self.m.loop = 'inf'
|
self.m.loop = 'inf'
|
||||||
self.m.play(TESTVID)
|
self.m.play(TESTVID)
|
||||||
|
|
@ -99,7 +68,6 @@ class TestProperties(MpvTestCase):
|
||||||
mpv.ErrorCode.PROPERTY_NOT_FOUND]):
|
mpv.ErrorCode.PROPERTY_NOT_FOUND]):
|
||||||
getattr(self.m, name)
|
getattr(self.m, name)
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_write(self):
|
def test_write(self):
|
||||||
self.m.loop = 'inf'
|
self.m.loop = 'inf'
|
||||||
self.m.play(TESTVID)
|
self.m.play(TESTVID)
|
||||||
|
|
@ -222,7 +190,6 @@ class TestProperties(MpvTestCase):
|
||||||
# See comment in test_property_decoding_invalid_utf8
|
# See comment in test_property_decoding_invalid_utf8
|
||||||
self.m.osd.alang
|
self.m.osd.alang
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_option_read(self):
|
def test_option_read(self):
|
||||||
self.m.loop = 'inf'
|
self.m.loop = 'inf'
|
||||||
self.m.play(TESTVID)
|
self.m.play(TESTVID)
|
||||||
|
|
@ -239,7 +206,6 @@ class TestProperties(MpvTestCase):
|
||||||
|
|
||||||
|
|
||||||
class ObservePropertyTest(MpvTestCase):
|
class ObservePropertyTest(MpvTestCase):
|
||||||
@devnull_libmpv()
|
|
||||||
def test_observe_property(self):
|
def test_observe_property(self):
|
||||||
handler = mock.Mock()
|
handler = mock.Mock()
|
||||||
|
|
||||||
|
|
@ -256,7 +222,6 @@ class ObservePropertyTest(MpvTestCase):
|
||||||
m.terminate() # needed for synchronization of event thread
|
m.terminate() # needed for synchronization of event thread
|
||||||
handler.assert_has_calls([mock.call('vid', 'auto')])
|
handler.assert_has_calls([mock.call('vid', 'auto')])
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_property_observer_decorator(self):
|
def test_property_observer_decorator(self):
|
||||||
handler = mock.Mock()
|
handler = mock.Mock()
|
||||||
|
|
||||||
|
|
@ -454,7 +419,6 @@ class KeyBindingTest(MpvTestCase):
|
||||||
handler2.assert_has_calls([ mock.call() ])
|
handler2.assert_has_calls([ mock.call() ])
|
||||||
|
|
||||||
class TestStreams(unittest.TestCase):
|
class TestStreams(unittest.TestCase):
|
||||||
@devnull_libmpv()
|
|
||||||
def test_python_stream(self):
|
def test_python_stream(self):
|
||||||
handler = mock.Mock()
|
handler = mock.Mock()
|
||||||
|
|
||||||
|
|
@ -589,27 +553,28 @@ class TestLifecycle(unittest.TestCase):
|
||||||
m.terminate()
|
m.terminate()
|
||||||
handler.assert_not_called()
|
handler.assert_not_called()
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_wait_for_property_negative(self):
|
def test_wait_for_property_negative(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
m = mpv.MPV()
|
m = mpv.MPV()
|
||||||
m.play(TESTVID)
|
m.play(TESTVID)
|
||||||
|
result = Future()
|
||||||
def run():
|
def run():
|
||||||
nonlocal self
|
nonlocal self
|
||||||
|
result.set_running_or_notify_cancel()
|
||||||
try:
|
try:
|
||||||
m.wait_for_property('mute')
|
m.wait_for_property('mute')
|
||||||
self.fail()
|
result.set_result(False)
|
||||||
except mpv.ShutdownError:
|
except mpv.ShutdownError:
|
||||||
pass
|
result.set_result(True)
|
||||||
t = threading.Thread(target=run, daemon=True)
|
t = threading.Thread(target=run, daemon=True)
|
||||||
t.start()
|
t.start()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
m.terminate()
|
m.terminate()
|
||||||
t.join()
|
t.join()
|
||||||
self.disp.stop()
|
self.disp.stop()
|
||||||
|
assert result.result()
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_wait_for_property_positive(self):
|
def test_wait_for_property_positive(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
|
|
@ -629,28 +594,29 @@ class TestLifecycle(unittest.TestCase):
|
||||||
handler.assert_called()
|
handler.assert_called()
|
||||||
self.disp.stop()
|
self.disp.stop()
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_wait_for_event(self):
|
def test_wait_for_event(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
handler = mock.Mock()
|
handler = mock.Mock()
|
||||||
m = mpv.MPV()
|
m = mpv.MPV()
|
||||||
m.play(TESTVID)
|
m.play(TESTVID)
|
||||||
|
result = Future()
|
||||||
def run():
|
def run():
|
||||||
nonlocal self
|
nonlocal self
|
||||||
|
result.set_running_or_notify_cancel()
|
||||||
try:
|
try:
|
||||||
m.wait_for_event('seek')
|
m.wait_for_event('seek')
|
||||||
self.fail()
|
result.set_result(False)
|
||||||
except mpv.ShutdownError:
|
except mpv.ShutdownError:
|
||||||
pass
|
result.set_result(True)
|
||||||
t = threading.Thread(target=run, daemon=True)
|
t = threading.Thread(target=run, daemon=True)
|
||||||
t.start()
|
t.start()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
m.terminate()
|
m.terminate()
|
||||||
t.join()
|
t.join()
|
||||||
self.disp.stop()
|
self.disp.stop()
|
||||||
|
assert result.result()
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_wait_for_property_shutdown(self):
|
def test_wait_for_property_shutdown(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
|
|
@ -664,11 +630,9 @@ class TestLifecycle(unittest.TestCase):
|
||||||
m.terminate()
|
m.terminate()
|
||||||
self.disp.stop()
|
self.disp.stop()
|
||||||
|
|
||||||
@devnull_libmpv()
|
|
||||||
def test_wait_for_event_shutdown(self):
|
def test_wait_for_event_shutdown(self):
|
||||||
self.disp = Xvfb()
|
self.disp = Xvfb()
|
||||||
self.disp.start()
|
self.disp.start()
|
||||||
handler = mock.Mock()
|
|
||||||
m = mpv.MPV()
|
m = mpv.MPV()
|
||||||
m.play(TESTVID)
|
m.play(TESTVID)
|
||||||
with self.assertRaises(mpv.ShutdownError):
|
with self.assertRaises(mpv.ShutdownError):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue