Skip to content

Commit 8c2f02b

Browse files
committed
CSM Engine Updates: Update CSM engine functionality with tests
1 parent 83bbe8c commit 8c2f02b

File tree

4 files changed

+347
-3
lines changed

4 files changed

+347
-3
lines changed

cosmotech/coal/csm/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
2+
# This document and all information contained herein is the exclusive property -
3+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
4+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
5+
# etc., to any person is prohibited unless it has been previously and
6+
# specifically authorized by written means by Cosmo Tech.

cosmotech/coal/csm/engine/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Copyright (C) - 2023 - 2025 - Cosmo Tech
2-
# Licensed under the MIT license.
2+
# This document and all information contained herein is the exclusive property -
3+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
4+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
5+
# etc., to any person is prohibited unless it has been previously and
6+
# specifically authorized by written means by Cosmo Tech.
37
import csv
48
import glob
59
import json
@@ -11,8 +15,8 @@ def apply_simple_csv_parameter_to_simulator(
1115
parameter_name: str,
1216
target_attribute_name: str,
1317
csv_id_column: str = "id",
14-
csv_value_column: str = "value"
15-
):
18+
csv_value_column: str = "value",
19+
):
1620
"""
1721
Accelerator used to apply CSV parameters directly to a simulator
1822
Will raise a ValueError if the parameter does not exist
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
2+
# This document and all information contained herein is the exclusive property -
3+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
4+
# Any use reproduction translation broadcasting transmission distribution
5+
# etc. to any person is prohibited unless it has been previously and
6+
# specifically authorized by written means by Cosmo Tech.
7+
8+
import os
9+
import glob
10+
import json
11+
import tempfile
12+
from unittest.mock import MagicMock, patch, mock_open
13+
14+
import pytest
15+
16+
from cosmotech.coal.csm.engine import apply_simple_csv_parameter_to_simulator
17+
18+
19+
class TestCsmEngine:
20+
"""Tests for the CSM Engine module."""
21+
22+
@patch("os.path.exists")
23+
@patch("glob.glob")
24+
@patch("builtins.open", new_callable=mock_open, read_data='id,value\nentity1,"42"\nentity2,"true"\n')
25+
def test_apply_simple_csv_parameter_to_simulator(self, mock_file, mock_glob, mock_exists):
26+
"""Test the apply_simple_csv_parameter_to_simulator function."""
27+
# Arrange
28+
mock_exists.return_value = True
29+
mock_glob.return_value = ["/path/to/parameter/file.csv"]
30+
31+
# Create a mock simulator
32+
mock_simulator = MagicMock()
33+
mock_model = MagicMock()
34+
mock_simulator.GetModel.return_value = mock_model
35+
36+
# Create mock entities
37+
mock_entity1 = MagicMock()
38+
mock_entity2 = MagicMock()
39+
mock_entity_not_found = None
40+
41+
# Configure model to return entities
42+
def find_entity_by_name(name):
43+
if name == "entity1":
44+
return mock_entity1
45+
elif name == "entity2":
46+
return mock_entity2
47+
else:
48+
return None
49+
50+
mock_model.FindEntityByName.side_effect = find_entity_by_name
51+
52+
# Set environment variable
53+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
54+
# Act
55+
apply_simple_csv_parameter_to_simulator(
56+
simulator=mock_simulator,
57+
parameter_name="test_parameter",
58+
target_attribute_name="test_attribute",
59+
csv_id_column="id",
60+
csv_value_column="value",
61+
)
62+
63+
# Assert
64+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
65+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
66+
mock_file.assert_called_once_with("/path/to/parameter/file.csv", "r")
67+
68+
# Check that the model was retrieved
69+
mock_simulator.GetModel.assert_called_once()
70+
71+
# Check that FindEntityByName was called for each row
72+
assert mock_model.FindEntityByName.call_count == 2
73+
mock_model.FindEntityByName.assert_any_call("entity1")
74+
mock_model.FindEntityByName.assert_any_call("entity2")
75+
76+
# Check that SetAttributeAsString was called for each entity
77+
mock_entity1.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(42))
78+
mock_entity2.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(True))
79+
80+
@patch("os.path.exists")
81+
def test_apply_simple_csv_parameter_to_simulator_parameter_not_exists(self, mock_exists):
82+
"""Test the apply_simple_csv_parameter_to_simulator function when parameter does not exist."""
83+
# Arrange
84+
mock_exists.return_value = False
85+
mock_simulator = MagicMock()
86+
87+
# Set environment variable
88+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
89+
# Act & Assert
90+
with pytest.raises(ValueError, match="Parameter test_parameter does not exists."):
91+
apply_simple_csv_parameter_to_simulator(
92+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
93+
)
94+
95+
# Assert
96+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
97+
mock_simulator.GetModel.assert_not_called()
98+
99+
@patch("os.path.exists")
100+
@patch("glob.glob")
101+
def test_apply_simple_csv_parameter_to_simulator_no_csv_files(self, mock_glob, mock_exists):
102+
"""Test the apply_simple_csv_parameter_to_simulator function when no CSV files are found."""
103+
# Arrange
104+
mock_exists.return_value = True
105+
mock_glob.return_value = []
106+
mock_simulator = MagicMock()
107+
108+
# Set environment variable
109+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
110+
# Act
111+
apply_simple_csv_parameter_to_simulator(
112+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
113+
)
114+
115+
# Assert
116+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
117+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
118+
mock_simulator.GetModel.assert_not_called()
119+
120+
@patch("os.path.exists")
121+
@patch("glob.glob")
122+
@patch("builtins.open", new_callable=mock_open, read_data='id,value\nentity1,"42"\nentity_not_found,"true"\n')
123+
def test_apply_simple_csv_parameter_to_simulator_entity_not_found(self, mock_file, mock_glob, mock_exists):
124+
"""Test the apply_simple_csv_parameter_to_simulator function when an entity is not found."""
125+
# Arrange
126+
mock_exists.return_value = True
127+
mock_glob.return_value = ["/path/to/parameter/file.csv"]
128+
129+
# Create a mock simulator
130+
mock_simulator = MagicMock()
131+
mock_model = MagicMock()
132+
mock_simulator.GetModel.return_value = mock_model
133+
134+
# Create mock entity
135+
mock_entity1 = MagicMock()
136+
137+
# Configure model to return entities
138+
def find_entity_by_name(name):
139+
if name == "entity1":
140+
return mock_entity1
141+
else:
142+
return None
143+
144+
mock_model.FindEntityByName.side_effect = find_entity_by_name
145+
146+
# Set environment variable
147+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
148+
# Act
149+
apply_simple_csv_parameter_to_simulator(
150+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
151+
)
152+
153+
# Assert
154+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
155+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
156+
mock_file.assert_called_once_with("/path/to/parameter/file.csv", "r")
157+
158+
# Check that the model was retrieved
159+
mock_simulator.GetModel.assert_called_once()
160+
161+
# Check that FindEntityByName was called for each row
162+
assert mock_model.FindEntityByName.call_count == 2
163+
mock_model.FindEntityByName.assert_any_call("entity1")
164+
mock_model.FindEntityByName.assert_any_call("entity_not_found")
165+
166+
# Check that SetAttributeAsString was called only for the found entity
167+
mock_entity1.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(42))
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
2+
# This document and all information contained herein is the exclusive property -
3+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
4+
# Any use reproduction translation broadcasting transmission distribution
5+
# etc. to any person is prohibited unless it has been previously and
6+
# specifically authorized by written means by Cosmo Tech.
7+
8+
import os
9+
import glob
10+
import json
11+
import tempfile
12+
from unittest.mock import MagicMock, patch, mock_open
13+
14+
import pytest
15+
16+
from cosmotech.coal.csm.engine import apply_simple_csv_parameter_to_simulator
17+
18+
19+
class TestCsmEngine:
20+
"""Tests for the CSM Engine module."""
21+
22+
@patch("os.path.exists")
23+
@patch("glob.glob")
24+
@patch("builtins.open", new_callable=mock_open, read_data='id,value\nentity1,"42"\nentity2,"true"\n')
25+
def test_apply_simple_csv_parameter_to_simulator(self, mock_file, mock_glob, mock_exists):
26+
"""Test the apply_simple_csv_parameter_to_simulator function."""
27+
# Arrange
28+
mock_exists.return_value = True
29+
mock_glob.return_value = ["/path/to/parameter/file.csv"]
30+
31+
# Create a mock simulator
32+
mock_simulator = MagicMock()
33+
mock_model = MagicMock()
34+
mock_simulator.GetModel.return_value = mock_model
35+
36+
# Create mock entities
37+
mock_entity1 = MagicMock()
38+
mock_entity2 = MagicMock()
39+
mock_entity_not_found = None
40+
41+
# Configure model to return entities
42+
def find_entity_by_name(name):
43+
if name == "entity1":
44+
return mock_entity1
45+
elif name == "entity2":
46+
return mock_entity2
47+
else:
48+
return None
49+
50+
mock_model.FindEntityByName.side_effect = find_entity_by_name
51+
52+
# Set environment variable
53+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
54+
# Act
55+
apply_simple_csv_parameter_to_simulator(
56+
simulator=mock_simulator,
57+
parameter_name="test_parameter",
58+
target_attribute_name="test_attribute",
59+
csv_id_column="id",
60+
csv_value_column="value",
61+
)
62+
63+
# Assert
64+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
65+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
66+
mock_file.assert_called_once_with("/path/to/parameter/file.csv", "r")
67+
68+
# Check that the model was retrieved
69+
mock_simulator.GetModel.assert_called_once()
70+
71+
# Check that FindEntityByName was called for each row
72+
assert mock_model.FindEntityByName.call_count == 2
73+
mock_model.FindEntityByName.assert_any_call("entity1")
74+
mock_model.FindEntityByName.assert_any_call("entity2")
75+
76+
# Check that SetAttributeAsString was called for each entity
77+
mock_entity1.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(42))
78+
mock_entity2.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(True))
79+
80+
@patch("os.path.exists")
81+
def test_apply_simple_csv_parameter_to_simulator_parameter_not_exists(self, mock_exists):
82+
"""Test the apply_simple_csv_parameter_to_simulator function when parameter does not exist."""
83+
# Arrange
84+
mock_exists.return_value = False
85+
mock_simulator = MagicMock()
86+
87+
# Set environment variable
88+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
89+
# Act & Assert
90+
with pytest.raises(ValueError, match="Parameter test_parameter does not exists."):
91+
apply_simple_csv_parameter_to_simulator(
92+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
93+
)
94+
95+
# Assert
96+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
97+
mock_simulator.GetModel.assert_not_called()
98+
99+
@patch("os.path.exists")
100+
@patch("glob.glob")
101+
def test_apply_simple_csv_parameter_to_simulator_no_csv_files(self, mock_glob, mock_exists):
102+
"""Test the apply_simple_csv_parameter_to_simulator function when no CSV files are found."""
103+
# Arrange
104+
mock_exists.return_value = True
105+
mock_glob.return_value = []
106+
mock_simulator = MagicMock()
107+
108+
# Set environment variable
109+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
110+
# Act
111+
apply_simple_csv_parameter_to_simulator(
112+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
113+
)
114+
115+
# Assert
116+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
117+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
118+
mock_simulator.GetModel.assert_not_called()
119+
120+
@patch("os.path.exists")
121+
@patch("glob.glob")
122+
@patch("builtins.open", new_callable=mock_open, read_data='id,value\nentity1,"42"\nentity_not_found,"true"\n')
123+
def test_apply_simple_csv_parameter_to_simulator_entity_not_found(self, mock_file, mock_glob, mock_exists):
124+
"""Test the apply_simple_csv_parameter_to_simulator function when an entity is not found."""
125+
# Arrange
126+
mock_exists.return_value = True
127+
mock_glob.return_value = ["/path/to/parameter/file.csv"]
128+
129+
# Create a mock simulator
130+
mock_simulator = MagicMock()
131+
mock_model = MagicMock()
132+
mock_simulator.GetModel.return_value = mock_model
133+
134+
# Create mock entity
135+
mock_entity1 = MagicMock()
136+
137+
# Configure model to return entities
138+
def find_entity_by_name(name):
139+
if name == "entity1":
140+
return mock_entity1
141+
else:
142+
return None
143+
144+
mock_model.FindEntityByName.side_effect = find_entity_by_name
145+
146+
# Set environment variable
147+
with patch.dict(os.environ, {"CSM_PARAMETERS_ABSOLUTE_PATH": "/path/to/parameter/"}):
148+
# Act
149+
apply_simple_csv_parameter_to_simulator(
150+
simulator=mock_simulator, parameter_name="test_parameter", target_attribute_name="test_attribute"
151+
)
152+
153+
# Assert
154+
mock_exists.assert_called_once_with("/path/to/parameter/test_parameter")
155+
mock_glob.assert_called_once_with("/path/to/parameter/test_parameter/*.csv")
156+
mock_file.assert_called_once_with("/path/to/parameter/file.csv", "r")
157+
158+
# Check that the model was retrieved
159+
mock_simulator.GetModel.assert_called_once()
160+
161+
# Check that FindEntityByName was called for each row
162+
assert mock_model.FindEntityByName.call_count == 2
163+
mock_model.FindEntityByName.assert_any_call("entity1")
164+
mock_model.FindEntityByName.assert_any_call("entity_not_found")
165+
166+
# Check that SetAttributeAsString was called only for the found entity
167+
mock_entity1.SetAttributeAsString.assert_called_once_with("test_attribute", json.dumps(42))

0 commit comments

Comments
 (0)