Skip to content

Commit 0d6ba9e

Browse files
committed
Enhance parameter validation testing
This commit adds comprehensive test coverage for the parameter validation functionality in the helpers module. The changes include: - Added test cases for all simulation parameters (lambda, mu, goalConnections, etc.) - Created dedicated test methods for each parameter's validation logic - Implemented a helper assertion method (_assert_invalid_param) for cleaner tests - Added validation for edge cases (zero values, out-of-bounds values, incorrect types) - Improved test organization and readability - Ensured consistent validation behavior across all parameters
1 parent c69825c commit 0d6ba9e

8 files changed

Lines changed: 337 additions & 232 deletions

pytest.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[pytest]
2+
testpaths = tests
3+
markers =
4+
smoke: mark test as smoke test
5+
regression: mark test as regression test

tests/test_compilation.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
from flask_testing import TestCase
44
from backend import app, compile_simulation
5+
from tests.test_utils import temporarily_rename_file
56
import json
67
import os
78

9+
810
class TestCompilation(TestCase):
911
"""Tests for simulation compilation"""
1012

@@ -13,27 +15,27 @@ def create_app(self):
1315
return app
1416

1517
def test_compilation_failure(self):
16-
os.rename("./src/main.cpp", "./src/main.cpp.temp")
17-
compile_result = compile_simulation(debug=True)
18-
os.rename("./src/main.cpp.temp", "./src/main.cpp")
19-
self.assertFalse(compile_result)
18+
# Test with missing main.cpp file
19+
with temporarily_rename_file("./src/main.cpp", "./src/main.cpp.temp"):
20+
compile_result = compile_simulation(debug=True)
21+
self.assertFalse(compile_result)
2022

21-
response = self.client.post('/run_simulation',
22-
data=json.dumps({}),
23-
content_type='application/json')
24-
self.assert_status(response, 500)
23+
response = self.client.post('/run_simulation',
24+
data=json.dumps({}),
25+
content_type='application/json')
26+
self.assert_status(response, 500)
2527

26-
os.rename("./src/main.cpp", "./src/main.cpp.temp")
27-
os.rename("./src/test_main.cpp", "./src/main.cpp")
28-
compile_result = compile_simulation(debug=True)
29-
self.assertFalse(compile_result)
30-
31-
response = self.client.post('/run_simulation',
32-
data=json.dumps({}),
33-
content_type='application/json')
34-
self.assert_status(response, 500)
35-
os.rename("./src/main.cpp", "./src/test_main.cpp")
36-
os.rename("./src/main.cpp.temp", "./src/main.cpp")
28+
# Test with invalid main.cpp file
29+
if os.path.exists("./src/test_main.cpp"):
30+
with temporarily_rename_file("./src/main.cpp", "./src.main.cpp.temp"):
31+
with temporarily_rename_file("./src/test_main.cpp", "./src/main.cpp"):
32+
compile_result = compile_simulation(debug=True)
33+
self.assertFalse(compile_result)
34+
35+
response = self.client.post('/run_simulation',
36+
data=json.dumps({}),
37+
content_type='application/json')
38+
self.assert_status(response, 500)
3739

3840
def test_compilation_success(self):
3941
compile_result = compile_simulation(debug=True)

tests/test_help_endpoint.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from flask_testing import TestCase
44
from backend import app
5+
import pytest
56

67
class TestHelpEndpoint(TestCase):
78
"""Tests for help endpoint"""

tests/test_helpers.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Tests for utils/helpers.py
2+
3+
import pytest
4+
import os
5+
from flask_testing import TestCase
6+
from backend import app
7+
from utils.helpers import *
8+
9+
class TestHelpers(TestCase):
10+
"""Tests for utils functions"""
11+
12+
def create_app(self):
13+
app.config['TESTING'] = True
14+
return app
15+
16+
def test_compile_simulation(self):
17+
# Test compilation failure
18+
os.rename("./src/main.cpp", "./src/main.cpp.temp")
19+
self.assertFalse(compile_simulation(debug=True))
20+
os.rename("./src/main.cpp.temp", "./src/main.cpp")
21+
22+
# Test compilation success
23+
self.assertTrue(compile_simulation(debug=True))
24+
25+
def test_validate_simulation_prerequisites(self):
26+
# Test when executable is not found
27+
os.rename("./src/simulation.out", "./src/simulation.out.temp_error")
28+
is_valid, response = validate_simulation_prerequisites()
29+
self.assertFalse(is_valid)
30+
self.assertEqual(response[1], 500)
31+
os.rename("./src/simulation.out.temp_error", "./src/simulation.out")
32+
33+
# Test when executable is found
34+
self.assertTrue(compile_simulation(debug=True))
35+
is_valid, response = validate_simulation_prerequisites()
36+
self.assertTrue(is_valid)
37+
38+
def test_invalid_lambda_param(self):
39+
# Test lambda = 0
40+
is_valid, response = parse_simulation_parameters({"lambdaParam": 0})
41+
self._assert_invalid_param(is_valid, response, "lambdaParam must be greater than 0")
42+
43+
# Test lambda as string
44+
is_valid, response = parse_simulation_parameters({"lambdaParam": "string"})
45+
self._assert_invalid_param(is_valid, response, "lambdaParam must be a number")
46+
47+
def test_invalid_mu_param(self):
48+
# Test mu = 0
49+
is_valid, response = parse_simulation_parameters({"mu": 0})
50+
self._assert_invalid_param(is_valid, response, "mu must be greater than 0")
51+
52+
# Test mu as string
53+
is_valid, response = parse_simulation_parameters({"mu": "string"})
54+
self._assert_invalid_param(is_valid, response, "mu must be a number")
55+
56+
def test_invalid_goal_connections(self):
57+
# Test goalConnections = 0
58+
is_valid, response = parse_simulation_parameters({"goalConnections": 0})
59+
self._assert_invalid_param(is_valid, response, "goalConnections must be greater than 0")
60+
61+
# Test goalConnections too high
62+
is_valid, response = parse_simulation_parameters({"goalConnections": 10000001})
63+
self._assert_invalid_param(is_valid, response, "goalConnections must be less than 10,000,000")
64+
65+
# Test goalConnections as string
66+
is_valid, response = parse_simulation_parameters({"goalConnections": "string"})
67+
self._assert_invalid_param(is_valid, response, "goalConnections must be an integer")
68+
69+
def test_invalid_network_type(self):
70+
# Test unsupported network type
71+
is_valid, response = parse_simulation_parameters({"networkType": 99})
72+
self._assert_invalid_param(is_valid, response, "At the moment only networkType 1 is supported")
73+
74+
# Test network type as string
75+
is_valid, response = parse_simulation_parameters({"networkType": "string"})
76+
self._assert_invalid_param(is_valid, response, "networkType must be an integer")
77+
78+
def test_invalid_confidence(self):
79+
# Test confidence too high
80+
is_valid, response = parse_simulation_parameters({"confidence": 1.1})
81+
self._assert_invalid_param(is_valid, response, "confidence must be between 0 and 1")
82+
83+
# Test confidence too low
84+
is_valid, response = parse_simulation_parameters({"confidence": -0.1})
85+
self._assert_invalid_param(is_valid, response, "confidence must be between 0 and 1")
86+
87+
# Test confidence as string
88+
is_valid, response = parse_simulation_parameters({"confidence": "string"})
89+
self._assert_invalid_param(is_valid, response, "confidence must be a number")
90+
91+
def test_invalid_algorithm(self):
92+
# Test invalid algorithm name
93+
is_valid, response = parse_simulation_parameters({"algorithm": "InvalidAlgorithm"})
94+
self._assert_invalid_param(is_valid, response, "algorithm must be FirstFit or BestFit")
95+
96+
# Test algorithm as number
97+
is_valid, response = parse_simulation_parameters({"algorithm": 123})
98+
self._assert_invalid_param(is_valid, response, "algorithm must be a string")
99+
100+
def test_invalid_k(self):
101+
# Test K too small
102+
is_valid, response = parse_simulation_parameters({"K": 0})
103+
self._assert_invalid_param(is_valid, response, "Min K is 1")
104+
105+
# Test K too large
106+
is_valid, response = parse_simulation_parameters({"K": 100})
107+
self._assert_invalid_param(is_valid, response, "Max K is 6")
108+
109+
# Test K as string
110+
is_valid, response = parse_simulation_parameters({"K": "string"})
111+
self._assert_invalid_param(is_valid, response, "K must be an integer")
112+
113+
def test_invalid_network(self):
114+
# Test invalid network name
115+
is_valid, response = parse_simulation_parameters({"network": "TestNetwork"})
116+
self._assert_invalid_param(is_valid, response, "network must be one of")
117+
118+
# Test network as number
119+
is_valid, response = parse_simulation_parameters({"network": 123})
120+
self._assert_invalid_param(is_valid, response, "network must be a string")
121+
122+
def test_invalid_bitrate(self):
123+
# Test invalid bitrate name
124+
is_valid, response = parse_simulation_parameters({"bitrate": "TestBitRate"})
125+
self._assert_invalid_param(is_valid, response, "bitrate must be one of")
126+
127+
# Test bitrate as number
128+
is_valid, response = parse_simulation_parameters({"bitrate": 123})
129+
self._assert_invalid_param(is_valid, response, "bitrate must be a string")
130+
131+
def _assert_invalid_param(self, is_valid, response, expected_error):
132+
"""Helper method to validate common assertions for invalid parameters"""
133+
self.assertFalse(is_valid)
134+
response_json = response[0].json
135+
self.assertEqual(response_json["status"], "error")
136+
self.assertEqual(response_json["message"], "Invalid parameters")
137+
self.assertIn(expected_error, response_json["error"])
138+
139+
def test_parse_simulation_parameters_valid(self):
140+
data = {
141+
"algorithm": "FirstFit",
142+
"networkType": 1,
143+
"goalConnections": 10,
144+
"confidence": 0.05,
145+
"lambdaParam": 1,
146+
"mu": 10,
147+
"network": "NSFNet",
148+
"bitrate": "fixed-rate",
149+
"K": 3
150+
}
151+
is_valid, params = parse_simulation_parameters(data)
152+
self.assertTrue(is_valid)
153+
self.assertEqual(params, ("FirstFit", 1, 10, 0.05, 1, 10, "NSFNet", "fixed-rate", 3))
154+
155+
def test_build_simulation_command(self):
156+
params = ("FirstFit", 1, 10, 0.05, 1, 10, "NSFNet", "fixed-rate", 3)
157+
command = build_simulation_command(params)
158+
expected_command = [
159+
f"./{SIMULATION_EXECUTABLE}",
160+
"FirstFit",
161+
"1",
162+
"10",
163+
"0.05",
164+
"1",
165+
"10",
166+
"NSFNet",
167+
"fixed-rate",
168+
"3"
169+
]
170+
self.assertEqual(command, expected_command)

0 commit comments

Comments
 (0)