2023-07-21 14:54:09 +01:00
|
|
|
# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
2023-06-30 09:08:13 +01:00
|
|
|
import datetime
|
|
|
|
|
import shutil
|
2023-06-07 22:57:37 +01:00
|
|
|
import tempfile
|
|
|
|
|
from datetime import datetime
|
2023-05-25 14:05:53 +01:00
|
|
|
from pathlib import Path
|
2023-10-27 17:50:41 +01:00
|
|
|
from typing import Any, Dict, Union
|
2023-06-30 09:08:13 +01:00
|
|
|
from unittest.mock import patch
|
2023-05-25 14:05:53 +01:00
|
|
|
|
2023-10-27 17:50:41 +01:00
|
|
|
import nodeenv
|
2023-06-30 09:08:13 +01:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
from primaite import getLogger
|
2023-10-25 13:56:02 +01:00
|
|
|
|
|
|
|
|
# from primaite.environment.primaite_env import Primaite
|
|
|
|
|
# from primaite.primaite_session import PrimaiteSession
|
2023-09-08 16:50:49 +01:00
|
|
|
from primaite.simulator.network.container import Network
|
|
|
|
|
from primaite.simulator.network.networks import arcd_uc2_network
|
2023-10-20 12:58:58 +01:00
|
|
|
from primaite.simulator.network.transmission.transport_layer import Port
|
2023-10-27 17:50:41 +01:00
|
|
|
from primaite.simulator.system.applications.application import Application
|
2023-10-10 15:14:47 +01:00
|
|
|
from primaite.simulator.system.core.sys_log import SysLog
|
2023-10-20 12:58:58 +01:00
|
|
|
from primaite.simulator.system.services.service import Service
|
2023-06-30 09:08:13 +01:00
|
|
|
from tests.mock_and_patch.get_session_path_mock import get_temp_session_path
|
2023-05-25 14:05:53 +01:00
|
|
|
|
|
|
|
|
ACTION_SPACE_NODE_VALUES = 1
|
|
|
|
|
ACTION_SPACE_NODE_ACTION_VALUES = 1
|
|
|
|
|
|
2023-06-30 09:08:13 +01:00
|
|
|
_LOGGER = getLogger(__name__)
|
|
|
|
|
|
2023-09-06 22:01:51 +01:00
|
|
|
# PrimAITE v3 stuff
|
|
|
|
|
from primaite.simulator.file_system.file_system import FileSystem
|
|
|
|
|
from primaite.simulator.network.hardware.base import Node
|
2023-06-30 09:08:13 +01:00
|
|
|
|
2023-09-06 22:01:51 +01:00
|
|
|
|
2023-10-20 12:58:58 +01:00
|
|
|
class TestService(Service):
|
|
|
|
|
"""Test Service class"""
|
|
|
|
|
|
|
|
|
|
def receive(self, payload: Any, session_id: str, **kwargs) -> bool:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2023-10-27 17:50:41 +01:00
|
|
|
class TestApplication(Application):
|
|
|
|
|
"""Test Application class"""
|
|
|
|
|
|
|
|
|
|
def describe_state(self) -> Dict:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2023-09-08 16:50:49 +01:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
|
def uc2_network() -> Network:
|
|
|
|
|
return arcd_uc2_network()
|
|
|
|
|
|
|
|
|
|
|
2023-10-20 12:58:58 +01:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
|
def service(file_system) -> TestService:
|
|
|
|
|
return TestService(
|
|
|
|
|
name="TestService", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="test_service")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-10-27 17:50:41 +01:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
|
def application(file_system) -> TestApplication:
|
|
|
|
|
return TestApplication(
|
|
|
|
|
name="TestApplication", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="test_application")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-09-06 22:01:51 +01:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
|
def file_system() -> FileSystem:
|
|
|
|
|
return Node(hostname="fs_node").file_system
|
|
|
|
|
|
|
|
|
|
|
2023-09-06 22:26:23 +01:00
|
|
|
# PrimAITE v2 stuff
|
2023-10-25 17:08:01 +01:00
|
|
|
@pytest.mark.skip("Deprecated") # TODO: implement a similar test for primaite v3
|
|
|
|
|
class TempPrimaiteSession: # PrimaiteSession):
|
2023-06-30 09:08:13 +01:00
|
|
|
"""
|
|
|
|
|
A temporary PrimaiteSession class.
|
|
|
|
|
|
|
|
|
|
Uses context manager for deletion of files upon exit.
|
|
|
|
|
"""
|
|
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
# def __init__(
|
|
|
|
|
# self,
|
|
|
|
|
# training_config_path: Union[str, Path],
|
|
|
|
|
# lay_down_config_path: Union[str, Path],
|
|
|
|
|
# ):
|
|
|
|
|
# super().__init__(training_config_path, lay_down_config_path)
|
|
|
|
|
# self.setup()
|
2023-06-30 09:08:13 +01:00
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
# @property
|
|
|
|
|
# def env(self) -> Primaite:
|
|
|
|
|
# """Direct access to the env for ease of testing."""
|
|
|
|
|
# return self._agent_session._env # noqa
|
2023-06-30 09:08:13 +01:00
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
# def __enter__(self):
|
|
|
|
|
# return self
|
2023-06-30 09:08:13 +01:00
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
# def __exit__(self, type, value, tb):
|
|
|
|
|
# shutil.rmtree(self.session_path)
|
|
|
|
|
# _LOGGER.debug(f"Deleted temp session directory: {self.session_path}")
|
2023-06-30 09:08:13 +01:00
|
|
|
|
|
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
@pytest.mark.skip("Deprecated") # TODO: implement a similar test for primaite v3
|
2023-06-30 09:08:13 +01:00
|
|
|
@pytest.fixture
|
|
|
|
|
def temp_primaite_session(request):
|
|
|
|
|
"""
|
|
|
|
|
Provides a temporary PrimaiteSession instance.
|
|
|
|
|
|
|
|
|
|
It's temporary as it uses a temporary directory as the session path.
|
|
|
|
|
|
|
|
|
|
To use this fixture you need to:
|
|
|
|
|
|
|
|
|
|
- parametrize your test function with:
|
2023-05-25 14:05:53 +01:00
|
|
|
|
2023-06-30 09:08:13 +01:00
|
|
|
- "temp_primaite_session"
|
|
|
|
|
- [[path to training config, path to lay down config]]
|
|
|
|
|
- Include the temp_primaite_session fixture as a param in your test
|
|
|
|
|
function.
|
|
|
|
|
- use the temp_primaite_session as a context manager assigning is the
|
|
|
|
|
name 'session'.
|
|
|
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
|
|
|
|
|
from primaite.config.lay_down_config import dos_very_basic_config_path
|
|
|
|
|
from primaite.config.training_config import main_training_config_path
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
"temp_primaite_session",
|
|
|
|
|
[
|
|
|
|
|
[main_training_config_path(), dos_very_basic_config_path()]
|
|
|
|
|
],
|
|
|
|
|
indirect=True
|
|
|
|
|
)
|
|
|
|
|
def test_primaite_session(temp_primaite_session):
|
|
|
|
|
with temp_primaite_session as session:
|
|
|
|
|
# Learning outputs are saved in session.learning_path
|
|
|
|
|
session.learn()
|
|
|
|
|
|
|
|
|
|
# Evaluation outputs are saved in session.evaluation_path
|
|
|
|
|
session.evaluate()
|
|
|
|
|
|
|
|
|
|
# To ensure that all files are written, you must call .close()
|
|
|
|
|
session.close()
|
|
|
|
|
|
|
|
|
|
# If you need to inspect any session outputs, it must be done
|
|
|
|
|
# inside the context manager
|
|
|
|
|
|
|
|
|
|
# Now that we've exited the context manager, the
|
|
|
|
|
# session.session_path directory and its contents are deleted
|
|
|
|
|
"""
|
|
|
|
|
training_config_path = request.param[0]
|
|
|
|
|
lay_down_config_path = request.param[1]
|
2023-08-03 12:42:16 +01:00
|
|
|
with patch("primaite.agents.agent_abc.get_session_path", get_temp_session_path) as mck:
|
2023-06-30 09:08:13 +01:00
|
|
|
mck.session_timestamp = datetime.now()
|
|
|
|
|
|
|
|
|
|
return TempPrimaiteSession(training_config_path, lay_down_config_path)
|
|
|
|
|
|
|
|
|
|
|
2023-10-25 17:08:01 +01:00
|
|
|
@pytest.mark.skip("Deprecated") # TODO: implement a similar test for primaite v3
|
2023-06-30 09:08:13 +01:00
|
|
|
@pytest.fixture
|
|
|
|
|
def temp_session_path() -> Path:
|
2023-06-07 22:57:37 +01:00
|
|
|
"""
|
|
|
|
|
Get a temp directory session path the test session will output to.
|
|
|
|
|
|
|
|
|
|
:return: The session directory path.
|
|
|
|
|
"""
|
2023-06-30 09:08:13 +01:00
|
|
|
session_timestamp = datetime.now()
|
2023-06-07 22:57:37 +01:00
|
|
|
date_dir = session_timestamp.strftime("%Y-%m-%d")
|
2023-06-19 20:27:08 +01:00
|
|
|
session_path = session_timestamp.strftime("%Y-%m-%d_%H-%M-%S")
|
2023-08-01 16:18:49 +01:00
|
|
|
session_path = Path(tempfile.gettempdir()) / "_primaite" / date_dir / session_path
|
2023-06-07 22:57:37 +01:00
|
|
|
session_path.mkdir(exist_ok=True, parents=True)
|
|
|
|
|
|
|
|
|
|
return session_path
|