Skip to content

Commit 8e687fa

Browse files
committed
No more credentials in DEBUG terminal, and fixing sonarqube
1 parent 14ef514 commit 8e687fa

File tree

2 files changed

+79
-165
lines changed

2 files changed

+79
-165
lines changed

agents/matlab/matlab_agent/src/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def run_agent(config_file):
214214
config_path=config_file)
215215

216216
try:
217-
logger.debug("Starting MATLAB agent with config: %s", config)
217+
logger.debug("Starting MATLAB agent with config: %s", config_file)
218218
agent.start()
219219
except KeyboardInterrupt:
220220
logger.info("Shutting down agent due to keyboard interrupt")
Lines changed: 78 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
"""Test suite for the ConfigManager class.
2+
3+
This refactored version removes duplicated configuration stubs by introducing a
4+
single reusable ``base_config`` fixture. Where individual tests need to tweak
5+
values, they operate on a ``deepcopy`` so that the canonical fixture remains
6+
pristine for all subsequent tests.
17
"""
2-
Test suite for the ConfigManager class.
3-
"""
8+
from __future__ import annotations
9+
10+
from copy import deepcopy
411
from pathlib import Path
512
from unittest import mock
613

@@ -10,42 +17,47 @@
1017
from src.utils.config_manager import ConfigManager
1118

1219

13-
@pytest.fixture
14-
def mock_config_data(dummy_credentials):
15-
"""Fixture providing standard test configuration data."""
16-
rabbit_creds = dummy_credentials.get("rabbitmq", {})
20+
@pytest.fixture(scope="module")
21+
def base_config(dummy_credentials: dict) -> dict:
22+
"""Return a fully‑populated configuration template shared by all tests."""
23+
24+
rabbit_creds: dict = dummy_credentials.get("rabbitmq", {})
1725
return {
1826
"agent": {"agent_id": "matlab"},
1927
"rabbitmq": {
2028
"host": "localhost",
2129
"port": 5672,
2230
"username": rabbit_creds.get("username", "guest"),
2331
"password": rabbit_creds.get("password", "guest"),
24-
"heartbeat": 600
32+
"heartbeat": 600,
2533
},
2634
"exchanges": {
2735
"input": "ex.bridge.output",
28-
"output": "ex.sim.result"
36+
"output": "ex.sim.result",
2937
},
3038
"queue": {
3139
"durable": True,
32-
"prefetch_count": 1
40+
"prefetch_count": 1,
3341
},
3442
"logging": {
3543
"level": "INFO",
36-
"file": "logs/matlab_agent.log"
44+
"file": "logs/matlab_agent.log",
3745
},
3846
"tcp": {
3947
"host": "localhost",
40-
"port": 5678
48+
"port": 5678,
4149
},
4250
"response_templates": {
4351
"success": {
4452
"status": "success",
4553
"simulation": {"type": "batch"},
4654
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ",
4755
"include_metadata": True,
48-
"metadata_fields": ["execution_time", "memory_usage", "matlab_version"]
56+
"metadata_fields": [
57+
"execution_time",
58+
"memory_usage",
59+
"matlab_version",
60+
],
4961
},
5062
"error": {
5163
"status": "error",
@@ -55,195 +67,97 @@ def mock_config_data(dummy_credentials):
5567
"matlab_start_failure": 500,
5668
"execution_error": 500,
5769
"timeout": 504,
58-
"missing_file": 404
70+
"missing_file": 404,
5971
},
60-
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
72+
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ",
6173
},
6274
"progress": {
6375
"status": "in_progress",
6476
"include_percentage": True,
6577
"update_interval": 5,
66-
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
67-
}
68-
}
78+
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ",
79+
},
80+
},
6981
}
7082

7183

7284
@pytest.fixture
73-
def mock_config_path():
74-
"""Fixture providing a standard mock config path."""
75-
return "/fake/path/config.yaml"
85+
def config_path() -> Path:
86+
"""Fake configuration path used throughout the tests."""
7687

88+
return Path("/fake/path/config.yaml")
7789

78-
@pytest.fixture
79-
def mock_load_config(mock_config_data):
80-
"""
81-
Fixture that patches the load_config function to return test configuration data.
8290

83-
Args:
84-
mock_config_data: The test configuration data fixture
91+
@pytest.fixture
92+
def patched_load(base_config: dict):
93+
"""Patch the ``load_config`` helper used by :class:`ConfigManager`."""
8594

86-
Returns:
87-
The mocked load_config function
88-
"""
89-
with mock.patch("src.utils.config_manager.load_config") as mocked_load:
90-
mocked_load.return_value = mock_config_data
91-
yield mocked_load
95+
with mock.patch(
96+
"src.utils.config_manager.load_config", return_value=deepcopy(base_config)
97+
) as mocked:
98+
yield mocked
9299

93100

94101
@pytest.fixture
95-
def mock_path_exists():
96-
"""Fixture that patches Path.exists to always return True."""
102+
def patched_exists():
103+
"""Pretend that any ``Path.exists`` call returns *True*."""
104+
97105
with mock.patch.object(Path, "exists", return_value=True):
98106
yield
99107

100108

101109
@pytest.fixture
102-
def config_manager(mock_config_path, mock_load_config, mock_path_exists):
103-
"""
104-
Fixture that creates a pre-configured ConfigManager instance.
105-
106-
Args:
107-
mock_config_path: The mock config path fixture
108-
mock_load_config: The mocked load_config function fixture
109-
mock_path_exists: The mocked Path.exists fixture
110-
111-
Returns:
112-
A ConfigManager instance initialized with the test configuration
113-
"""
114-
return ConfigManager(mock_config_path)
115-
116-
117-
def test_config_manager_initialization(dummy_credentials):
118-
"""Test that ConfigManager initializes correctly with the provided configuration."""
119-
rabbit_creds = dummy_credentials.get("rabbitmq", {})
120-
config_path = "/fake/path/config.yaml"
121-
test_config_data = {
122-
"agent": {"agent_id": "matlab"},
123-
"rabbitmq": {
124-
"host": "localhost",
125-
"port": 5672,
126-
"username": rabbit_creds.get("username", "guest"),
127-
"password": rabbit_creds.get("password", "guest"),
128-
"heartbeat": 600
129-
},
130-
"exchanges": {
131-
"input": "ex.bridge.output",
132-
"output": "ex.sim.result"
133-
},
134-
"queue": {
135-
"durable": True,
136-
"prefetch_count": 1
137-
},
138-
"logging": {
139-
"level": "INFO",
140-
"file": "logs/matlab_agent.log"
141-
},
142-
"tcp": {
143-
"host": "localhost",
144-
"port": 5678
145-
},
146-
"response_templates": {
147-
"success": {
148-
"status": "success",
149-
"simulation": {"type": "batch"},
150-
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ",
151-
"include_metadata": True,
152-
"metadata_fields": ["execution_time", "memory_usage", "matlab_version"]
153-
},
154-
"error": {
155-
"status": "error",
156-
"include_stacktrace": False,
157-
"error_codes": {
158-
"invalid_config": 400,
159-
"matlab_start_failure": 500,
160-
"execution_error": 500,
161-
"timeout": 504,
162-
"missing_file": 404
163-
},
164-
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
165-
},
166-
"progress": {
167-
"status": "in_progress",
168-
"include_percentage": True,
169-
"update_interval": 5,
170-
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
171-
}
172-
}
173-
}
174-
with mock.patch("src.utils.config_manager.load_config") as load_config_mock, \
175-
mock.patch.object(Path, "exists", return_value=True):
176-
load_config_mock.return_value = test_config_data
177-
manager = ConfigManager(config_path)
178-
load_config_mock.assert_called_once_with(Path(config_path))
179-
assert manager.config["agent"]["agent_id"] == "matlab"
180-
assert manager.config["rabbitmq"]["host"] == "localhost"
110+
def manager(config_path: Path, patched_load, patched_exists):
111+
"""A :class:`ConfigManager` instance pre‑loaded with *base_config*."""
112+
113+
return ConfigManager(config_path)
114+
115+
def test_manager_initialization(manager: ConfigManager, patched_load, config_path):
116+
"""The manager should forward *config_path* to ``load_config`` exactly once."""
117+
118+
patched_load.assert_called_once_with(Path(config_path))
119+
assert manager.config["agent"]["agent_id"] == "matlab"
181120

182121

183122
def test_get_default_config():
184-
"""Test that default configuration values are correct."""
185-
manager = ConfigManager()
186-
default_config = manager.get_default_config()
123+
"""The factory default configuration is stable and complete."""
187124

188-
assert isinstance(default_config, dict)
189-
assert default_config["agent"]["agent_id"] == "matlab"
190-
assert default_config["rabbitmq"]["port"] == 5672
125+
cm = ConfigManager()
126+
default_cfg = cm.get_default_config()
191127

128+
assert default_cfg["agent"]["agent_id"] == "matlab"
129+
assert default_cfg["rabbitmq"]["port"] == 5672
192130

193-
def test_get_config():
194-
"""Test that get_config returns the correct configuration values."""
195-
config_path = "/fake/path/config.yaml"
196-
test_config_data = {
197-
"agent": {"agent_id": "matlab"},
198-
"rabbitmq": {"host": "localhost", "port": 5672}
199-
}
200-
with mock.patch("src.utils.config_manager.load_config") as load_config_mock, \
201-
mock.patch.object(Path, "exists", return_value=True):
202-
load_config_mock.return_value = test_config_data
203-
manager = ConfigManager(config_path)
204-
config = manager.get_config()
205131

206-
assert config["agent"]["agent_id"] == "matlab"
207-
assert config["rabbitmq"]["host"] == "localhost"
132+
def test_get_config(manager: ConfigManager):
133+
"""``get_config`` should return the same data originally loaded."""
208134

135+
assert manager.get_config()["rabbitmq"]["host"] == "localhost"
209136

210-
def test_validate_config_success(dummy_credentials):
211-
"""Test that config validation succeeds with correct data."""
212-
rabbit_creds = dummy_credentials.get("rabbitmq", {})
213-
test_config_data = {
214-
"agent": {"agent_id": "matlab"},
215-
"rabbitmq": {
216-
"host": "localhost",
217-
"port": 5672,
218-
"username": rabbit_creds.get("username", "guest"),
219-
"password": rabbit_creds.get("password", "guest"),
220-
"heartbeat": 600
221-
}
222-
}
223-
with mock.patch("src.utils.config_manager.load_config") as load_config_mock, \
224-
mock.patch.object(Path, "exists", return_value=True):
225-
load_config_mock.return_value = test_config_data
226-
manager = ConfigManager("/fake/path/config.yaml")
227137

228-
# Test the protected method directly
229-
validated_config = manager._validate_config(
230-
test_config_data) # pylint: disable=protected-access
231-
assert validated_config["agent"]["agent_id"] == "matlab"
138+
@pytest.mark.parametrize("agent_id", ["matlab", "python_sim"])
139+
def test_validate_config_success(agent_id: str, base_config: dict):
140+
"""Any valid configuration variant should pass model validation."""
141+
142+
cfg = deepcopy(base_config)
143+
cfg["agent"]["agent_id"] = agent_id
144+
145+
validated = ConfigManager()._validate_config(cfg) # pylint: disable=protected-access
146+
assert validated["agent"]["agent_id"] == agent_id
232147

233148

234149
def test_validate_config_failure():
235-
"""Test that validation error is raised with invalid data."""
236-
manager = ConfigManager()
237-
invalid_config = {"rabbitmq": {"port": "not_a_number"}}
150+
"""An invalid configuration must raise a :class:`ValidationError`."""
238151

239152
with pytest.raises(ValidationError):
240-
manager._validate_config(
241-
invalid_config) # pylint: disable=protected-access
153+
ConfigManager()._validate_config({"rabbitmq": {"port": "not_a_number"}})
154+
155+
156+
def test_initialization_with_invalid_path(monkeypatch):
157+
"""If the file is missing, the manager should fall back to defaults."""
242158

159+
monkeypatch.setattr(Path, "exists", lambda *_: False)
243160

244-
def test_initialization_with_invalid_path():
245-
"""Test initialization when the configuration file does not exist."""
246-
with mock.patch.object(Path, "exists", return_value=False):
247-
manager = ConfigManager("/invalid/path/config.yaml")
161+
cm = ConfigManager("/invalid/path/config.yaml")
248162

249-
assert manager.config == manager.get_default_config()
163+
assert cm.config == cm.get_default_config()

0 commit comments

Comments
 (0)