blob: 3cf4560e5cdb90e90d4de0f625995e8827bd667c [file]
import pytest
import marshmallow as ma
from app.api.v2.errors import DataValidationError
from app.api.v2.managers.base_api_manager import BaseApiManager
from app.objects.interfaces.i_object import FirstClassObjectInterface
from app.utility.base_object import BaseObject
from app.utility.base_world import BaseWorld
class StubDataService:
def __init__(self):
self.ram = {}
self.conf = {}
self.Access = BaseWorld.Access
def apply_config(self, prop, config):
self.conf[prop] = config
def get_config(self, prop=None, name=None):
if prop in self.conf:
return self.conf[prop]
class TestSchema(ma.Schema):
__test__ = False
name = ma.fields.String()
value = ma.fields.String()
@ma.post_load()
def build_test_object(self, data, **kwargs):
return None if kwargs.get('partial') is True else TestObject(**data)
class TestObject(FirstClassObjectInterface, BaseObject):
__test__ = False
schema = TestSchema()
display_schema = TestSchema()
@property
def unique(self):
return self.hash('%s' % self.name)
def __init__(self, name, value=''):
super().__init__()
self.name = name
self.value = value
def store(self, ram):
ram_key = 'tests'
existing = self.retrieve(ram[ram_key], self.unique)
if not existing:
ram[ram_key].append(self)
return self.retrieve(ram[ram_key], self.unique)
existing.update('name', self.name)
existing.update('value', self.value)
return existing
def test_find_objects(agent):
stub_data_svc = StubDataService()
stub_data_svc.ram['agents'] = [
agent(paw='agent0', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent1', sleep_min=2, sleep_max=5, watchdog=0)
]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
agents = list(manager.find_objects('agents'))
assert len(agents) == len(stub_data_svc.ram['agents'])
def test_find_objects_with_search(agent):
search_property = 'sleep_min'
search_value = 2
stub_data_svc = StubDataService()
stub_data_svc.ram['agents'] = [
agent(paw='agent0', sleep_min=1, sleep_max=5, watchdog=0),
agent(paw='agent1', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent2', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent3', sleep_min=3, sleep_max=5, watchdog=0),
]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
search = {search_property: search_value}
agents = list(manager.find_objects('agents', search=search))
assert len(agents) == 2
for agent in agents:
assert getattr(agent, search_property) == search_value
def test_find_object(agent):
search_property = 'paw'
search_value = 'agent0'
test_agent = agent(paw='agent0', sleep_min=1, sleep_max=5, watchdog=0)
stub_data_svc = StubDataService()
stub_data_svc.ram['agents'] = [
agent(paw='agent1', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent2', sleep_min=2, sleep_max=5, watchdog=0),
test_agent,
]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
search = {search_property: search_value}
agent = manager.find_object('agents', search=search)
assert agent == test_agent
def test_dump(data_svc, agent):
test_agent = agent(sleep_min=2, sleep_max=5, watchdog=0)
dumped_agent = test_agent.schema.dump(test_agent)
manager = BaseApiManager(data_svc=data_svc, file_svc=None)
manager_dumped_agent = manager.dump_object_with_filters(test_agent)
for key in manager_dumped_agent:
assert manager_dumped_agent[key] == dumped_agent[key]
def test_dump_with_exclude(data_svc, agent):
exclude_key = 'paw'
test_agent = agent(sleep_min=2, sleep_max=5, watchdog=0)
dumped_agent = test_agent.schema.dump(test_agent)
manager = BaseApiManager(data_svc=data_svc, file_svc=None)
manager_dumped_agent = manager.dump_object_with_filters(test_agent, exclude=[exclude_key])
assert exclude_key in dumped_agent
assert exclude_key not in manager_dumped_agent
for key in manager_dumped_agent:
assert manager_dumped_agent[key] == dumped_agent[key]
def test_dump_with_include(data_svc, agent):
include_key = 'paw'
test_agent = agent(sleep_min=2, sleep_max=5, watchdog=0)
dumped_agent = test_agent.schema.dump(test_agent)
manager = BaseApiManager(data_svc=data_svc, file_svc=None)
manager_dumped_agent = manager.dump_object_with_filters(test_agent, include=[include_key])
assert include_key in dumped_agent
assert include_key in manager_dumped_agent
assert len(manager_dumped_agent.keys()) == 1
assert manager_dumped_agent[include_key] == dumped_agent[include_key]
def test_find_and_dump_objects_with_sort(agent):
sort_property = 'paw'
stub_data_svc = StubDataService()
stub_data_svc.ram['agents'] = [
agent(paw='agent5', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent1', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent3', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent0', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent4', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agent2', sleep_min=2, sleep_max=5, watchdog=0),
]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
dumped_agents = manager.find_and_dump_objects('agents', sort=sort_property)
assert len(dumped_agents) == len(stub_data_svc.ram['agents'])
prev_paw = None
for dumped_agent in dumped_agents:
assert not prev_paw or dumped_agent[sort_property] > prev_paw
prev_paw = dumped_agent[sort_property]
def test_find_and_dump_objects_with_sort_and_default(agent):
stub_data_svc = StubDataService()
stub_data_svc.ram['agents'] = [
agent(paw='agentF', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agentB', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agentD', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agentA', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agentE', sleep_min=2, sleep_max=5, watchdog=0),
agent(paw='agentC', sleep_min=2, sleep_max=5, watchdog=0),
]
stub_data_svc.apply_config('objects.agents.default', 'agentE')
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
dumped_agents = manager.find_and_dump_objects('agents', sort='paw')
assert len(dumped_agents) == len(stub_data_svc.ram['agents'])
assert dumped_agents[0]['paw'] == 'agentE'
prev_paw = None
for dumped_agent in dumped_agents[1:]:
assert not prev_paw or dumped_agent['paw'] > prev_paw
prev_paw = dumped_agent['paw']
def test_create_object_from_schema():
stub_data_svc = StubDataService()
stub_data_svc.ram['tests'] = []
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
data = {'name': 'test_name', 'value': 'test_value'}
access = {'access': (BaseWorld.Access.RED, BaseWorld.Access.APP)}
obj = manager.create_object_from_schema(TestSchema, data, access)
assert obj.name == 'test_name' and obj.value == 'test_value'
def test_create_object_from_schema_duplicate():
stub_data_svc = StubDataService()
stub_data_svc.ram['tests'] = []
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
data = {'name': 'test_name', 'value': 'test_value'}
access = {'access': (BaseWorld.Access.RED, BaseWorld.Access.APP)}
manager.create_object_from_schema(TestSchema, data, access)
manager.create_object_from_schema(TestSchema, data, access)
assert len(stub_data_svc.ram) == 1
def test_find_and_update_object(agent):
stub_data_svc = StubDataService()
stub_data_svc.ram['tests'] = [
TestObject(name='name0', value='value0'),
TestObject(name='name1', value='value1'),
]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
data = {'value': 'value1'}
search = {'name': 'name0'}
manager.find_and_update_object('tests', data, search)
assert len(stub_data_svc.ram['tests']) == 2
for test_obj in stub_data_svc.ram['tests']:
assert test_obj.value == 'value1'
def test_replace_object(agent):
stub_data_svc = StubDataService()
test_obj = TestObject(name='name0', value='value0')
stub_data_svc.ram['tests'] = [test_obj]
manager = BaseApiManager(data_svc=stub_data_svc, file_svc=None)
data = {'name': 'name0'}
manager.replace_object(test_obj, data)
assert len(stub_data_svc.ram['tests']) == 1
assert not stub_data_svc.ram['tests'][0].value
def test_sanitize_id():
valid = '766be199-7316-4b26-b3db-e272aaf7e0d4'
assert valid == BaseApiManager._sanitize_id(valid)
assert valid.upper() == BaseApiManager._sanitize_id(valid.upper())
assert valid == BaseApiManager._sanitize_id('../.././&%$!"#766be19:9-73[16-]4b}26-b{3d!b-e272..\\//aaf/*7e0d4')
assert 'testid123TEST' == BaseApiManager._sanitize_id('testid123TEST')
with pytest.raises(DataValidationError):
BaseApiManager._sanitize_id('../../.')
with pytest.raises(DataValidationError):
BaseApiManager._sanitize_id('')
# Non-string IDs should raise a DataValidationError
with pytest.raises(DataValidationError):
BaseApiManager._sanitize_id(12345)
def test_sanitize_id_logs_warning_when_changed(caplog):
# Capture warnings when an ID is mutated by sanitization
caplog.set_level('WARNING')
original = 'abc/def?ghi'
sanitized = BaseApiManager._sanitize_id(original)
assert sanitized == 'abcdefghi'
# Ensure a warning was emitted that includes the sanitized ID
assert any('Sanitized ID' in rec.getMessage() and sanitized in rec.getMessage() for rec in caplog.records)