mirror of
https://github.com/dkmstr/openuds.git
synced 2025-03-11 00:58:39 +03:00
Adding testing mechaniccs
This commit is contained in:
parent
9614323a1b
commit
57be9c80b6
@ -153,13 +153,23 @@ class Environment:
|
||||
return Environment(name, id_generators)
|
||||
|
||||
@staticmethod
|
||||
def environment_for_type(type_) -> 'Environment':
|
||||
def type_environment(type_: typing.Type) -> 'Environment':
|
||||
"""
|
||||
Obtains an environment associated with a type instead of a record
|
||||
@param type_: Type
|
||||
@return Associated Environment
|
||||
"""
|
||||
return Environment('type-' + str(type_))
|
||||
|
||||
@staticmethod
|
||||
def private_environment(owner: typing.Any) -> 'Environment':
|
||||
"""
|
||||
Obtains an environment with an unique identifier
|
||||
@return: An environment with an unique identifier
|
||||
"""
|
||||
return Environment(
|
||||
'#_#' + str(id(owner)) + '#^#'
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def temporary_environment() -> 'Environment':
|
||||
@ -187,7 +197,7 @@ class Environment:
|
||||
return env
|
||||
|
||||
@staticmethod
|
||||
def ommon_environment() -> 'Environment':
|
||||
def common_environment() -> 'Environment':
|
||||
"""
|
||||
Provides global environment
|
||||
"""
|
||||
|
@ -50,7 +50,7 @@ class DelayedTask(Environmentable):
|
||||
"""
|
||||
Remember to invoke parent init in derived clases using super(myClass,self).__init__() to let this initialize its own variables
|
||||
"""
|
||||
super().__init__(environment or Environment.environment_for_type(self.__class__))
|
||||
super().__init__(environment or Environment.type_environment(self.__class__))
|
||||
|
||||
def execute(self) -> None:
|
||||
"""
|
||||
|
@ -28,8 +28,8 @@
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import base64
|
||||
import time
|
||||
import codecs
|
||||
import pickle # nosec: pickle is safe here
|
||||
import threading
|
||||
from socket import gethostname
|
||||
@ -71,6 +71,7 @@ class DelayedTaskThread(threading.Thread):
|
||||
except Exception as e:
|
||||
logger.exception("Exception in thread %s: %s", e.__class__, e)
|
||||
finally:
|
||||
# This is run on a different thread, so we ensure the connection is closed
|
||||
connections['default'].close()
|
||||
|
||||
|
||||
@ -120,9 +121,9 @@ class DelayedTaskRunner(metaclass=singleton.Singleton):
|
||||
) # @UndefinedVariable
|
||||
if task.insert_date > now + timedelta(seconds=30):
|
||||
logger.warning('Executed %s due to insert_date being in the future!', task.type)
|
||||
taskInstanceDump = codecs.decode(task.instance.encode(), 'base64')
|
||||
task_instance_dump = base64.b64decode(task.instance.encode())
|
||||
task.delete()
|
||||
taskInstance = pickle.loads(taskInstanceDump) # nosec: controlled pickle
|
||||
task_instance = pickle.loads(task_instance_dump) # nosec: controlled pickle
|
||||
except IndexError:
|
||||
return # No problem, there is no waiting delayed task
|
||||
except OperationalError:
|
||||
@ -134,11 +135,11 @@ class DelayedTaskRunner(metaclass=singleton.Singleton):
|
||||
logger.exception('Obtainint one task for execution')
|
||||
return
|
||||
|
||||
if taskInstance:
|
||||
if task_instance:
|
||||
logger.debug('Executing delayedTask:>%s<', task)
|
||||
# Re-create environment data
|
||||
taskInstance.env = Environment.environment_for_type(taskInstance.__class__)
|
||||
DelayedTaskThread(taskInstance).start()
|
||||
task_instance.env = Environment.type_environment(task_instance.__class__)
|
||||
DelayedTaskThread(task_instance).start()
|
||||
|
||||
def _insert(self, instance: DelayedTask, delay: int, tag: str) -> None:
|
||||
now = sql_datetime()
|
||||
@ -148,7 +149,7 @@ class DelayedTaskRunner(metaclass=singleton.Singleton):
|
||||
# Save "env" from delayed task, set it to None and restore it after save
|
||||
env = instance.env
|
||||
instance.env = None # type: ignore # clean env before saving pickle, save space (the env will be created again when executing)
|
||||
instance_dump = codecs.encode(pickle.dumps(instance), 'base64').decode()
|
||||
instance_dump = base64.b64encode(pickle.dumps(instance)).decode()
|
||||
instance.env = env
|
||||
|
||||
type_name = str(cls.__module__ + '.' + cls.__name__)
|
||||
|
@ -47,7 +47,7 @@ from uds.core import types, consts
|
||||
if typing.TYPE_CHECKING:
|
||||
from .user_service import UserService
|
||||
from .publication import Publication
|
||||
from uds.core import services
|
||||
from uds.core import services, environment
|
||||
from uds.core.util.unique_name_generator import UniqueNameGenerator
|
||||
from uds.core.util.unique_mac_generator import UniqueMacGenerator
|
||||
from uds.core.util.unique_gid_generator import UniqueGIDGenerator
|
||||
@ -211,7 +211,7 @@ class Service(Module):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
environment,
|
||||
environment: 'environment.Environment',
|
||||
parent: 'services.ServiceProvider',
|
||||
values: Module.ValuesType = None,
|
||||
uuid: typing.Optional[str] = None,
|
||||
|
@ -83,7 +83,7 @@ class TestEnvironment(UDSTransactionTestCase):
|
||||
self.assertEqual(env.cache.get('test'), None)
|
||||
|
||||
def test_global_environment(self) -> None:
|
||||
env = environment.Environment.ommon_environment()
|
||||
env = environment.Environment.common_environment()
|
||||
self._check_environment(env, environment.COMMON_ENV, True)
|
||||
|
||||
def test_temporary_environment(self) -> None:
|
||||
@ -99,8 +99,8 @@ class TestEnvironment(UDSTransactionTestCase):
|
||||
self._check_environment(env, 't-test_table-123', True)
|
||||
|
||||
def test_environment_for_type(self) -> None:
|
||||
env = environment.Environment.environment_for_type('test_type')
|
||||
self._check_environment(env, 'type-test_type', True)
|
||||
env = environment.Environment.type_environment(TestEnvironment)
|
||||
self._check_environment(env, 'type-' + str(TestEnvironment), True)
|
||||
|
||||
def test_exclusive_temporary_environment(self) -> None:
|
||||
unique_key: str = ''
|
||||
|
@ -96,7 +96,7 @@ class PhysicalMachinesMultiSerializationTest(UDSTestCase):
|
||||
environment: Environment
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.environment = Environment.environment_for_type('test')
|
||||
self.environment = Environment.temporary_environment()
|
||||
self.environment.storage.save_to_db('ips', pickle.dumps(STORED_IPS))
|
||||
|
||||
def check(self, version: str, instance: 'service_multi.IPMachinesService') -> None:
|
||||
|
52
server/tests/services/proxmox/test_provider.py
Normal file
52
server/tests/services/proxmox/test_provider.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2024 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import typing
|
||||
import collections.abc
|
||||
|
||||
from unittest import mock
|
||||
from ...utils.autospec import autospec, AutoSpecMethodInfo
|
||||
|
||||
from uds.services.Proxmox import provider, client
|
||||
|
||||
METHODS_INFO: typing.Final[list[AutoSpecMethodInfo]] = [
|
||||
AutoSpecMethodInfo('test', method=mock.Mock(return_value=True)),
|
||||
]
|
||||
|
||||
|
||||
class TestProxmovProvider:
|
||||
def test_provider(self) -> None:
|
||||
"""
|
||||
Test the provider
|
||||
"""
|
||||
client = autospec(provider.ProxmoxProvider, METHODS_INFO)
|
||||
assert client.test() is True
|
@ -35,9 +35,8 @@ import typing
|
||||
|
||||
# We use storage, so we need transactional tests
|
||||
from tests.utils.test import UDSTransactionTestCase
|
||||
from uds.core.util import autoserializable
|
||||
from uds.core.services import service
|
||||
from uds.core.environment import Environment
|
||||
from uds.services import Proxmox
|
||||
|
||||
|
||||
from uds.services.Proxmox.deployment import Operation as Operation, ProxmoxDeployment as Deployment
|
||||
@ -95,7 +94,7 @@ class ProxmoxDeploymentSerializationTest(UDSTransactionTestCase):
|
||||
environment = Environment.testing_environment()
|
||||
|
||||
def _create_instance(unmarshal_data: 'bytes|None' = None) -> Deployment:
|
||||
instance = Deployment(environment=environment, service=None)
|
||||
instance = Deployment(environment=environment, service=service.Service(Environment.testing_environment(), )
|
||||
if unmarshal_data:
|
||||
instance.unmarshal(unmarshal_data)
|
||||
return instance
|
||||
|
51
server/tests/utils/autospec.py
Normal file
51
server/tests/utils/autospec.py
Normal file
@ -0,0 +1,51 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2024 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import collections.abc
|
||||
import typing
|
||||
import dataclasses
|
||||
from unittest import mock
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AutoSpecMethodInfo:
|
||||
name: str
|
||||
return_value: typing.Any = None
|
||||
method: 'typing.Callable|None' = None
|
||||
|
||||
|
||||
def autospec(cls: typing.Type, metods_info: collections.abc.Iterable, **kwargs: typing.Any) -> typing.Any:
|
||||
"""
|
||||
This is a helper function that will create a mock object with the same methods as the class passed as parameter.
|
||||
This is useful for testing purposes, where you want to mock a class and still have the same methods available.
|
||||
"""
|
||||
obj = mock.create_autospec(cls, **kwargs)
|
||||
for method_info in metods_info:
|
||||
setattr(obj, method_info.name, method_info.method or mock.Mock(return_value=method_info.return_value))
|
||||
return obj
|
53
server/tests/utils/fake.py
Normal file
53
server/tests/utils/fake.py
Normal file
@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2024 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
|
||||
import random
|
||||
import uuid
|
||||
import typing
|
||||
import collections.abc
|
||||
|
||||
from uds.core import services, environment
|
||||
|
||||
|
||||
def fake_service_provider() -> services.ServiceProvider:
|
||||
uuid_ = str(uuid.uuid4())
|
||||
return services.ServiceProvider(
|
||||
environment=environment.Environment.private_environment(uuid_),
|
||||
uuid=uuid_,
|
||||
)
|
||||
|
||||
def fake_service() -> services.Service:
|
||||
uuid_ = str(uuid.uuid4())
|
||||
return services.Service(
|
||||
environment=environment.Environment.private_environment(uuid_),
|
||||
parent=fake_service_provider(),
|
||||
uuid=uuid_,
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2022 Virtual Cable S.L.
|
||||
# Copyright (c) 2022-2024 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,7 +26,7 @@
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
|
||||
import random
|
||||
|
Loading…
x
Reference in New Issue
Block a user