-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_profiles.py
More file actions
213 lines (163 loc) · 8.95 KB
/
Copy pathtest_profiles.py
File metadata and controls
213 lines (163 loc) · 8.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
"""
Tests for core/profiles.py
Covers: _is_gaming_by_load, _is_gaming_by_process, _check_user_profiles,
evaluate(), get_current(), set_manual_override().
psutil.process_iter is mocked — no real process list needed.
cfg.get() is monkeypatched to a controlled config.
"""
import os
import sys
import pytest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@pytest.fixture(autouse=True)
def reset_profile_state():
"""Reset module-level profile state before each test."""
import core.profiles as p
p._current_profile = "idle"
p._manual_override = None
yield
p._current_profile = "idle"
p._manual_override = None
@pytest.fixture
def base_config(monkeypatch):
import core.config_manager as cm
from core.constants import DEFAULT_CONFIG
import copy
c = copy.deepcopy(DEFAULT_CONFIG)
monkeypatch.setattr(cm, "_config", c)
return c
# ─────────────────────────────────────────────────────────────────────────────
# _is_gaming_by_load
# ─────────────────────────────────────────────────────────────────────────────
def test_gaming_by_load_high_gpu(base_config):
from core.profiles import _is_gaming_by_load
sensors = {"gpu_load": 80, "cpu_load_pct": 20}
c = base_config
assert _is_gaming_by_load(sensors, c) is True
def test_gaming_by_load_both_elevated(base_config):
from core.profiles import _is_gaming_by_load
# gpu_load below threshold but combined with high CPU
sensors = {"gpu_load": 25, "cpu_load_pct": 60}
c = base_config
# 25 >= 40 * 0.6 = 24 → True
assert _is_gaming_by_load(sensors, c) is True
def test_gaming_by_load_idle(base_config):
from core.profiles import _is_gaming_by_load
sensors = {"gpu_load": 5, "cpu_load_pct": 10}
c = base_config
assert _is_gaming_by_load(sensors, c) is False
def test_gaming_by_load_missing_gpu(base_config):
from core.profiles import _is_gaming_by_load
sensors = {"cpu_load_pct": 99}
c = base_config
assert _is_gaming_by_load(sensors, c) is False
# ─────────────────────────────────────────────────────────────────────────────
# _is_gaming_by_process
# ─────────────────────────────────────────────────────────────────────────────
def test_gaming_by_process_known_game(base_config):
from core.profiles import _is_gaming_by_process
running = {"thedivision2.exe", "explorer.exe"}
assert _is_gaming_by_process(running, base_config) is True
def test_gaming_by_process_launcher(base_config):
# Launcher processes (steam.exe, epicgameslauncher.exe, ...) are
# intentionally NOT in GAMING_PROCESSES — they run whenever the platform
# is open. Only processes that imply a game is actually running count.
from core.profiles import _is_gaming_by_process
running = {"thedivision2.exe", "chrome.exe"}
assert _is_gaming_by_process(running, base_config) is True
def test_gaming_by_process_no_game(base_config):
from core.profiles import _is_gaming_by_process
running = {"chrome.exe", "explorer.exe", "notepad.exe"}
assert _is_gaming_by_process(running, base_config) is False
def test_gaming_by_process_custom_game(base_config):
from core.profiles import _is_gaming_by_process
base_config["profiles"]["custom_gaming_processes"] = ["mygame.exe"]
running = {"mygame.exe"}
assert _is_gaming_by_process(running, base_config) is True
# ─────────────────────────────────────────────────────────────────────────────
# _check_user_profiles
# ─────────────────────────────────────────────────────────────────────────────
def test_check_user_profiles_match(base_config):
from core.profiles import _check_user_profiles
base_config["profiles"]["user_profiles"] = [
{"name": "editing", "label": "Editing",
"processes": ["premiere.exe"], "priority": 50}
]
running = {"premiere.exe", "chrome.exe"}
result = _check_user_profiles(running, base_config)
assert result == "editing"
def test_check_user_profiles_no_match(base_config):
from core.profiles import _check_user_profiles
base_config["profiles"]["user_profiles"] = [
{"name": "editing", "label": "Editing",
"processes": ["premiere.exe"], "priority": 50}
]
running = {"chrome.exe", "explorer.exe"}
result = _check_user_profiles(running, base_config)
assert result is None
def test_check_user_profiles_priority_order(base_config):
from core.profiles import _check_user_profiles
base_config["profiles"]["user_profiles"] = [
{"name": "low_prio", "processes": ["shared.exe"], "priority": 90},
{"name": "high_prio", "processes": ["shared.exe"], "priority": 10},
]
running = {"shared.exe"}
result = _check_user_profiles(running, base_config)
assert result == "high_prio"
def test_check_user_profiles_empty_process_list_no_match(base_config):
from core.profiles import _check_user_profiles
base_config["profiles"]["user_profiles"] = [
{"name": "empty", "processes": [], "priority": 10}
]
running = {"anything.exe"}
result = _check_user_profiles(running, base_config)
assert result is None
# ─────────────────────────────────────────────────────────────────────────────
# Manual override
# ─────────────────────────────────────────────────────────────────────────────
def test_manual_override_set_and_get():
from core import profiles
profiles.set_manual_override("gaming")
assert profiles.get_current() == "gaming"
assert profiles.is_manual_override() is True
def test_manual_override_clear():
from core import profiles
profiles.set_manual_override("gaming")
profiles.set_manual_override(None)
assert profiles.is_manual_override() is False
assert profiles.get_current() == "idle"
# ─────────────────────────────────────────────────────────────────────────────
# evaluate() integration
# ─────────────────────────────────────────────────────────────────────────────
def test_evaluate_idle_when_nothing_running(base_config, monkeypatch):
import core.profiles as p
monkeypatch.setattr(p, "_get_running_processes", lambda: set())
result = p.evaluate({"gpu_load": 2, "cpu_load_pct": 3})
assert result == "idle"
def test_evaluate_gaming_by_process(base_config, monkeypatch):
import core.profiles as p
monkeypatch.setattr(p, "_get_running_processes", lambda: {"thedivision2.exe"})
result = p.evaluate({"gpu_load": 5, "cpu_load_pct": 5})
assert result == "gaming"
def test_evaluate_streaming_takes_priority_over_gaming(base_config, monkeypatch):
import core.profiles as p
monkeypatch.setattr(p, "_get_running_processes",
lambda: {"obs64.exe", "steam.exe"})
result = p.evaluate({"gpu_load": 70})
assert result == "streaming"
def test_evaluate_manual_override_bypasses_detection(base_config, monkeypatch):
import core.profiles as p
monkeypatch.setattr(p, "_get_running_processes", lambda: {"steam.exe"})
p.set_manual_override("idle")
result = p.evaluate({"gpu_load": 90, "cpu_load_pct": 90})
assert result == "idle"
def test_evaluate_gaming_by_load_fallback(base_config, monkeypatch):
# Load-based detection requires _LOAD_HIT_NEEDED consecutive hits before
# committing to gaming (anti-flap hysteresis). Call evaluate() enough
# times to clear the threshold.
import core.profiles as p
monkeypatch.setattr(p, "_get_running_processes", lambda: set())
result = None
for _ in range(p._LOAD_HIT_NEEDED):
result = p.evaluate({"gpu_load": 80, "cpu_load_pct": 50})
assert result == "gaming"