1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-08-25 13:49:59 +03:00

Adding more tests and fixes

This commit is contained in:
Adolfo Gómez García
2022-08-29 15:21:12 +02:00
parent 70488199b9
commit db12077304
11 changed files with 236 additions and 27 deletions

View File

@ -85,19 +85,24 @@ class UniqueIdTests(UDSTestCase):
self.assertEqual(self.uidGen.get(), 0)
def test_release_older_unique_id(self):
self.uidGen.get() # 0
self.assertEqual(self.uidGen.get(), 1)
NUM = 100
for i in range(NUM):
self.assertEqual(self.uidGen.get(), i)
stamp = getSqlDatetimeAsUnix() + 1
time.sleep(2)
self.uidGen.get() # 2
for i in range(NUM):
self.assertEqual(self.uidGen.get(), i + NUM)
self.uidGen.releaseOlderThan(getSqlDatetimeAsUnix() - 1) # Clear ups older than 1 seconds ago
self.uidGen.releaseOlderThan(stamp) # Clear ups older than 0 seconds ago
self.assertEqual(self.uidGen.get(), 0)
self.assertEqual(self.uidGen.get(), 1)
self.assertEqual(self.uidGen.get(), 3)
for i in range(NUM):
self.assertEqual(self.uidGen.get(), i)
# from NUM to NUM*2-1 (both included) are still there, so we should get 200
self.assertEqual(self.uidGen.get(), NUM*2)
self.assertEqual(self.uidGen.get(), NUM*2+1)
def test_gid(self):
for x in range(100):

View File

@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2022 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 datetime
from uds import models
from uds.core.environment import Environment
from uds.core.util import config
from uds.core.util.state import State
from uds.core.workers.assigned_unused import AssignedAndUnused
from ...utils.test import UDSTransactionTestCase
from ...fixtures import services as fixtures_services
class AssignedAndUnusedTests(UDSTransactionTestCase):
userServices: typing.List[models.UserService]
def setUp(self):
config.GlobalConfig.CHECK_UNUSED_TIME.set('600')
AssignedAndUnused.setup()
# All created user services has "in_use" to False, os_state and state to USABLE
self.userServices = fixtures_services.newUserServiceForTesting(count=32)
def test_assigned_unused(self):
for us in self.userServices: # Update state date to now
us.setState(State.USABLE)
# Set now, should not be removed
count = models.UserService.objects.filter(state=State.REMOVABLE).count()
cleaner = AssignedAndUnused(Environment.getTempEnv())
# since_state = getSqlDatetime() - datetime.timedelta(seconds=cleaner.frecuency)
cleaner.run()
self.assertEqual(models.UserService.objects.filter(state=State.REMOVABLE).count(), count)
# Set half the userServices to a long-ago state, should be removed
for i, us in enumerate(self.userServices):
if i%2 == 0:
us.state_date = models.getSqlDatetime() - datetime.timedelta(seconds=602)
us.save(update_fields=['state_date'])
cleaner.run()
self.assertEqual(models.UserService.objects.filter(state=State.REMOVABLE).count(), count + len(self.userServices)//2)

View File

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# 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. 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 datetime
import typing
from uds import models
from uds.core.environment import Environment
from uds.core.util import config
from uds.core.util.state import State
from uds.core.workers.hanged_userservice_cleaner import HangedCleaner
from ...utils.test import UDSTransactionTestCase
from ...fixtures import services as fixtures_services
MAX_INIT = 300
TEST_SERVICES = 5 * 5 # Ensure multiple of 5 for testing
class HangedCleanerTests(UDSTransactionTestCase):
userServices: typing.List[models.UserService]
def setUp(self):
config.GlobalConfig.MAX_INITIALIZING_TIME.set(MAX_INIT)
config.GlobalConfig.MAX_REMOVAL_TIME.set(MAX_INIT)
HangedCleaner.setup()
# All created user services has "in_use" to False, os_state and state to USABLE
self.userServices = fixtures_services.newUserServiceForTesting(
count=TEST_SERVICES
)
# Setup a few user services as hanged
for i, us in enumerate(self.userServices):
if i % 5 == 0:
us.state = (
State.PREPARING
) # These will convert in "CANCELED" (first CANCELING but TestDeployment Cancels inmediately, so it will be CANCELED)
elif i % 5 == 1:
us.state = State.USABLE
us.os_state = State.PREPARING # THese in "REMOVABLE"
elif i % 5 == 2:
us.state = State.REMOVING # These will be set "REMOVABLE" to retry
elif i % 5 == 3:
us.state = State.CANCELING # These will be set "REMOVABLE" to retry
else:
# Just for setting defaults, that already are defaults :)
us.state = State.USABLE
us.os_state = State.USABLE
us.state_date = models.getSqlDatetime() - datetime.timedelta(
seconds=MAX_INIT + 1
)
us.save(update_fields=['state', 'os_state', 'state_date'])
def test_hanged_cleaner(self):
# At start, there is no "removable" user services
cleaner = HangedCleaner(Environment.getTempEnv())
cleaner.run()
one_fith = TEST_SERVICES // 5
self.assertEqual(
models.UserService.objects.filter(state=State.CANCELED).count(), one_fith
)
self.assertEqual(
models.UserService.objects.filter(state=State.REMOVABLE).count(), 3*one_fith
)
self.assertEqual(
models.UserService.objects.filter(state=State.USABLE).count(), one_fith
)

View File

@ -153,3 +153,24 @@ def createSingleTestingUserServiceStructure(
)
return user_service
def newUserServiceForTesting(
count: int = 1,
type_: typing.Union[
typing.Literal['managed'], typing.Literal['unmanaged']
] = 'managed',
) -> typing.List[models.UserService]:
from . import authenticators
auth = authenticators.createAuthenticator()
user_services: typing.List[models.UserService] = []
for _ in range(count):
groups = authenticators.createGroups(auth, 3)
user = authenticators.createUsers(auth, 1, groups=groups)[0]
user_services.append(
createSingleTestingUserServiceStructure(
createProvider(), user, groups, type_
)
)
return user_services

View File

@ -36,9 +36,8 @@ from django.test.client import Client
from django.http.response import HttpResponse
from django.conf import settings
from uds import models
from uds.REST.handlers import AUTH_TOKEN_HEADER
from uds.core.managers.crypto import CryptoManager
from uds.core.util.config import GlobalConfig
logger = logging.getLogger(__name__)
@ -104,14 +103,26 @@ class UDSClient(Client):
def post(self, *args, **kwargs) -> 'UDSHttpResponse':
return typing.cast('UDSHttpResponse', super().post(*args, **kwargs))
class UDSTestCase(TestCase):
client_class: typing.Type = UDSClient
client: UDSClient
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
setupClass(cls)
class UDSTransactionTestCase(TransactionTestCase):
client_class: typing.Type = UDSClient
client: UDSClient
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
setupClass(cls)
def setupClass(cls: typing.Union[typing.Type[UDSTestCase], typing.Type[UDSTransactionTestCase]]) -> None:
# Nothing right now
pass

View File

@ -31,7 +31,7 @@
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
import base64
import pickle
import pickle # nosec: Safe pickle usage
import gzip
import typing
@ -92,7 +92,7 @@ class Serializable:
to unmarshal that data variable
"""
if hasattr(self, 'data') and hasattr(getattr(self, 'data'), '__dict__'):
setattr(self, 'data', pickle.loads(data))
setattr(self, 'data', pickle.loads(data)) # nosec: Safe pickle load
return
raise NotImplementedError('You must override the unmarshal method or provide a data member')

View File

@ -86,7 +86,7 @@ class Config:
class Value:
_section: 'Config.Section'
_section: 'Config.Section' # type: ignore # mypy bug?
_type: int
_key: str
_crypt: bool
@ -211,7 +211,7 @@ class Config:
def getHelp(self) -> str:
return gettext(self._help)
def set(self, value: typing.Union[str, bool]) -> None:
def set(self, value: typing.Union[str, bool, int]) -> None:
if GlobalConfig.isInitialized() is False:
_saveLater.append((self, value))
return
@ -219,6 +219,9 @@ class Config:
if isinstance(value, bool):
value = ['0', '1'][value]
if isinstance(value, int):
value = str(value)
if self._crypt:
value = cryptoManager().encrypt(value)
@ -249,6 +252,8 @@ class Config:
self._section.name(),
self._key,
)
finally:
self._data = value
def __str__(self) -> str:
return '{}.{}'.format(self._section.name(), self._key)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 20122 Virtual Cable S.L.U.
# Copyright (c) 2022 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -64,7 +64,11 @@ class TestUserDeployment(services.UserDeployment):
ip: str = ''
mac: str = ''
data: Data = dataclasses.field(default_factory=Data)
data: Data
def initialize(self) -> None:
super().initialize()
self.data = TestUserDeployment.Data()
# : Recheck every five seconds by default (for task methods)
suggestedTime = 5

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2019 Virtual Cable S.L.
# Copyright (c) 2022 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -12,7 +12,7 @@
# * 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. nor the names of its contributors
# * 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.
#
@ -28,8 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
Created on Jun 22, 2012
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
import logging
@ -92,11 +90,13 @@ class TestProvider(services.ServiceProvider):
name: str = ''
integer: int = 0
data: Data = dataclasses.field(default_factory=Data)
data: Data
def initialize(self, values: 'module.Module.ValuesType') -> None:
self.data = TestProvider.Data()
if values:
name = random.SystemRandom().choices(string.ascii_letters, k=10)
self.data.name = ''.join(random.SystemRandom().choices(string.ascii_letters, k=10))
self.data.integer = random.randint(0, 100)
return super().initialize(values)
@staticmethod

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2019 Virtual Cable S.L.
# Copyright (c) 2022 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -12,7 +12,7 @@
# * 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. nor the names of its contributors
# * 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.
#
@ -51,9 +51,7 @@ logger = logging.getLogger(__name__)
class ServiceTestNoCache(services.Service):
"""
Basic testing service without cache and no publication OFC
"""
# : Name to show the administrator. This string will be translated BEFORE
# : sending it to administration interface, so don't forget to
# : mark it as _ (using gettext_noop)