mirror of
https://github.com/valitydev/salt.git
synced 2024-11-06 16:45:27 +00:00
0d32cb9228
Libvirt events algorigthm converting the libvirt enums into string has a flaw that unit tests couldn't see. Libvirt python binding defines the following constants: VIR_DOMAIN_EVENT_CRASHED_PANICKED = 0 VIR_DOMAIN_EVENT_DEFINED = 0 VIR_DOMAIN_EVENT_CRASHED = 8 However VIR_DOMAIN_EVENT_CRASHED_PANICKED is the only value in this enum and thus wasn't not considered a sub-enum element. So the value 0 in enum 'VIR_DOMAIN_EVENT_' was wrongly mapped to "crashed panicked" instead of "defined". In order to safely rule this case out, check if we have an item that just ends with the subprefix without the '_'.
164 lines
6.4 KiB
Python
164 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
unit tests for the libvirt_events engine
|
|
'''
|
|
# Import Python libs
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
# Import Salt Testing Libs
|
|
from tests.support.mixins import LoaderModuleMockMixin
|
|
from tests.support.unit import skipIf, TestCase
|
|
from tests.support.mock import (
|
|
NO_MOCK,
|
|
NO_MOCK_REASON,
|
|
MagicMock,
|
|
patch)
|
|
|
|
# Import Salt Libs
|
|
import salt.engines.libvirt_events as libvirt_events
|
|
|
|
|
|
# pylint: disable=protected-access,attribute-defined-outside-init,invalid-name,unused-argument,no-self-use
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
class EngineLibvirtEventTestCase(TestCase, LoaderModuleMockMixin):
|
|
'''
|
|
Test cases for salt.engine.libvirt_events
|
|
'''
|
|
|
|
def setup_loader_modules(self):
|
|
patcher = patch('salt.engines.libvirt_events.libvirt')
|
|
self.mock_libvirt = patcher.start()
|
|
self.mock_libvirt.getVersion.return_value = 2000000
|
|
self.mock_libvirt.virEventRunDefaultImpl.return_value = -1 # Don't loop for ever
|
|
self.mock_libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE = 0
|
|
self.mock_libvirt.VIR_DOMAIN_EVENT_ID_REBOOT = 1
|
|
self.addCleanup(patcher.stop)
|
|
self.addCleanup(delattr, self, 'mock_libvirt')
|
|
return {libvirt_events: {}}
|
|
|
|
@patch('salt.engines.libvirt_events.libvirt',
|
|
VIR_PREFIX_NONE=0,
|
|
VIR_PREFIX_ONE=1,
|
|
VIR_PREFIX_TWO=2,
|
|
VIR_PREFIX_SUB_FOO=0,
|
|
VIR_PREFIX_SUB_BAR=1,
|
|
VIR_PREFIX_SUB_FOOBAR=2)
|
|
def test_get_libvirt_enum_string_subprefix(self, libvirt_mock):
|
|
'''
|
|
Make sure the libvirt enum value to string works reliably with
|
|
elements with a sub prefix, eg VIR_PREFIX_SUB_* in this case.
|
|
'''
|
|
# Test case with a sub prefix
|
|
|
|
assert libvirt_events._get_libvirt_enum_string('VIR_PREFIX_', 2) == 'two'
|
|
|
|
@patch('salt.engines.libvirt_events.libvirt',
|
|
VIR_PREFIX_FOO=0,
|
|
VIR_PREFIX_BAR_FOO=1)
|
|
def test_get_libvirt_enum_string_underscores(self, libvirt_mock):
|
|
'''
|
|
Make sure the libvirt enum value to string works reliably and items
|
|
with an underscore aren't confused with sub prefixes.
|
|
'''
|
|
assert libvirt_events._get_libvirt_enum_string('VIR_PREFIX_', 1) == 'bar foo'
|
|
|
|
@patch('salt.engines.libvirt_events.libvirt',
|
|
VIR_DOMAIN_EVENT_CRASHED_PANICKED=0,
|
|
VIR_DOMAIN_EVENT_DEFINED=0,
|
|
VIR_DOMAIN_EVENT_UNDEFINED=1,
|
|
VIR_DOMAIN_EVENT_CRASHED=2,
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED=0,
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED=1)
|
|
def test_get_domain_event_detail(self, mock_libvirt):
|
|
'''
|
|
Test get_domain_event_detail function
|
|
'''
|
|
assert libvirt_events._get_domain_event_detail(1, 2) == ('undefined', 'unknown')
|
|
assert libvirt_events._get_domain_event_detail(0, 1) == ('defined', 'updated')
|
|
assert libvirt_events._get_domain_event_detail(4, 2) == ('unknown', 'unknown')
|
|
|
|
@patch('salt.engines.libvirt_events.libvirt', VIR_NETWORK_EVENT_ID_LIFECYCLE=1000)
|
|
def test_event_register(self, mock_libvirt):
|
|
'''
|
|
Test that the libvirt_events engine actually registers events catch them and cleans
|
|
before leaving the place.
|
|
'''
|
|
mock_cnx = MagicMock()
|
|
mock_libvirt.openReadOnly.return_value = mock_cnx
|
|
|
|
# Don't loop for ever
|
|
mock_libvirt.virEventRunDefaultImpl.return_value = -1
|
|
|
|
mock_cnx.networkEventRegisterAny.return_value = 10000
|
|
|
|
libvirt_events.start('test:///', 'test/prefix')
|
|
|
|
# Check that the connection has been opened
|
|
mock_libvirt.openReadOnly.assert_called_once_with('test:///')
|
|
|
|
# Check that the connection has been closed
|
|
mock_cnx.close.assert_called_once()
|
|
|
|
# Check events registration and deregistration
|
|
mock_cnx.domainEventRegisterAny.assert_any_call(
|
|
None, mock_libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
libvirt_events._domain_event_lifecycle_cb,
|
|
{'prefix': 'test/prefix', 'object': 'domain', 'event': 'lifecycle'})
|
|
mock_cnx.networkEventRegisterAny.assert_any_call(
|
|
None, mock_libvirt.VIR_NETWORK_EVENT_ID_LIFECYCLE,
|
|
libvirt_events._network_event_lifecycle_cb,
|
|
{'prefix': 'test/prefix', 'object': 'network', 'event': 'lifecycle'})
|
|
|
|
# Check that the deregister events are called with the result of register
|
|
mock_cnx.networkEventDeregisterAny.assert_called_with(
|
|
mock_cnx.networkEventRegisterAny.return_value)
|
|
|
|
# Check that the default 'all' filter actually worked
|
|
counts = {obj: len(callback_def) for obj, callback_def in libvirt_events.CALLBACK_DEFS.items()}
|
|
for obj, count in counts.items():
|
|
register = libvirt_events.REGISTER_FUNCTIONS[obj]
|
|
assert getattr(mock_cnx, register).call_count == count
|
|
|
|
def test_event_skipped(self):
|
|
'''
|
|
Test that events are skipped if their ID isn't defined in the libvirt
|
|
module (older libvirt)
|
|
'''
|
|
self.mock_libvirt.mock_add_spec([
|
|
'openReadOnly',
|
|
'virEventRegisterDefaultImpl',
|
|
'virEventRunDefaultImpl',
|
|
'VIR_DOMAIN_EVENT_ID_LIFECYCLE'], spec_set=True)
|
|
|
|
libvirt_events.start('test:///', 'test/prefix')
|
|
|
|
# Check events registration and deregistration
|
|
mock_cnx = self.mock_libvirt.openReadOnly.return_value
|
|
|
|
mock_cnx.domainEventRegisterAny.assert_any_call(
|
|
None, self.mock_libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
libvirt_events._domain_event_lifecycle_cb,
|
|
{'prefix': 'test/prefix', 'object': 'domain', 'event': 'lifecycle'})
|
|
|
|
# Network events should have been skipped
|
|
mock_cnx.networkEventRegisterAny.assert_not_called()
|
|
|
|
def test_event_filtered(self):
|
|
'''
|
|
Test that events are skipped if their ID isn't defined in the libvirt
|
|
module (older libvirt)
|
|
'''
|
|
libvirt_events.start('test', 'test/prefix', 'domain/lifecycle')
|
|
|
|
# Check events registration and deregistration
|
|
mock_cnx = self.mock_libvirt.openReadOnly.return_value
|
|
|
|
mock_cnx.domainEventRegisterAny.assert_any_call(
|
|
None, 0, libvirt_events._domain_event_lifecycle_cb,
|
|
{'prefix': 'test/prefix', 'object': 'domain', 'event': 'lifecycle'})
|
|
|
|
# Network events should have been filtered out
|
|
mock_cnx.networkEventRegisterAny.assert_not_called()
|