Skip to content

Commit aaa18b3

Browse files
committed
fix(loadmanager): fix dynamic stop and proper destroy for the class and fix test
1 parent bcaf361 commit aaa18b3

File tree

5 files changed

+74
-45
lines changed

5 files changed

+74
-45
lines changed

app/managers/load_manager.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,20 @@ def __init__(self):
1111
os.getcwd(), "app/scripts/memory_stress.py"
1212
)
1313

14-
self.cpu_requested = int(os.getenv("CPU_REQUESTED", 0))
14+
self.cpu_requested = float(os.getenv("CPU_REQUESTED", 0))
1515
self.memory_requested = int(os.getenv("MEMORY_REQUESTED", 0))
1616
self.cpu_processes = []
17+
self.cpu_timers = []
18+
self.memory_timers = []
1719
self.memory_process = None
1820

1921
self.memory_at_start = int(os.getenv("INITIAL_MEMORY_LOAD", 50))
2022
self.memory_at_end = int(os.getenv("FINAL_MEMORY_LOAD", 256))
2123
self.memory_duration = int(os.getenv("MEMORY_LOAD_DURATION", 60))
2224
self.stop_memory_at_end = os.getenv("STOP_MEMORY_LOAD_AT_END", "true") == "true"
2325

24-
self.cpu_at_start = int(os.getenv("INITIAL_CPU_LOAD", 0))
25-
self.cpu_at_end = int(os.getenv("FINAL_CPU_LOAD", 1))
26+
self.cpu_at_start = float(os.getenv("INITIAL_CPU_LOAD", 0))
27+
self.cpu_at_end = float(os.getenv("FINAL_CPU_LOAD", 1))
2628
self.cpu_duration = int(os.getenv("CPU_LOAD_DURATION", 60))
2729
self.stop_cpu_at_end = os.getenv("STOP_CPU_LOAD_AT_END", "true") == "true"
2830

@@ -43,6 +45,10 @@ def __init__(self):
4345
self.stop_cpu_at_end,
4446
)
4547

48+
def __del__(self):
49+
self.stop_cpu_load()
50+
self.stop_memory_load()
51+
4652
def stop_cpu_load(self):
4753
for process in self.cpu_processes:
4854
try:
@@ -51,6 +57,9 @@ def stop_cpu_load(self):
5157
except Exception as e:
5258
raise RuntimeError(f"Failed to terminate process {process.pid}: {e}")
5359
self.cpu_processes.clear()
60+
for timer in self.cpu_timers:
61+
timer.cancel()
62+
self.cpu_timers.clear()
5463
self.cpu_requested = 0
5564

5665
def add_cpu_load(self, value: int):
@@ -75,6 +84,10 @@ def stop_memory_load(self):
7584
try:
7685
self.memory_process.terminate()
7786
self.memory_process = None
87+
88+
for timer in self.memory_timers:
89+
timer.cancel()
90+
self.memory_timers.clear()
7891
self.memory_requested = 0
7992
except Exception as e:
8093
raise RuntimeError(f"Failed to terminate memory stress: {e}")
@@ -110,7 +123,6 @@ def dynamic_memory_load(
110123
raise ValueError(
111124
"Arguments 'start_value', 'end_value', 'duration' have to be integers."
112125
) from e
113-
114126
num_intervals = duration // 10
115127

116128
if num_intervals < 1:
@@ -127,10 +139,12 @@ def apply_dynamic_memory_load(interval_num):
127139
self.add_memory_load(int(current_memory))
128140

129141
if interval_num + 1 < num_intervals:
130-
Timer(10, apply_dynamic_memory_load, [interval_num + 1]).start()
131-
else:
132-
if stop_at_end:
133-
self.stop_memory_load
142+
timer = Timer(10, apply_dynamic_memory_load, [interval_num + 1])
143+
self.memory_timers.append(timer)
144+
timer.start()
145+
elif stop_at_end:
146+
stop_timer = Timer(10, self.stop_memory_load)
147+
stop_timer.start()
134148

135149
apply_dynamic_memory_load(0)
136150

@@ -164,9 +178,13 @@ def apply_dynamic_cpu_load(interval_num):
164178
self.add_cpu_load(current_cpu)
165179

166180
if interval_num + 1 < num_intervals:
167-
Timer(10, apply_dynamic_cpu_load, [interval_num + 1]).start()
168-
else:
169-
if stop_at_end:
170-
self.stop_cpu_load
181+
timer = Timer(10, apply_dynamic_cpu_load, [interval_num + 1])
182+
self.cpu_timers.append(timer)
183+
timer.start()
184+
185+
elif stop_at_end:
186+
# Correctly schedule stop_memory_load to execute after the last interval
187+
stop_timer = Timer(10, self.stop_cpu_load)
188+
stop_timer.start()
171189

172190
apply_dynamic_cpu_load(0)

tests/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def kill_stress_processes():
2929
"""Kill all stress test processes"""
3030
for proc in psutil.process_iter(["pid", "name", "cmdline"]):
3131
try:
32-
# Chercher les processus python qui exécutent cpu_stress.py ou memory_stress.py
3332
if proc.info["cmdline"] and "python" in proc.info["cmdline"][0]:
3433
cmdline = " ".join(proc.info["cmdline"])
3534
if "cpu_stress.py" in cmdline or "memory_stress.py" in cmdline:

tests/integration/test_load_endpoints.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ def client(self):
1313
def test_cpu_load_endpoints(self, client):
1414
"""Test CPU load endpoints"""
1515
# Test start CPU load
16-
response = client.post("/load/cpu/start", json={"value": 30})
17-
assert response.status_code == 200
18-
19-
# Test stop CPU load
20-
response = client.post("/load/cpu/stop")
16+
response = client.post("/load/cpu/start", json={"value": 1})
2117
assert response.status_code == 200
2218

2319
def test_memory_load_endpoints(self, client):
@@ -26,19 +22,15 @@ def test_memory_load_endpoints(self, client):
2622
response = client.post("/load/memory/start", json={"value": 50})
2723
assert response.status_code == 200
2824

29-
# Test stop memory load
30-
response = client.post("/load/memory/stop")
31-
assert response.status_code == 200
32-
3325
def test_dynamic_load_endpoints(self, client):
3426
"""Test dynamic load endpoints"""
3527
# Test dynamic CPU load
3628
cpu_response = client.post(
3729
"/load/cpu/dynamic",
3830
json={
39-
"start_value": 10,
40-
"end_value": 20,
41-
"duration": 60,
31+
"start_value": 0,
32+
"end_value": 0.5,
33+
"duration": 30,
4234
"stop_at_end": True,
4335
},
4436
)
@@ -51,7 +43,7 @@ def test_dynamic_load_endpoints(self, client):
5143
json={
5244
"start_value": 100,
5345
"end_value": 200,
54-
"duration": 60,
46+
"duration": 20,
5547
"stop_at_end": True,
5648
},
5749
)
@@ -67,6 +59,12 @@ def test_dynamic_load_endpoints(self, client):
6759
assert "cpu_active" in load_status
6860
assert "memory_active" in load_status
6961

62+
response = client.post("/load/memory/stop")
63+
assert response.status_code == 200
64+
65+
response = client.post("/load/memory/stop")
66+
assert response.status_code == 200
67+
7068
def test_get_current_load(self, client):
7169
"""Test get current load endpoint"""
7270
response = client.get("/load")

tests/test_api.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ def test_load_endpoints():
5151
# Test CPU operations
5252
response = client.post(
5353
"/load/cpu/dynamic",
54-
json={"start_value": 10, "end_value": 20, "duration": 60, "stop_at_end": True},
54+
json={
55+
"start_value": 0.1,
56+
"end_value": 0.3,
57+
"duration": 20,
58+
"stop_at_end": True,
59+
},
5560
)
5661
assert response.status_code == 200
5762

@@ -62,6 +67,17 @@ def test_load_endpoints():
6267
assert response.status_code == 200
6368

6469
# Test Memory operations
70+
response = client.post(
71+
"/load/cpu/dynamic",
72+
json={
73+
"start_value": 100,
74+
"end_value": 256,
75+
"duration": 20,
76+
"stop_at_end": True,
77+
},
78+
)
79+
assert response.status_code == 200
80+
6581
response = client.post("/load/memory/start", json={"value": 100})
6682
assert response.status_code == 200
6783

tests/unit/test_load_manager.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ def test_initialization_with_defaults(self, load_manager):
4141

4242
def test_initialization_with_env_vars(self, monkeypatch):
4343
"""Test initialization with specific environment variables"""
44-
monkeypatch.setenv("CPU_REQUESTED", "20")
44+
monkeypatch.setenv("CPU_REQUESTED", "0.5")
4545
monkeypatch.setenv("MEMORY_REQUESTED", "40")
4646
monkeypatch.setenv("ENABLE_DYNAMIC_CPU_LOAD", "false")
4747
monkeypatch.setenv("ENABLE_DYNAMIC_MEMORY_LOAD", "false")
4848

4949
manager = LoadManager()
50-
assert manager.cpu_requested == 20
50+
assert manager.cpu_requested == 0.5
5151
assert manager.memory_requested == 40
5252

5353
# 2. Tests des méthodes CPU
@@ -65,7 +65,7 @@ def test_add_cpu_load_with_invalid_values(self, load_manager):
6565

6666
def test_stop_cpu_load(self, load_manager):
6767
"""Test stopping CPU load"""
68-
load_manager.add_cpu_load(30)
68+
load_manager.add_cpu_load(1)
6969
load_manager.stop_cpu_load()
7070
assert load_manager.cpu_requested == 0
7171
assert not load_manager.cpu_processes
@@ -78,20 +78,19 @@ def test_stop_cpu_load_no_processes(self, load_manager):
7878

7979
def test_dynamic_cpu_load(self, load_manager):
8080
"""Test dynamic CPU load"""
81-
load_manager.dynamic_cpu_load(10, 80, 1, True)
82-
assert load_manager.cpu_requested >= 10
83-
assert load_manager.cpu_requested <= 80
81+
load_manager.dynamic_cpu_load(0.1, 1, 1, True)
82+
assert load_manager.cpu_requested >= 0.1
83+
assert load_manager.cpu_requested <= 1
8484

85-
@pytest.mark.asyncio
86-
async def test_dynamic_cpu_load_invalid_duration(self, load_manager):
85+
def test_dynamic_cpu_load_invalid_duration(self, load_manager):
8786
"""Test invalid duration for dynamic CPU load"""
8887
with pytest.raises(ValueError):
89-
load_manager.dynamic_cpu_load(-1, 80, -1, True)
88+
load_manager.dynamic_cpu_load(-1, 1, -1, True)
9089

9190
def test_dynamic_cpu_load_zero_duration(self, load_manager):
9291
"""Test dynamic CPU load with zero duration"""
93-
load_manager.dynamic_cpu_load(10, 90, 0, True)
94-
assert load_manager.cpu_requested == 90
92+
load_manager.dynamic_cpu_load(0, 1, 0, False)
93+
assert load_manager.cpu_requested == 1
9594

9695
# 3. Tests des méthodes mémoire
9796
def test_add_memory_load(self, load_manager):
@@ -121,26 +120,25 @@ def test_stop_memory_load_no_processes(self, load_manager):
121120

122121
def test_dynamic_memory_load(self, load_manager):
123122
"""Test dynamic memory load"""
124-
load_manager.dynamic_memory_load(100, 200, 1, True)
123+
load_manager.dynamic_memory_load(100, 200, 1, False)
125124
assert load_manager.memory_requested >= 100
126125
assert load_manager.memory_requested <= 200
127126

128-
@pytest.mark.asyncio
129-
async def test_dynamic_memory_load_invalid_duration(self, load_manager):
127+
def test_dynamic_memory_load_invalid_duration(self, load_manager):
130128
"""Test invalid duration for dynamic memory load"""
131129
with pytest.raises(ValueError):
132130
load_manager.dynamic_memory_load(-1, 200, -1, True)
133131

134132
def test_dynamic_memory_load_zero_duration(self, load_manager):
135133
"""Test dynamic memory load with zero duration"""
136-
load_manager.dynamic_memory_load(100, 200, 0, True)
137-
assert load_manager.memory_requested == 200
134+
load_manager.dynamic_memory_load(100, 256, 0, False)
135+
assert load_manager.memory_requested == 256
138136

139137
# 4. Tests combinés et autres
140138
def test_stop_all_loads(self, load_manager):
141139
"""Test stopping all loads"""
142-
load_manager.add_cpu_load(30)
143-
load_manager.add_memory_load(50)
140+
load_manager.add_cpu_load(1)
141+
load_manager.add_memory_load(100)
144142
load_manager.stop_cpu_load()
145143
load_manager.stop_memory_load()
146144
assert load_manager.cpu_requested == 0

0 commit comments

Comments
 (0)