core-extra/daemon/tests/test_services.py

376 lines
13 KiB
Python

import itertools
from pathlib import Path
import pytest
from mock import MagicMock
from core.emulator.session import Session
from core.errors import CoreCommandError
from core.nodes.base import CoreNode
from core.services.coreservices import CoreService, ServiceDependencies, ServiceManager
_PATH: Path = Path(__file__).resolve().parent
_SERVICES_PATH = _PATH / "myservices"
SERVICE_ONE = "MyService"
SERVICE_TWO = "MyService2"
class TestServices:
def test_service_all_files(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
file_name = "myservice.sh"
node = session.add_node(CoreNode)
# when
session.services.set_service_file(node.id, SERVICE_ONE, file_name, "# test")
# then
service = session.services.get_service(node.id, SERVICE_ONE)
all_files = session.services.all_files(service)
assert service
assert all_files and len(all_files) == 1
def test_service_all_configs(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
node = session.add_node(CoreNode)
# when
session.services.set_service(node.id, SERVICE_ONE)
session.services.set_service(node.id, SERVICE_TWO)
# then
all_configs = session.services.all_configs()
assert all_configs
assert len(all_configs) == 2
def test_service_add_services(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
node = session.add_node(CoreNode)
total_service = len(node.services)
# when
session.services.add_services(node, node.model, [SERVICE_ONE, SERVICE_TWO])
# then
assert node.services
assert len(node.services) == total_service + 2
def test_service_file(self, request, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
file_path = Path(my_service.configs[0])
file_path = node.host_path(file_path)
# when
session.services.create_service_files(node, my_service)
# then
if not request.config.getoption("mock"):
assert file_path.exists()
def test_service_validate(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
# when
status = session.services.validate_service(node, my_service)
# then
assert not status
def test_service_validate_error(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_TWO)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
# when
status = session.services.validate_service(node, my_service)
# then
assert status
def test_service_startup(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
# when
status = session.services.startup_service(node, my_service, wait=True)
# then
assert not status
def test_service_startup_error(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_TWO)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
# when
status = session.services.startup_service(node, my_service, wait=True)
# then
assert status
def test_service_stop(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
# when
status = session.services.stop_service(node, my_service)
# then
assert not status
def test_service_stop_error(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_TWO)
node = session.add_node(CoreNode)
session.services.create_service_files(node, my_service)
node.cmd = MagicMock(side_effect=CoreCommandError(-1, "invalid"))
# when
status = session.services.stop_service(node, my_service)
# then
assert status
def test_service_custom_startup(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
# when
session.services.set_service(node.id, my_service.name)
custom_my_service = session.services.get_service(node.id, my_service.name)
custom_my_service.startup = ("sh custom.sh",)
# then
assert my_service.startup != custom_my_service.startup
def test_service_set_file(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node1 = session.add_node(CoreNode)
node2 = session.add_node(CoreNode)
file_name = my_service.configs[0]
file_data1 = "# custom file one"
file_data2 = "# custom file two"
session.services.set_service_file(
node1.id, my_service.name, file_name, file_data1
)
session.services.set_service_file(
node2.id, my_service.name, file_name, file_data2
)
# when
custom_service1 = session.services.get_service(node1.id, my_service.name)
session.services.create_service_files(node1, custom_service1)
custom_service2 = session.services.get_service(node2.id, my_service.name)
session.services.create_service_files(node2, custom_service2)
def test_service_import(self):
"""
Test importing a custom service.
"""
ServiceManager.add_services(_SERVICES_PATH)
assert ServiceManager.get(SERVICE_ONE)
assert ServiceManager.get(SERVICE_TWO)
def test_service_setget(self, session: Session):
# given
ServiceManager.add_services(_SERVICES_PATH)
my_service = ServiceManager.get(SERVICE_ONE)
node = session.add_node(CoreNode)
# when
no_service = session.services.get_service(node.id, SERVICE_ONE)
default_service = session.services.get_service(
node.id, SERVICE_ONE, default_service=True
)
session.services.set_service(node.id, SERVICE_ONE)
custom_service = session.services.get_service(
node.id, SERVICE_ONE, default_service=True
)
# then
assert no_service is None
assert default_service == my_service
assert custom_service and custom_service != my_service
def test_services_dependency(self):
# given
service_a = CoreService()
service_a.name = "a"
service_b = CoreService()
service_b.name = "b"
service_c = CoreService()
service_c.name = "c"
service_d = CoreService()
service_d.name = "d"
service_e = CoreService()
service_e.name = "e"
service_a.dependencies = (service_b.name,)
service_b.dependencies = ()
service_c.dependencies = (service_b.name, service_d.name)
service_d.dependencies = ()
service_e.dependencies = ()
services = [service_a, service_b, service_c, service_d, service_e]
expected1 = {service_a.name, service_b.name, service_c.name, service_d.name}
expected2 = [service_e]
# when
permutations = itertools.permutations(services)
for permutation in permutations:
permutation = list(permutation)
results = ServiceDependencies(permutation).boot_order()
# then
for result in results:
result_set = {x.name for x in result}
if len(result) == 4:
a_index = result.index(service_a)
b_index = result.index(service_b)
c_index = result.index(service_c)
d_index = result.index(service_d)
assert b_index < a_index
assert b_index < c_index
assert d_index < c_index
assert result_set == expected1
elif len(result) == 1:
assert expected2 == result
else:
raise ValueError(
f"unexpected result: {results}, perm({permutation})"
)
def test_services_dependency_missing(self):
# given
service_a = CoreService()
service_a.name = "a"
service_b = CoreService()
service_b.name = "b"
service_c = CoreService()
service_c.name = "c"
service_a.dependencies = (service_b.name,)
service_b.dependencies = (service_c.name,)
service_c.dependencies = ("d",)
services = [service_a, service_b, service_c]
# when, then
permutations = itertools.permutations(services)
for permutation in permutations:
permutation = list(permutation)
with pytest.raises(ValueError):
ServiceDependencies(permutation).boot_order()
def test_services_dependency_cycle(self):
# given
service_a = CoreService()
service_a.name = "a"
service_b = CoreService()
service_b.name = "b"
service_c = CoreService()
service_c.name = "c"
service_a.dependencies = (service_b.name,)
service_b.dependencies = (service_c.name,)
service_c.dependencies = (service_a.name,)
services = [service_a, service_b, service_c]
# when, then
permutations = itertools.permutations(services)
for permutation in permutations:
permutation = list(permutation)
with pytest.raises(ValueError):
ServiceDependencies(permutation).boot_order()
def test_services_dependency_common(self):
# given
service_a = CoreService()
service_a.name = "a"
service_b = CoreService()
service_b.name = "b"
service_c = CoreService()
service_c.name = "c"
service_d = CoreService()
service_d.name = "d"
service_a.dependencies = (service_b.name,)
service_c.dependencies = (service_d.name, service_b.name)
services = [service_a, service_b, service_c, service_d]
expected = {service_a.name, service_b.name, service_c.name, service_d.name}
# when
permutations = itertools.permutations(services)
for permutation in permutations:
permutation = list(permutation)
results = ServiceDependencies(permutation).boot_order()
# then
for result in results:
assert len(result) == 4
result_set = {x.name for x in result}
a_index = result.index(service_a)
b_index = result.index(service_b)
c_index = result.index(service_c)
d_index = result.index(service_d)
assert b_index < a_index
assert d_index < c_index
assert b_index < c_index
assert expected == result_set
def test_services_dependency_common2(self):
# given
service_a = CoreService()
service_a.name = "a"
service_b = CoreService()
service_b.name = "b"
service_c = CoreService()
service_c.name = "c"
service_d = CoreService()
service_d.name = "d"
service_a.dependencies = (service_b.name,)
service_b.dependencies = (service_c.name, service_d.name)
service_c.dependencies = (service_d.name,)
services = [service_a, service_b, service_c, service_d]
expected = {service_a.name, service_b.name, service_c.name, service_d.name}
# when
permutations = itertools.permutations(services)
for permutation in permutations:
permutation = list(permutation)
results = ServiceDependencies(permutation).boot_order()
# then
for result in results:
assert len(result) == 4
result_set = {x.name for x in result}
a_index = result.index(service_a)
b_index = result.index(service_b)
c_index = result.index(service_c)
d_index = result.index(service_d)
assert b_index < a_index
assert c_index < b_index
assert d_index < b_index
assert d_index < c_index
assert expected == result_set