blob: 59d503c157fc1d74d58eaba38a580424b80c809a [file] [log] [blame]
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +01001# osmo_gsm_tester: test class
2#
3# Copyright (C) 2017 by sysmocom - s.f.m.c. GmbH
4#
5# Author: Pau Espin Pedrol <pespin@sysmocom.de>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20import os
21import sys
22import time
23import traceback
24from . import testenv
25
26from . import log, util, resource
27
28class Test(log.Origin):
29 UNKNOWN = 'UNKNOWN'
30 SKIP = 'skip'
31 PASS = 'pass'
32 FAIL = 'FAIL'
33
34 _run_dir = None
35
36 def __init__(self, suite_run, test_basename):
37 self.basename = test_basename
38 super().__init__(log.C_TST, self.basename)
39 self.suite_run = suite_run
40 self.path = os.path.join(self.suite_run.definition.suite_dir, self.basename)
41 self.status = Test.UNKNOWN
42 self.start_timestamp = 0
43 self.duration = 0
44 self.fail_type = None
45 self.fail_message = None
46
47 def get_run_dir(self):
48 if self._run_dir is None:
49 self._run_dir = util.Dir(self.suite_run.get_run_dir().new_dir(self._name))
50 return self._run_dir
51
52 def run(self):
53 try:
54 log.large_separator(self.suite_run.trial.name(), self.suite_run.name(), self.name(), sublevel=3)
55 self.status = Test.UNKNOWN
56 self.start_timestamp = time.time()
Pau Espin Pedrol9a4631c2018-03-28 19:17:34 +020057 from . import suite, sms
58 from .event_loop import MainLoop
59 testenv.setup(self.suite_run, self, suite, MainLoop, sms)
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010060 with self.redirect_stdout():
61 util.run_python_file('%s.%s' % (self.suite_run.definition.name(), self.basename),
62 self.path)
63 if self.status == Test.UNKNOWN:
64 self.set_pass()
65 except Exception as e:
66 if hasattr(e, 'msg'):
67 msg = e.msg
68 else:
69 msg = str(e)
70 if isinstance(e, AssertionError):
71 # AssertionError lacks further information on what was
72 # asserted. Find the line where the code asserted:
73 msg += log.get_src_from_exc_info(sys.exc_info())
74 # add source file information to failure report
75 if hasattr(e, 'origins'):
76 msg += ' [%s]' % e.origins
77 tb_str = traceback.format_exc()
78 if isinstance(e, resource.NoResourceExn):
79 tb_str += self.suite_run.resource_status_str()
80 self.set_fail(type(e).__name__, msg, tb_str, log.get_src_from_exc_info())
81 except BaseException as e:
82 # when the program is aborted by a signal (like Ctrl-C), escalate to abort all.
83 self.err('TEST RUN ABORTED: %s' % type(e).__name__)
84 raise
85
86 def name(self):
87 l = log.get_line_for_src(self.path)
88 if l is not None:
89 return '%s:%s' % (self._name, l)
90 return super().name()
91
92 def set_fail(self, fail_type, fail_message, tb_str=None, src=4):
93 self.status = Test.FAIL
94 self.duration = time.time() - self.start_timestamp
95 self.fail_type = fail_type
96 self.fail_message = fail_message
97
98 if tb_str is None:
99 # populate an exception-less call to set_fail() with traceback info
100 tb_str = ''.join(traceback.format_stack()[:-1])
101
102 self.fail_tb = tb_str
103 self.err('%s: %s' % (self.fail_type, self.fail_message), _src=src)
104 if self.fail_tb:
105 self.log(self.fail_tb, _level=log.L_TRACEBACK)
106 self.log('Test FAILED (%.1f sec)' % self.duration)
107
108 def set_pass(self):
109 self.status = Test.PASS
110 self.duration = time.time() - self.start_timestamp
111 self.log('Test passed (%.1f sec)' % self.duration)
112
113 def set_skip(self):
114 self.status = Test.SKIP
115 self.duration = 0
116
117# vim: expandtab tabstop=4 shiftwidth=4