Skip to content

Commit 3d0bfc2

Browse files
authored
Guards against timeout configuration error (#1232)
* Guards against timeout configuration error * Relaxing timeout condition by allowing equal * Fixed tests and used new argument based timing configurations of measurement durations [skip ci] * (fix): placeholder value removed
1 parent 6a811b8 commit 3d0bfc2

File tree

2 files changed

+30
-75
lines changed

2 files changed

+30
-75
lines changed

lib/scenario_runner.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,31 @@ def __init__(self,
163163
self.__volume_sizes = {}
164164
self.__warnings = []
165165

166+
self._check_all_durations()
167+
166168
# we currently do not use this variable
167169
# self.__filename = self._original_filename # this can be changed later if working directory changes
168170

171+
172+
def _check_all_durations(self):
173+
if self._measurement_total_duration is None: # exit early if no max timeout specififed
174+
return
175+
176+
durations = {
177+
"measurement_flow_process_duration": self._measurement_flow_process_duration,
178+
'pre_test_sleep': self._measurement_pre_test_sleep,
179+
'post_test_sleep': self._measurement_post_test_sleep,
180+
'idle_duration': self._measurement_idle_duration,
181+
'baseline_duration': self._measurement_baseline_duration,
182+
'phase_transition_time': self._measurement_phase_transition_time,
183+
'wait_time_dependencies': self._measurement_wait_time_dependencies,
184+
}
185+
186+
for key, value in durations.items():
187+
if value is not None and value > self._measurement_total_duration:
188+
raise ValueError(f"Cannot run flows due to configuration error. Measurement_total_duration must be >= {key}, otherwise the flow will run into a timeout in every case. Values are: {key}: {value} and measurement_total_duration: {self._measurement_total_duration}")
189+
190+
169191
def custom_sleep(self, sleep_time):
170192
if not self._dev_no_sleeps:
171193
print(TerminalColors.HEADER, '\nSleeping for : ', sleep_time, TerminalColors.ENDC)

tests/test_config_opts.py

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,11 @@
1111
from tests import test_functions as Tests
1212
from lib.scenario_runner import ScenarioRunner
1313

14-
#pylint: disable=unused-argument # unused arguement off for now - because there are no running tests in this file
15-
@pytest.fixture(name="reset_config")
16-
def reset_config_fixture():
17-
config = GlobalConfig().config
18-
idle_start_time = config['measurement']['idle-time-start']
19-
idle_time_end = config['measurement']['idle-time-end']
20-
flow_process_runtime = config['measurement']['flow-process-runtime']
21-
yield
22-
config['measurement']['idle-time-start'] = idle_start_time
23-
config['measurement']['idle-time-end'] = idle_time_end
24-
config['measurement']['flow-process-runtime'] = flow_process_runtime
25-
2614
def test_global_timeout():
2715

2816
measurement_total_duration = 1
2917

30-
runner = ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_cache_build=False, dev_no_sleeps=True, dev_no_metrics=True, dev_no_phase_stats=True, measurement_total_duration=1)
18+
runner = ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_cache_build=False, dev_no_sleeps=True, dev_no_metrics=True, dev_no_phase_stats=True, measurement_total_duration=1, measurement_pre_test_sleep=1, measurement_baseline_duration=1, measurement_idle_duration=1, measurement_post_test_sleep=1, measurement_wait_time_dependencies=1)
3119

3220
out = io.StringIO()
3321
err = io.StringIO()
@@ -47,6 +35,13 @@ def test_global_timeout():
4735
Tests.assertion_info('Timeout was not raised', str(out.getvalue()))
4836

4937

38+
def test_invalid_combination_measurement_flow_process_duration():
39+
40+
with pytest.raises(ValueError) as err:
41+
ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_cache_build=False, dev_no_sleeps=True, dev_no_metrics=True, dev_no_phase_stats=True, measurement_total_duration=10, measurement_flow_process_duration=20)
42+
43+
assert str(err.value) == 'Cannot run flows due to configuration error. Measurement_total_duration must be >= measurement_flow_process_duration, otherwise the flow will run into a timeout in every case. Values are: measurement_flow_process_duration: 20 and measurement_total_duration: 10'
44+
5045
def test_provider_disabling_not_active_by_default():
5146

5247

@@ -136,65 +131,3 @@ def test_phase_padding_active():
136131
assert notes[-7][0] - notes[-8][0] == runner._phase_padding_ms*FROM_MS_TO_US
137132

138133
assert notes[-6][1] == 'Ending phase [RUNTIME] [UNPADDED]'
139-
140-
141-
142-
# Rethink how to do this test entirely
143-
def wip_test_idle_start_time(reset_config):
144-
GlobalConfig().config['measurement']['idle-time-start'] = 2
145-
runner = ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_no_metrics=True, dev_no_phase_stats=True, dev_no_sleeps=True, dev_cache_build=True)
146-
run_id = runner.run()
147-
query = """
148-
SELECT
149-
time, note
150-
FROM
151-
notes
152-
WHERE
153-
run_id = %s
154-
ORDER BY
155-
time
156-
"""
157-
158-
notes = DB().fetch_all(query, (run_id,))
159-
160-
timestamp_preidle = [note for note in notes if "Booting" in note[1]][0][0]
161-
timestamp_start = [note for note in notes if note[1] == 'Start of measurement'][0][0]
162-
163-
#assert that the difference between the two timestamps is roughly 2 seconds
164-
diff = (timestamp_start - timestamp_preidle)/1000000
165-
assert 1.9 <= diff <= 2.1, \
166-
Tests.assertion_info('2s apart', f"timestamp difference of notes: {diff}s")
167-
168-
# Rethink how to do this test entirely
169-
def wip_test_idle_end_time(reset_config):
170-
GlobalConfig().config['measurement']['idle-time-end'] = 2
171-
runner = ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_no_metrics=True, dev_no_phase_stats=True, dev_no_sleeps=True, dev_cache_build=True)
172-
run_id = runner.run()
173-
query = """
174-
SELECT
175-
time, note
176-
FROM
177-
notes
178-
WHERE
179-
run_id = %s
180-
ORDER BY
181-
time
182-
"""
183-
184-
notes = DB().fetch_all(query, (run_id,))
185-
timestamp_postidle = [note for note in notes if note[1] == 'End of post-measurement idle'][0][0]
186-
timestamp_end = [note for note in notes if note[1] == 'End of measurement'][0][0]
187-
188-
#assert that the difference between the two timestamps is roughly 2 seconds
189-
diff = (timestamp_postidle - timestamp_end)/1000000
190-
assert 1.9 <= diff <= 2.1, \
191-
Tests.assertion_info('2s apart', f"timestamp difference of notes: {diff}s")
192-
193-
def wip_test_process_runtime_exceeded(reset_config):
194-
GlobalConfig().config['measurement']['flow-process-runtime'] = .1
195-
runner = ScenarioRunner(uri=GMT_DIR, uri_type='folder', filename='tests/data/usage_scenarios/basic_stress.yml', skip_system_checks=True, dev_no_metrics=True, dev_no_phase_stats=True, dev_no_sleeps=True, dev_cache_build=True)
196-
with pytest.raises(RuntimeError) as err:
197-
runner.run()
198-
expected_exception = 'Process exceeded runtime of 0.1s: stress-ng -c 1 -t 1 -q'
199-
assert expected_exception in str(err.value), \
200-
Tests.assertion_info(expected_exception, str(err.value))

0 commit comments

Comments
 (0)