Merge branch 'dev' into feature/2712-Terminal_Login_Handling

This commit is contained in:
Charlie Crane
2024-07-19 11:18:34 +01:00
82 changed files with 11493 additions and 645 deletions

View File

@@ -0,0 +1,137 @@
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
from uuid import uuid4
import pytest
from primaite import PRIMAITE_CONFIG
from primaite.game.agent.agent_log import AgentLog
from primaite.simulator import LogLevel, SIM_OUTPUT
@pytest.fixture(autouse=True)
def override_dev_mode_temporarily():
"""Temporarily turn off dev mode for this test."""
primaite_dev_mode = PRIMAITE_CONFIG["developer_mode"]["enabled"]
PRIMAITE_CONFIG["developer_mode"]["enabled"] = False
yield # run tests
PRIMAITE_CONFIG["developer_mode"]["enabled"] = primaite_dev_mode
@pytest.fixture(scope="function")
def agentlog() -> AgentLog:
return AgentLog(agent_name="test_agent")
def test_debug_agent_log_level(agentlog, capsys):
"""Test that the debug log level logs debug agent logs and above."""
SIM_OUTPUT.agent_log_level = LogLevel.DEBUG
SIM_OUTPUT.write_agent_log_to_terminal = True
test_string = str(uuid4())
agentlog.debug(msg=test_string)
agentlog.info(msg=test_string)
agentlog.warning(msg=test_string)
agentlog.error(msg=test_string)
agentlog.critical(msg=test_string)
captured = "".join(capsys.readouterr())
assert test_string in captured
assert "DEBUG" in captured
assert "INFO" in captured
assert "WARNING" in captured
assert "ERROR" in captured
assert "CRITICAL" in captured
def test_info_agent_log_level(agentlog, capsys):
"""Test that the debug log level logs debug agent logs and above."""
SIM_OUTPUT.agent_log_level = LogLevel.INFO
SIM_OUTPUT.write_agent_log_to_terminal = True
test_string = str(uuid4())
agentlog.debug(msg=test_string)
agentlog.info(msg=test_string)
agentlog.warning(msg=test_string)
agentlog.error(msg=test_string)
agentlog.critical(msg=test_string)
captured = "".join(capsys.readouterr())
assert test_string in captured
assert "DEBUG" not in captured
assert "INFO" in captured
assert "WARNING" in captured
assert "ERROR" in captured
assert "CRITICAL" in captured
def test_warning_agent_log_level(agentlog, capsys):
"""Test that the debug log level logs debug agent logs and above."""
SIM_OUTPUT.agent_log_level = LogLevel.WARNING
SIM_OUTPUT.write_agent_log_to_terminal = True
test_string = str(uuid4())
agentlog.debug(msg=test_string)
agentlog.info(msg=test_string)
agentlog.warning(msg=test_string)
agentlog.error(msg=test_string)
agentlog.critical(msg=test_string)
captured = "".join(capsys.readouterr())
assert test_string in captured
assert "DEBUG" not in captured
assert "INFO" not in captured
assert "WARNING" in captured
assert "ERROR" in captured
assert "CRITICAL" in captured
def test_error_agent_log_level(agentlog, capsys):
"""Test that the debug log level logs debug agent logs and above."""
SIM_OUTPUT.agent_log_level = LogLevel.ERROR
SIM_OUTPUT.write_agent_log_to_terminal = True
test_string = str(uuid4())
agentlog.debug(msg=test_string)
agentlog.info(msg=test_string)
agentlog.warning(msg=test_string)
agentlog.error(msg=test_string)
agentlog.critical(msg=test_string)
captured = "".join(capsys.readouterr())
assert test_string in captured
assert "DEBUG" not in captured
assert "INFO" not in captured
assert "WARNING" not in captured
assert "ERROR" in captured
assert "CRITICAL" in captured
def test_critical_agent_log_level(agentlog, capsys):
"""Test that the debug log level logs debug agent logs and above."""
SIM_OUTPUT.agent_log_level = LogLevel.CRITICAL
SIM_OUTPUT.write_agent_log_to_terminal = True
test_string = str(uuid4())
agentlog.debug(msg=test_string)
agentlog.info(msg=test_string)
agentlog.warning(msg=test_string)
agentlog.error(msg=test_string)
agentlog.critical(msg=test_string)
captured = "".join(capsys.readouterr())
assert test_string in captured
assert "DEBUG" not in captured
assert "INFO" not in captured
assert "WARNING" not in captured
assert "ERROR" not in captured
assert "CRITICAL" in captured

View File

@@ -26,7 +26,7 @@ def test_file_scan_request(populated_file_system):
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
assert file.visible_health_status == FileSystemItemHealthStatus.GOOD
fs.apply_request(request=["file", file.name, "scan"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "scan"])
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
assert file.visible_health_status == FileSystemItemHealthStatus.CORRUPT
@@ -37,12 +37,12 @@ def test_file_checkhash_request(populated_file_system):
"""Test that an agent can request a file hash check."""
fs, folder, file = populated_file_system
fs.apply_request(request=["file", file.name, "checkhash"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "checkhash"])
assert file.health_status == FileSystemItemHealthStatus.GOOD
file.sim_size = 0
fs.apply_request(request=["file", file.name, "checkhash"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "checkhash"])
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
@@ -54,7 +54,7 @@ def test_file_repair_request(populated_file_system):
file.corrupt()
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
fs.apply_request(request=["file", file.name, "repair"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "repair"])
assert file.health_status == FileSystemItemHealthStatus.GOOD
@@ -71,7 +71,7 @@ def test_file_restore_request(populated_file_system):
assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None
assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False
fs.apply_request(request=["file", file.name, "corrupt"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"])
assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT
fs.apply_request(request=["restore", "file", folder.name, file.name])
@@ -81,7 +81,7 @@ def test_file_restore_request(populated_file_system):
def test_file_corrupt_request(populated_file_system):
"""Test that an agent can request a file corruption."""
fs, folder, file = populated_file_system
fs.apply_request(request=["file", file.name, "corrupt"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"])
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
@@ -90,7 +90,7 @@ def test_deleted_file_cannot_be_interacted_with(populated_file_system):
fs, folder, file = populated_file_system
assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None
fs.apply_request(request=["file", file.name, "corrupt"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"])
assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT
assert (
fs.get_file(folder_name=folder.name, file_name=file.name).visible_health_status

View File

@@ -39,3 +39,39 @@ def test_folder_delete_request(populated_file_system):
assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is None
fs.show(full=True)
def test_folder_exists_request_validator(populated_file_system):
"""Tests that the _FolderExistsValidator works as intended."""
fs, folder, file = populated_file_system
validator = FileSystem._FolderExistsValidator(file_system=fs)
assert validator(request=["test_folder"], context={}) # test_folder exists
assert validator(request=["fake_folder"], context={}) is False # fake_folder does not exist
assert validator.fail_message == "Cannot perform request on folder because it does not exist."
def test_file_exists_request_validator(populated_file_system):
"""Tests that the _FolderExistsValidator works as intended."""
fs, folder, file = populated_file_system
validator = FileSystem._FileExistsValidator(file_system=fs)
assert validator(request=["test_folder", "test_file.txt"], context={}) # test_file.txt exists
assert validator(request=["test_folder", "fake_file.txt"], context={}) is False # fake_file.txt does not exist
assert validator.fail_message == "Cannot perform request on a file that does not exist."
def test_folder_not_deleted_request_validator(populated_file_system):
"""Tests that the _FolderExistsValidator works as intended."""
fs, folder, file = populated_file_system
validator = FileSystem._FolderNotDeletedValidator(file_system=fs)
assert validator(request=["test_folder"], context={}) # test_folder is not deleted
fs.delete_folder(folder_name="test_folder")
assert validator(request=["test_folder"], context={}) is False # test_folder is deleted
assert validator.fail_message == "Cannot perform request on folder because it is deleted."

View File

@@ -166,15 +166,40 @@ def test_deleted_folder_and_its_files_cannot_be_interacted_with(populated_file_s
fs, folder, file = populated_file_system
assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None
fs.apply_request(request=["file", file.name, "corrupt"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"])
assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT
fs.apply_request(request=["delete", "folder", folder.name])
assert fs.get_file(folder_name=folder.name, file_name=file.name) is None
fs.apply_request(request=["file", file.name, "repair"])
fs.apply_request(request=["folder", folder.name, "file", file.name, "repair"])
deleted_folder = fs.deleted_folders.get(folder.uuid)
deleted_file = deleted_folder.deleted_files.get(file.uuid)
assert deleted_file.health_status is not FileSystemItemHealthStatus.GOOD
def test_file_exists_request_validator(populated_file_system):
"""Tests that the _FolderExistsValidator works as intended."""
fs, folder, file = populated_file_system
validator = Folder._FileExistsValidator(folder=folder)
assert validator(request=["test_file.txt"], context={}) # test_file.txt exists
assert validator(request=["fake_file.txt"], context={}) is False # fake_file.txt does not exist
assert validator.fail_message == "Cannot perform request on a file that does not exist."
def test_file_not_deleted_request_validator(populated_file_system):
"""Tests that the _FolderExistsValidator works as intended."""
fs, folder, file = populated_file_system
validator = Folder._FileNotDeletedValidator(folder=folder)
assert validator(request=["test_file.txt"], context={}) # test_file.txt is not deleted
fs.delete_file(folder_name="test_folder", file_name="test_file.txt")
assert validator(request=["fake_file.txt"], context={}) is False # test_file.txt is deleted
assert validator.fail_message == "Cannot perform request on a file that is deleted."

View File

@@ -0,0 +1,34 @@
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
import pytest
from primaite.simulator.network.hardware.base import NetworkInterface, Node
from primaite.simulator.network.hardware.nodes.host.computer import Computer
@pytest.fixture
def node() -> Node:
return Computer(hostname="test", ip_address="192.168.1.2", subnet_mask="255.255.255.0")
def test_nic_enabled_validator(node):
"""Test the NetworkInterface enabled validator."""
network_interface = node.network_interface[1]
validator = NetworkInterface._EnabledValidator(network_interface=network_interface)
assert validator(request=[], context={}) is False # not enabled
network_interface.enabled = True
assert validator(request=[], context={}) # enabled
def test_nic_disabled_validator(node):
"""Test the NetworkInterface enabled validator."""
network_interface = node.network_interface[1]
validator = NetworkInterface._DisabledValidator(network_interface=network_interface)
assert validator(request=[], context={}) # not enabled
network_interface.enabled = True
assert validator(request=[], context={}) is False # enabled

View File

@@ -155,3 +155,39 @@ def test_reset_node(node):
assert node.operating_state == NodeOperatingState.BOOTING
assert node.operating_state == NodeOperatingState.ON
def test_node_is_on_validator(node):
"""Test that the node is on validator."""
node.power_on()
for i in range(node.start_up_duration + 1):
node.apply_timestep(i)
validator = Node._NodeIsOnValidator(node=node)
assert validator(request=[], context={})
node.power_off()
for i in range(node.shut_down_duration + 1):
node.apply_timestep(i)
assert validator(request=[], context={}) is False
def test_node_is_off_validator(node):
"""Test that the node is on validator."""
node.power_on()
for i in range(node.start_up_duration + 1):
node.apply_timestep(i)
validator = Node._NodeIsOffValidator(node=node)
assert validator(request=[], context={}) is False
node.power_off()
for i in range(node.shut_down_duration + 1):
node.apply_timestep(i)
assert validator(request=[], context={})

View File

@@ -1 +1,15 @@
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
from primaite.simulator.system.applications.application import Application, ApplicationOperatingState
def test_application_state_validator(application):
"""Test the application state validator."""
validator = Application._StateValidator(application=application, state=ApplicationOperatingState.CLOSED)
assert validator(request=[], context={}) # application is closed
application.run()
assert validator(request=[], context={}) is False # application is running - expecting closed
validator = Application._StateValidator(application=application, state=ApplicationOperatingState.RUNNING)
assert validator(request=[], context={}) # application is running
application.close()
assert validator(request=[], context={}) is False # application is closed - expecting running

View File

@@ -1,5 +1,5 @@
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
from primaite.simulator.system.services.service import ServiceOperatingState
from primaite.simulator.system.services.service import Service, ServiceOperatingState
from primaite.simulator.system.software import SoftwareHealthState
@@ -92,3 +92,21 @@ def test_service_fix(service):
assert service.health_state_actual == SoftwareHealthState.FIXING
service.apply_timestep(2)
assert service.health_state_actual == SoftwareHealthState.GOOD
def test_service_state_validator(service):
"""Test the service state validator."""
validator = Service._StateValidator(service=service, state=ServiceOperatingState.STOPPED)
assert validator(request=[], context={}) # service is stopped
service.start()
assert validator(request=[], context={}) is False # service is running - expecting stopped
validator = Service._StateValidator(service=service, state=ServiceOperatingState.RUNNING)
assert validator(request=[], context={}) # service is running
service.pause()
assert validator(request=[], context={}) is False # service is paused - expecting running
validator = Service._StateValidator(service=service, state=ServiceOperatingState.PAUSED)
assert validator(request=[], context={}) # service is paused
service.resume()
assert validator(request=[], context={}) is False # service is running - expecting paused