Francesco Romani has uploaded a new change for review. Change subject: tests: add more tests for custom error responses ......................................................................
tests: add more tests for custom error responses An upcoming patchset wants to introduce and leverage the response module. This patch prepares the soil by adding unit tests. We start from the error paths, since they are (hopefully?) less often tested. Moreover, to test error path is often clumsy due to the need to trigger faults or inject them in the code, so this is a useful safety net to have. Change-Id: Icf3d03f125f9c53339d9ad7fef8c31482bab0bfb Signed-off-by: Francesco Romani <from...@redhat.com> --- M tests/vmTests.py M tests/vmfakelib.py 2 files changed, 133 insertions(+), 13 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/65/38665/1 diff --git a/tests/vmTests.py b/tests/vmTests.py index 26c39ef..4adea76 100644 --- a/tests/vmTests.py +++ b/tests/vmTests.py @@ -51,6 +51,7 @@ from vmTestsData import CONF_TO_DOMXML_PPC64 from vmTestsData import CONF_TO_DOMXML_NO_VDSM import vmfakelib as fake +from vmStorageTests import drive_config from testValidation import slowtest @@ -873,6 +874,10 @@ GRAPHIC_DEVICES = [{'type': 'graphics', 'device': 'spice', 'port': '-1'}, {'type': 'graphics', 'device': 'vnc', 'port': '-1'}] + TICKET_PARAMS = { + 'userName': 'admin', + 'userId': 'fdfc627c-d875-11e0-90f0-83df133b58cc'} + @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection()) @permutations([[define.NORMAL], [define.ERROR]]) def testTimeOffsetNotPresentByDefault(self, exitCode): @@ -951,25 +956,27 @@ self._verifyDeviceUpdate( device, self.GRAPHIC_DEVICES, domXml, devXml) - def _verifyDeviceUpdate(self, device, allDevices, domXml, devXml): - TICKET_PARAMS = { - 'userName': 'admin', - 'userId': 'fdfc627c-d875-11e0-90f0-83df133b58cc'} + def _getGraphicsDeviceParams(self, graphicsType): + return { + 'deviceType': hwclass.GRAPHICS, + 'graphicsType': graphicsType, + 'password': '***', + 'ttl': 0, + 'existingConnAction': 'disconnect', + 'params': self.TICKET_PARAMS} + def _verifyDeviceUpdate(self, device, allDevices, domXml, devXml): def _check_ticket_params(domXML, conf, params): - self.assertEqual(params, TICKET_PARAMS) + self.assertEqual(params, self.TICKET_PARAMS) with MonkeyPatchScope([(hooks, 'before_vm_set_ticket', _check_ticket_params)]): with fake.VM(devices=allDevices) as testvm: testvm._dom = fake.Domain(domXml) - testvm.updateDevice({ - 'deviceType': 'graphics', - 'graphicsType': device['device'], - 'password': '***', - 'ttl': 0, - 'existingConnAction': 'disconnect', - 'params': TICKET_PARAMS}) + + testvm.updateDevice( + self._getGraphicsDeviceParams(device['device'])) + self.assertEquals(testvm._dom.devXml, devXml) def testDomainNotRunningWithoutDomain(self): @@ -1018,6 +1025,45 @@ 'hdc': libvirt.VIR_DOMAIN_DISK_ERROR_UNSPEC}) testvm._dom = dom self.assertEqual(testvm._readPauseCode(), 'EOTHER') + + @permutations([[libvirt.VIR_ERR_OPERATION_DENIED, 'setNumberOfCpusErr'], + [libvirt.VIR_ERR_NO_DOMAIN, 'noVM']]) + def testSetNumberOfVcpusFailed(self, virtError, vdsmError): + # caveat emptor: in this test we DON't + # overwrite the message, thus will be the default one; but for + # errors != 'noVM', it can change. + with MonkeyPatchScope([(hooks, 'before_set_num_of_cpus', + lambda: None)]): + with fake.VM() as testvm: + testvm._dom = fake.Domain(virtError=virtError) + + res = testvm.setNumberOfCpus(4) # random value + + self.assertEqual(res, define.errCode[vdsmError]) + + def testUpdateDeviceGraphicsFailed(self): + def _check_ticket_params(domXML, conf, params): + pass + + with MonkeyPatchScope([(hooks, 'before_vm_set_ticket', + _check_ticket_params)]): + with fake.VM(devices=self.GRAPHIC_DEVICES) as testvm: + # caveat: we intentionally recycle the very same + # error message to simplify assert() down under + expected_status = define.errCode['ticketErr'] + message = expected_status['status']['message'] + device = 'spice' + domXml = ''' + <devices> + <graphics type="%s" port="5900" /> + </devices>''' % device + + testvm._dom = fake.Domain(domXml, timeoutError=message) + + res = testvm.updateDevice( + self._getGraphicsDeviceParams(device)) + + self.assertEqual(res, expected_status) VM_EXITS = tuple(product((define.NORMAL, define.ERROR), @@ -1298,6 +1344,7 @@ self.assertEqual(int(testvm.conf['smp']), cpus) +@expandPermutations class ChangeBlockDevTests(TestCaseBase): def test_change_cd_failure(self): @@ -1315,3 +1362,65 @@ expected_status = define.errCode['changeDisk']['status'] self.assertEqual(res['status'], expected_status) + + @permutations([[libvirt.VIR_ERR_OPERATION_DENIED, 'hotplugDisk'], + [libvirt.VIR_ERR_NO_DOMAIN, 'noVM']]) + def test_hotplug_disk_failure(self, virtError, vdsmError): + # caveat emptor: in this test we DON't + # overwrite the message, thus will be the default one; but for + # errors != 'noVM', it can change. + PATH = '/this/path/does/not/exists' + + def _fake_hook(driveXml, conf, params): + return driveXml + + cif = fake.ClientIF() + with MonkeyPatchScope([(cif, 'prepareVolumePath', + lambda _: PATH), + (cif, 'teardownVolumePath', + lambda _: None), + (hooks, 'before_disk_hotplug', + _fake_hook), + (utils, 'isBlockDevice', + lambda path: True)]): + with fake.VM(devices=[drive_config()], + cif=cif) as fakevm: + # no specific meaning, actually any error != None is good + fakevm._dom = fake.Domain( + virtError=libvirt.VIR_ERR_ACCESS_DENIED) + + res = fakevm.hotplugDisk({ + 'drive': drive_config( + path=PATH, + serial='65-a561-23e5b495b9bc')}) + + expected_status = define.errCode['hotplugDisk']['status'] + self.assertEqual(res['status'], expected_status) + + def test_hotunplug_inexistent_disk(self): + PATH = '/this/path/does/not/exists' + + def _fake_hook(driveXml, conf, params): + return driveXml + + cif = fake.ClientIF() + with MonkeyPatchScope([(cif, 'prepareVolumePath', + lambda _: PATH), + (cif, 'teardownVolumePath', + lambda _: None), + (hooks, 'before_disk_hotunplug', + _fake_hook), + (utils, 'isBlockDevice', + lambda path: True)]): + with fake.VM(cif=cif) as fakevm: + # no specific meaning, actually any error != None is good + fakevm._dom = fake.Domain( + virtError=libvirt.VIR_ERR_ACCESS_DENIED) + + res = fakevm.hotunplugDisk({}) + + expected_status = define.errCode['hotunplugDisk']['status'] + self.assertEqual(res['status']['code'], + expected_status['code']) + self.assertEqual(res['status']['message'], + "Disk not found") diff --git a/tests/vmfakelib.py b/tests/vmfakelib.py index 6919351..99c1b42 100644 --- a/tests/vmfakelib.py +++ b/tests/vmfakelib.py @@ -61,7 +61,8 @@ virtError=libvirt.VIR_ERR_OK, domState=libvirt.VIR_DOMAIN_RUNNING, domReason=0, - vmId=''): + vmId='', + timeoutError=None): self._xml = xml self.devXml = '' self._virtError = virtError @@ -72,8 +73,12 @@ self._vmId = vmId self.calls = {} self._diskErrors = {} + self._timeoutError = timeoutError def _failIfRequested(self): + if self._timeoutError: + raise vm.TimeoutError(str(self._timeoutError)) + if self._virtError != libvirt.VIR_ERR_OK: err = libvirt.libvirtError(defmsg='') err.err = [self._virtError] @@ -99,6 +104,9 @@ def vcpusFlags(self, flags): return -1 + + def setVcpusFlags(self, numberOfCpus, flags): + self._failIfRequested() def metadata(self, type, uri, flags): self._failIfRequested() @@ -130,6 +138,9 @@ def diskErrors(self): return self._diskErrors + def attachDevice(self, devXml): + self._failIfRequested() + class GuestAgent(object): def __init__(self): -- To view, visit https://gerrit.ovirt.org/38665 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Icf3d03f125f9c53339d9ad7fef8c31482bab0bfb Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Francesco Romani <from...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches