mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-01-11 05:17:59 +03:00
virtinst: support: add full code coverage testing
This commit is contained in:
parent
54a28485df
commit
ef972cf2ea
@ -61,3 +61,30 @@ class TestURI(unittest.TestCase):
|
|||||||
conn = tests.utils.URIs.openconn(uri)
|
conn = tests.utils.URIs.openconn(uri)
|
||||||
self.assertEqual(conn.conn_version(), 1)
|
self.assertEqual(conn.conn_version(), 1)
|
||||||
self.assertEqual(conn.local_libvirt_version(), 2)
|
self.assertEqual(conn.local_libvirt_version(), 2)
|
||||||
|
|
||||||
|
conn = tests.utils.URIs.open_testdefault_cached()
|
||||||
|
# Add some support tests with it
|
||||||
|
with self.assertRaises(ValueError) as cm:
|
||||||
|
conn.support.domain_xml_inactive("foo")
|
||||||
|
self.assertTrue("must be of type <class 'libvirt.virDomain'>" in
|
||||||
|
str(cm.exception))
|
||||||
|
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
from virtinst import support
|
||||||
|
def _run(**kwargs):
|
||||||
|
check = support._SupportCheck(**kwargs)
|
||||||
|
return check(conn)
|
||||||
|
|
||||||
|
self.assertFalse(_run(function="virNope.Foo"))
|
||||||
|
self.assertFalse(_run(function="virDomain.IDontExist"))
|
||||||
|
self.assertTrue(_run(function="virDomain.isActive"))
|
||||||
|
self.assertFalse(_run(function="virConnect.getVersion",
|
||||||
|
flag="SOME_FLAG_DOESNT_EXIST"))
|
||||||
|
self.assertFalse(_run(version="1000.0.0"))
|
||||||
|
self.assertFalse(_run(hv_version={"test": "1000.0.0"}))
|
||||||
|
self.assertFalse(_run(hv_libvirt_version={"test": "1000.0.0"}))
|
||||||
|
self.assertFalse(_run(hv_libvirt_version={"qemu": "1.2.3"}))
|
||||||
|
self.assertTrue(_run(hv_libvirt_version={"qemu": "1.2.3", "all": 0}))
|
||||||
|
|
||||||
|
dom = conn.lookupByName("test")
|
||||||
|
self.assertTrue(conn.support.domain_xml_inactive(dom))
|
||||||
|
@ -9,77 +9,23 @@
|
|||||||
import libvirt
|
import libvirt
|
||||||
|
|
||||||
|
|
||||||
# Check that command is present in the python bindings, and return the
|
|
||||||
# the requested function
|
|
||||||
def _get_command(funcname, objname=None, obj=None):
|
|
||||||
if not obj:
|
|
||||||
obj = libvirt
|
|
||||||
|
|
||||||
if objname:
|
|
||||||
if not hasattr(libvirt, objname):
|
|
||||||
return None
|
|
||||||
obj = getattr(libvirt, objname)
|
|
||||||
|
|
||||||
if not hasattr(obj, funcname):
|
|
||||||
return None
|
|
||||||
|
|
||||||
return getattr(obj, funcname)
|
|
||||||
|
|
||||||
|
|
||||||
# Make sure libvirt object 'objname' has function 'funcname'
|
|
||||||
def _has_command(funcname, objname=None, obj=None):
|
|
||||||
return bool(_get_command(funcname, objname, obj))
|
|
||||||
|
|
||||||
|
|
||||||
# Make sure libvirt object has flag 'flag_name'
|
|
||||||
def _get_flag(flag_name):
|
|
||||||
return _get_command(flag_name)
|
|
||||||
|
|
||||||
|
|
||||||
# Try to call the passed function, and look for signs that libvirt or driver
|
|
||||||
# doesn't support it
|
|
||||||
def _try_command(func, run_args, check_all_error=False):
|
|
||||||
try:
|
|
||||||
func(*run_args)
|
|
||||||
except libvirt.libvirtError as e:
|
|
||||||
if SupportCache.is_error_nosupport(e):
|
|
||||||
return False
|
|
||||||
|
|
||||||
if check_all_error:
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
# Other python exceptions likely mean the bindings are horked
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
# Return the hypervisor version
|
|
||||||
def _split_function_name(function):
|
|
||||||
if not function:
|
|
||||||
return (None, None)
|
|
||||||
|
|
||||||
output = function.split(".")
|
|
||||||
if len(output) == 1:
|
|
||||||
return (None, output[0])
|
|
||||||
else:
|
|
||||||
return (output[0], output[1])
|
|
||||||
|
|
||||||
|
|
||||||
def _check_function(function, flag, run_args, data):
|
def _check_function(function, flag, run_args, data):
|
||||||
# Make sure function is present in either libvirt module or
|
"""
|
||||||
# object_name class
|
Make sure function and option flag is present in the libvirt module.
|
||||||
object_name, function_name = _split_function_name(function)
|
If run_args specified, try actually running the function against
|
||||||
if not function_name:
|
the passed 'data' object
|
||||||
return None
|
"""
|
||||||
|
object_name, function_name = function.split(".")
|
||||||
flag_tuple = ()
|
classobj = getattr(libvirt, object_name, None)
|
||||||
|
if not classobj:
|
||||||
if not _has_command(function_name, objname=object_name):
|
return False
|
||||||
|
if not getattr(classobj, function_name, None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
flag_tuple = None
|
||||||
if flag:
|
if flag:
|
||||||
found_flag = _get_flag(flag)
|
found_flag = getattr(libvirt, flag, None)
|
||||||
if not bool(found_flag):
|
if found_flag is None:
|
||||||
return False
|
return False
|
||||||
flag_tuple = (found_flag,)
|
flag_tuple = (found_flag,)
|
||||||
|
|
||||||
@ -88,18 +34,26 @@ def _check_function(function, flag, run_args, data):
|
|||||||
|
|
||||||
# If function requires an object, make sure the passed obj
|
# If function requires an object, make sure the passed obj
|
||||||
# is of the correct type
|
# is of the correct type
|
||||||
if object_name:
|
if not isinstance(data, classobj):
|
||||||
classobj = _get_command(object_name)
|
raise ValueError(
|
||||||
if not isinstance(data, classobj):
|
"Passed obj %s with args must be of type %s, was %s" %
|
||||||
raise ValueError(
|
(data, str(classobj), type(data)))
|
||||||
"Passed obj %s with args must be of type %s, was %s" %
|
|
||||||
(data, str(classobj), type(data)))
|
|
||||||
|
|
||||||
cmd = _get_command(function_name, obj=data)
|
use_args = run_args
|
||||||
|
if flag_tuple:
|
||||||
|
use_args += flag_tuple
|
||||||
|
|
||||||
# Function with args specified is all the proof we need
|
try:
|
||||||
return _try_command(cmd, run_args + flag_tuple,
|
getattr(data, function_name)(*run_args)
|
||||||
check_all_error=bool(flag_tuple))
|
except libvirt.libvirtError as e:
|
||||||
|
if SupportCache.is_error_nosupport(e):
|
||||||
|
return False
|
||||||
|
if bool(flag_tuple): # pragma: no cover
|
||||||
|
return False
|
||||||
|
except Exception as e: # pragma: no cover
|
||||||
|
# Other python exceptions likely mean the bindings are horked
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _version_str_to_int(verstr):
|
def _version_str_to_int(verstr):
|
||||||
@ -122,9 +76,8 @@ class _SupportCheck(object):
|
|||||||
@version: Minimum libvirt version required for this feature. Not used
|
@version: Minimum libvirt version required for this feature. Not used
|
||||||
if 'args' provided.
|
if 'args' provided.
|
||||||
|
|
||||||
@function: Function name to check exists. If object not specified,
|
@function: Function name to check exists. Expected to be of the
|
||||||
function is checked against libvirt module. If run_args is specified,
|
format $obj.$func. Like virDomain.isActive
|
||||||
this function will actually be called, so beware.
|
|
||||||
|
|
||||||
@run_args: Argument tuple to actually test 'function' with, and check
|
@run_args: Argument tuple to actually test 'function' with, and check
|
||||||
for an 'unsupported' error from libvirt.
|
for an 'unsupported' error from libvirt.
|
||||||
@ -153,6 +106,9 @@ class _SupportCheck(object):
|
|||||||
self.hv_version = hv_version or {}
|
self.hv_version = hv_version or {}
|
||||||
self.hv_libvirt_version = hv_libvirt_version or {}
|
self.hv_libvirt_version = hv_libvirt_version or {}
|
||||||
|
|
||||||
|
if self.function:
|
||||||
|
assert len(function.split(".")) == 2
|
||||||
|
|
||||||
versions = ([self.version] + list(self.hv_libvirt_version.values()))
|
versions = ([self.version] + list(self.hv_libvirt_version.values()))
|
||||||
for vstr in versions:
|
for vstr in versions:
|
||||||
v = _version_str_to_int(vstr)
|
v = _version_str_to_int(vstr)
|
||||||
@ -178,9 +134,11 @@ class _SupportCheck(object):
|
|||||||
if "VirtinstConnection" in repr(data):
|
if "VirtinstConnection" in repr(data):
|
||||||
data = data.get_conn_for_api_arg()
|
data = data.get_conn_for_api_arg()
|
||||||
|
|
||||||
ret = _check_function(self.function, self.flag, self.run_args, data)
|
if self.function:
|
||||||
if ret is not None:
|
ret = _check_function(
|
||||||
return ret
|
self.function, self.flag, self.run_args, data)
|
||||||
|
if ret is not None:
|
||||||
|
return ret
|
||||||
|
|
||||||
# Do this after the function check, since there's an ordering issue
|
# Do this after the function check, since there's an ordering issue
|
||||||
# with VirtinstConnection
|
# with VirtinstConnection
|
||||||
@ -243,7 +201,7 @@ class SupportCache:
|
|||||||
with code VIR_ERR_NO_DOMAIN
|
with code VIR_ERR_NO_DOMAIN
|
||||||
"""
|
"""
|
||||||
if not isinstance(err, libvirt.libvirtError):
|
if not isinstance(err, libvirt.libvirtError):
|
||||||
return False
|
return False # pragma: no cover
|
||||||
return err.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN
|
return err.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -256,13 +214,13 @@ class SupportCache:
|
|||||||
:returns: True if command isn't supported, False if we can't determine
|
:returns: True if command isn't supported, False if we can't determine
|
||||||
"""
|
"""
|
||||||
if not isinstance(err, libvirt.libvirtError):
|
if not isinstance(err, libvirt.libvirtError):
|
||||||
return False
|
return False # pragma: no cover
|
||||||
|
|
||||||
if (err.get_error_code() == libvirt.VIR_ERR_RPC or
|
if (err.get_error_code() == libvirt.VIR_ERR_RPC or
|
||||||
err.get_error_code() == libvirt.VIR_ERR_NO_SUPPORT):
|
err.get_error_code() == libvirt.VIR_ERR_NO_SUPPORT):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, virtconn):
|
def __init__(self, virtconn):
|
||||||
|
Loading…
Reference in New Issue
Block a user