mirror of
https://gitlab.com/libvirt/libvirt-python.git
synced 2025-08-02 04:21:59 +03:00
tests: add libvirtaio test coverage
Signed-off-by: Chris Gunn <chrisgun@microsoft.com>
This commit is contained in:
committed by
Daniel P. Berrangé
parent
c2fae558c3
commit
b9f79758c9
3
pytest.ini
Normal file
3
pytest.ini
Normal file
@ -0,0 +1,3 @@
|
||||
[pytest]
|
||||
markers =
|
||||
separate_process: mark test as requiring its own process
|
13
setup.py
13
setup.py
@ -310,8 +310,19 @@ class my_test(Command):
|
||||
os.environ["PYTHONPATH"] = self.build_platlib
|
||||
|
||||
pytest = self.find_pytest_path()
|
||||
subprocess.check_call([pytest])
|
||||
|
||||
# Run the normal tests.
|
||||
subprocess.check_call([pytest, "-m", "not separate_process"])
|
||||
|
||||
# Run the tests that require their own process.
|
||||
testlist = subprocess.run(
|
||||
[pytest, "--collect-only", "--quiet", "-m", "separate_process"],
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
testlist = testlist.stdout.decode("utf-8").splitlines()
|
||||
testlist = filter(
|
||||
lambda test: test and "tests collected" not in test, testlist)
|
||||
for test in testlist:
|
||||
subprocess.check_call([pytest, test])
|
||||
|
||||
class my_clean(Command):
|
||||
def run(self):
|
||||
|
114
tests/test_aio.py
Normal file
114
tests/test_aio.py
Normal file
@ -0,0 +1,114 @@
|
||||
import asyncio
|
||||
import libvirt
|
||||
import libvirtaio
|
||||
import sys
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
|
||||
class TestLibvirtAio(unittest.TestCase):
|
||||
async def _run(self, register):
|
||||
def lifecycleCallback(conn, dom, event, detail, domainChangedEvent):
|
||||
if (event == libvirt.VIR_DOMAIN_EVENT_STOPPED or
|
||||
event == libvirt.VIR_DOMAIN_EVENT_STARTED):
|
||||
domainChangedEvent.set()
|
||||
|
||||
if register:
|
||||
libvirtEvents = libvirtaio.virEventRegisterAsyncIOImpl()
|
||||
else:
|
||||
libvirtEvents = libvirtaio.getCurrentImpl()
|
||||
|
||||
conn = libvirt.open("test:///default")
|
||||
dom = conn.lookupByName("test")
|
||||
|
||||
eventRegistered = False
|
||||
domainStopped = False
|
||||
try:
|
||||
# Ensure the VM is running.
|
||||
self.assertEqual([libvirt.VIR_DOMAIN_RUNNING, libvirt.VIR_DOMAIN_RUNNING_UNKNOWN], dom.state())
|
||||
self.assertTrue(libvirtEvents.is_idle())
|
||||
|
||||
# Register VM start/stopped event handler.
|
||||
domainChangedEvent = asyncio.Event()
|
||||
conn.domainEventRegisterAny(dom, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, lifecycleCallback, domainChangedEvent)
|
||||
eventRegistered = True
|
||||
|
||||
self.assertFalse(libvirtEvents.is_idle())
|
||||
|
||||
# Stop the VM.
|
||||
dom.destroy()
|
||||
domainStopped = True
|
||||
|
||||
# Ensure domain stopped event is received.
|
||||
await asyncio.wait_for(domainChangedEvent.wait(), 2)
|
||||
self.assertEqual([libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_SHUTOFF_DESTROYED], dom.state())
|
||||
|
||||
# Start the VM.
|
||||
domainChangedEvent.clear()
|
||||
domainStopped = False
|
||||
dom.create()
|
||||
|
||||
# Ensure domain started event is received.
|
||||
await asyncio.wait_for(domainChangedEvent.wait(), 2)
|
||||
self.assertEqual([libvirt.VIR_DOMAIN_RUNNING, libvirt.VIR_DOMAIN_RUNNING_BOOTED], dom.state())
|
||||
self.assertFalse(libvirtEvents.is_idle())
|
||||
|
||||
# Deregister the VM start/stopped event handler.
|
||||
eventRegistered = False
|
||||
conn.domainEventDeregisterAny(libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE)
|
||||
|
||||
# Wait for event queue to clear.
|
||||
await libvirtEvents.drain()
|
||||
|
||||
# Make sure event queue is cleared.
|
||||
self.assertTrue(libvirtEvents.is_idle())
|
||||
|
||||
finally:
|
||||
if eventRegistered:
|
||||
conn.domainEventDeregisterAny(libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE)
|
||||
|
||||
if domainStopped:
|
||||
dom.create()
|
||||
|
||||
@pytest.mark.separate_process
|
||||
def testEventsWithManualLoopSetup(self):
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
loop.run_until_complete(self._run(register=True))
|
||||
|
||||
loop.close()
|
||||
asyncio.set_event_loop(None)
|
||||
|
||||
@pytest.mark.separate_process
|
||||
@unittest.skipIf(sys.version_info < (3,7), "test requires Python 3.7+")
|
||||
def testEventsWithAsyncioRun(self):
|
||||
asyncio.run(self._run(register=True))
|
||||
|
||||
@pytest.mark.separate_process
|
||||
@unittest.skipIf(sys.version_info >= (3,10), "test not compatible with Python 3.10+")
|
||||
def testEventsPreInit(self):
|
||||
# Initialize libvirt events before setting the event loop. This is not recommended.
|
||||
# But is supported in older version of Python for the sake of back-compat.
|
||||
loop = asyncio.new_event_loop()
|
||||
libvirtaio.virEventRegisterAsyncIOImpl(loop)
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
loop.run_until_complete(self._run(register=False))
|
||||
|
||||
loop.close()
|
||||
asyncio.set_event_loop(None)
|
||||
|
||||
@pytest.mark.separate_process
|
||||
def testEventsImplicitLoopInit(self):
|
||||
# Allow virEventRegisterAsyncIOImpl() to init the event loop by calling
|
||||
# asyncio.get_event_loop(). This is not recommended and probably only works by
|
||||
# accident. But is supported for now for the sake of back-compat. For Python
|
||||
# 3.10+, asyncio will report deprecation warnings.
|
||||
libvirtaio.virEventRegisterAsyncIOImpl()
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
loop.run_until_complete(self._run(register=False))
|
||||
|
||||
loop.close()
|
||||
asyncio.set_event_loop(None)
|
Reference in New Issue
Block a user