pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-gsm-tester/+/18799 )
Change subject: Implement per-test timeout guard ...................................................................... Implement per-test timeout guard Timeout value can be specified by test in suite.conf: config: suite: <suite_name>: <test_name>: timeout: 2 # 2 seconds timeout Change-Id: I522f51f77f8be64ebfdb5d5e07ba92baf82d7706 --- M selftest/suite_test/suite_test.py M selftest/suite_test/suitedirA/test_suite/suite.conf A selftest/suite_test/suitedirA/test_suite/test_timeout.py M src/osmo_gsm_tester/core/suite.py M src/osmo_gsm_tester/core/test.py M src/osmo_gsm_tester/testenv.py 6 files changed, 30 insertions(+), 5 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/99/18799/1 diff --git a/selftest/suite_test/suite_test.py b/selftest/suite_test/suite_test.py index 260b9c4..9708037 100755 --- a/selftest/suite_test/suite_test.py +++ b/selftest/suite_test/suite_test.py @@ -102,7 +102,7 @@ s = suite.SuiteRun(trial, 'test_suite', s_def, [sc]) s.reserve_resources() print(repr(s.reserved_resources)) -results = s.run_tests('test_suite_params.py') +results = s.run_tests(['test_suite_params.py', 'test_timeout.py']) print(report.suite_to_text(s)) print('- test with template overlay') diff --git a/selftest/suite_test/suitedirA/test_suite/suite.conf b/selftest/suite_test/suitedirA/test_suite/suite.conf index ff4899a..0426ea7 100644 --- a/selftest/suite_test/suitedirA/test_suite/suite.conf +++ b/selftest/suite_test/suitedirA/test_suite/suite.conf @@ -15,3 +15,9 @@ one_bool_parameter: 'bool_str' second_list_parameter: ['uint'] + +config: + suite: + test_suite: + test_timeout: + timeout: 1 # timeout in 1 second diff --git a/selftest/suite_test/suitedirA/test_suite/test_timeout.py b/selftest/suite_test/suitedirA/test_suite/test_timeout.py new file mode 100644 index 0000000..eeddb70 --- /dev/null +++ b/selftest/suite_test/suitedirA/test_suite/test_timeout.py @@ -0,0 +1,6 @@ +from osmo_gsm_tester.testenv import * + +timeout = int(tenv.config_test_specific()['timeout']) +print('starting test and waiting to receive Timeout after %d seconds' % timeout) +sleep(10) +print('test failed, we expected timeout after %d seconds' % timeout) diff --git a/src/osmo_gsm_tester/core/suite.py b/src/osmo_gsm_tester/core/suite.py index 9b9062d..aa09cd6 100644 --- a/src/osmo_gsm_tester/core/suite.py +++ b/src/osmo_gsm_tester/core/suite.py @@ -44,6 +44,8 @@ self.suite_dir = suite_dir self.conf = None self._schema = None + self.test_basenames = [] + self.load_test_basenames() self.read_conf() def read_conf(self): @@ -54,13 +56,17 @@ SuiteDefinition.CONF_FILENAME)) # Drop schema part since it's dynamically defining content, makes no sense to validate it. self._schema = self.conf.pop('schema', {}) + # Add per-test 'timeout' attribute: + d = {t.rstrip('.py'):{'timeout': schema.DURATION} for t in self.test_basenames} + #self.log('dictionary is: %r' % repr(d)) + schema.combine(self._schema, d) + # Convert config file format to proper schema format and register it: sdef = schema.config_to_schema_def(self._schema, "%s." % self._suite_name) schema.register_config_schema('suite', sdef) + # Finally validate the file: schema.validate(self.conf, schema.get_all_schema()) - self.load_test_basenames() def load_test_basenames(self): - self.test_basenames = [] for basename in sorted(os.listdir(self.suite_dir)): if not basename.endswith('.py'): continue diff --git a/src/osmo_gsm_tester/core/test.py b/src/osmo_gsm_tester/core/test.py index 45dfd41..2fa4fe9 100644 --- a/src/osmo_gsm_tester/core/test.py +++ b/src/osmo_gsm_tester/core/test.py @@ -35,12 +35,12 @@ PASS = 'pass' FAIL = 'FAIL' - def __init__(self, suite_run, test_basename, test_specific_config): + def __init__(self, suite_run, test_basename, config_test_specific): self.basename = test_basename super().__init__(log.C_TST, self.basename) self._run_dir = None self.suite_run = suite_run - self._config_test_specific = test_specific_config + self._config_test_specific = config_test_specific self.path = os.path.join(self.suite_run.definition.suite_dir, self.basename) self.status = Test.UNKNOWN self.start_timestamp = 0 @@ -49,6 +49,7 @@ self.fail_message = None self.log_targets = [] self._report_stdout = None + self.timeout = int(config_test_specific['timeout']) if 'timeout' in config_test_specific else None def module_name(self): 'Return test name without trailing .py' @@ -110,6 +111,10 @@ 'time elapsed since test was started' return time.time() - self.start_timestamp + def verify_timeout(self): + if self.timeout is not None and self.elapsed_time() > self.timeout: + raise log.Error('Test Timeout triggered: %d seconds elapsed' % self.timeout) + def set_fail(self, fail_type, fail_message, tb_str=None, src=4): self.status = Test.FAIL self.duration = self.elapsed_time() diff --git a/src/osmo_gsm_tester/testenv.py b/src/osmo_gsm_tester/testenv.py index 11199c2..e2e8ce9 100644 --- a/src/osmo_gsm_tester/testenv.py +++ b/src/osmo_gsm_tester/testenv.py @@ -130,6 +130,8 @@ proc.log_stderr_tail() log_module.ctx(proc) raise log_module.Error('Process ended prematurely: %s' % proc.name()) + # TODO: do it better, use a GLib timer and make sure to remove in testenv.stop() + self._test.verify_timeout() def stop(self): # if sys.exit() called from signal handler (e.g. SIGINT), SystemExit -- To view, visit https://gerrit.osmocom.org/c/osmo-gsm-tester/+/18799 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-gsm-tester Gerrit-Branch: master Gerrit-Change-Id: I522f51f77f8be64ebfdb5d5e07ba92baf82d7706 Gerrit-Change-Number: 18799 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-MessageType: newchange