4 from sys import stdout, stderr
5 from optparse import OptionParser
7 from os.path import basename, splitext, abspath
8 from subprocess import Popen, PIPE
9 from ctypes import cdll, c_int
20 verbose_level = V_ERROR
25 %(passed_suites)s test suite(s) passed, %(failed_suites)s failed, \
26 %(skipped_suites)s skipped.
27 %(passed_cases)s test case(s) passed, %(failed_cases)s failed.
28 %(passed_checks)s check(s) passed, %(failed_checks)s failed.
31 def log(level, msg, *args):
36 if verbose_level >= level:
37 out.write((msg % args) + '\n')
40 def get_fun(so, name, argtype=None, restype=None):
47 def get_val(so, name):
48 return c_int.in_dll(so, name).value
51 #class SOError (Exception):
55 class TestCase(object):
57 def __init__(self, so, name):
60 self.testcase = get_fun(so, name)
61 self.reset_counters = get_fun(so, 'mutest_reset_counters')
62 self.set_verbose_level = get_fun(so,
63 'mutest_set_verbose_level', argtype=[c_int])
66 def passed_count(self):
67 return get_val(self.so, 'mutest_passed_count')
70 def failed_count(self):
71 return get_val(self.so, 'mutest_failed_count')
75 self.set_verbose_level(verbose_level)
78 return (self.passed_count, self.failed_count)
81 class TestSuiteResult (object):
89 return 'TestSuiteResult(failed=%s, passed_cases=%s, '\
90 'failed_cases=%s, passed_checks=%s, failed_checks=%s)'\
92 self.passed_cases, self.failed_cases,
93 self.passed_checks, self.failed_checks)
96 class TestSuite (object):
98 def __init__(self, so, name, case_names):
102 self.api_version = get_val(so, 'mutest_api_version')
106 self.cases = [TestCase(self.so, name) for name in case_names]
109 r = TestSuiteResult()
110 for case in self.cases:
111 log(V_CASE, "\t* Executing test case '%s'...",
113 (case_passed_checks, case_failed_checks) = case.run()
114 log(V_CASE, '\t Results: %s check(s) passed, %s '
115 'failed.', case_passed_checks,
117 if case_failed_checks:
122 r.passed_checks += case_passed_checks
123 r.failed_checks += case_failed_checks
127 case_names_re = re.compile(r'[0-9a-f]{8} T (mu_test\w*)', re.I)
129 def get_case_names(so_name):
130 proc = Popen(['nm', '-p', so_name], stdout=PIPE)
131 output = proc.communicate()[0]
132 return case_names_re.findall(output)
135 def parse_arguments(args):
136 verbose_help = ('Show a short result summary, add more for extra '
137 'verbosity: -vv for test suites progress, -vvv for '
138 'test cases progress and -vvvv for printing each '
139 'and every check done')
140 quiet_help = ('Be quiet (overrides -v)')
141 search_help = ('Search for all test suites in the current directory '
142 '(*.so) and add them')
143 parser = OptionParser()
144 parser.add_option('-v', dest='verbose_level', action='count',
145 default=1, help=verbose_help)
146 parser.add_option('-q', '--verbose-level', dest='quiet',
147 action='store_true', default=False, help=quiet_help)
148 parser.add_option('-a', '--search-all', dest='search_all',
149 action='store_true', default=False, help=search_help)
150 return parser.parse_args()
156 (opts, args) = parse_arguments(args)
161 verbose_level = opts.verbose_level
164 args.extend(glob('*.so'))
167 log(V_SUMMARY, 'No test suites to run')
170 results = dict(passed_suites=0, failed_suites=0, skipped_suites=0,
171 passed_cases=0, failed_cases=0,
172 passed_checks=0, failed_checks=0)
175 suite_name = splitext(basename(so_name))[0]
176 log(V_SUITE, '\nRunning test suite "%s"...', suite_name)
179 so = cdll.LoadLibrary(abspath(so_name))
181 log(V_ERROR, 'Error loading "%s" (%s), skipping '
182 'test suite "%s"', so_name, e,
184 results['skipped_suites'] += 1
187 case_names = get_case_names(so_name)
189 suite = TestSuite(so, suite_name, case_names)
191 if suite.api_version != API_VERSION:
192 log(V_ERROR, 'Wrong API version (%s expected, %s '
193 'found), skipping test suite "%s"',
194 API_VERSION, suite.api_version,
196 results['skipped_suites'] += 1
201 log(V_SUITE, 'Results: %s test case(s) passed, %s failed, '
202 '%s check(s) passed, %s failed.',
203 r.passed_cases, r.failed_cases,
204 r.passed_checks, r.failed_checks)
207 results['failed_suites'] += 1
209 results['passed_suites'] += 1
210 results['failed_cases'] += r.failed_cases
211 results['passed_cases'] += r.passed_cases
212 results['failed_checks'] += r.failed_checks
213 results['passed_checks'] += r.passed_checks
215 log(V_SUMMARY, SUMMARY_TEXT % results)
220 if __name__ == '__main__':
222 sys.exit(main(sys.argv[1:]))