The Gaudi Framework  v29r0 (ff2e7097)
Run.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 import os
3 import sys
4 import xml.sax.saxutils as XSS
5 import BaseTest as GT
6 import logging
7 
8 # FIXME: module alias for backward compatibility
9 sys.modules['GaudiTest'] = GT
10 
11 
12 def basic_report(results):
13  '''
14  Report function taking the dictionary from BasicTest.run() and display
15  stdout and stderr from it.
16  '''
17  print '=== stdout ==='
18  print results.get('stdout', '')
19  print '=== stderr ==='
20  print results.get('stderr', '')
21  print '=== result ==='
22  print results.get('Status')
23  if results.get('Status') != 'passed' and 'Causes' in results:
24  print ' ', 'unexpected ' + ', '.join(results['Causes'])
25 
26 
27 def quiet_report(results):
28  '''
29  Do not report anything from the result of the test.
30  '''
31  pass
32 
33 
34 def ctest_report(results):
35  '''
36  Report function taking the dictionary from BasicTest.run() and report data
37  from it in a CTest-friendly way.
38  '''
39  # It's weird, I know, but it tells CTest not to cut the output.
40  print 'CTEST_FULL_OUTPUT'
41  print results.get('stdout', '')
42  handler = {'Environment': lambda v: '\n'.join('{0}={1}'.format(*item)
43  for item in sorted(v.iteritems())),
44  'Causes': lambda v: 'unexpected ' + ', '.join(v)}
45 
46  def id_handler(v): return str(v)
47  ignore = set(['Status', 'Name', 'stdout', 'Exit Code'])
48  template = (
49  '<DartMeasurement type="text/string" name="{0}">{1}</DartMeasurement>')
50 
51  for key in results:
52  if key in ignore:
53  continue
54  hndlr = handler.get(key, id_handler)
55  data = XSS.escape(GT.sanitize_for_xml(hndlr(results[key])))
56  sys.stdout.write(template.format(key, data))
57 
58 
59 def pprint_report(results):
60  '''
61  Report function taking the dictionary from BasicTest.run() and print it with
62  the pprint module.
63  '''
64  from pprint import pprint
65  pprint(results)
66 
67 
68 def main():
69  '''
70  Main function of the script.
71  '''
72  from optparse import OptionParser, OptionGroup
73  parser = OptionParser()
74 
75  parser.add_option('--report', action='store',
76  choices=[n.replace('_report', '')
77  for n in globals() if n.endswith('_report')],
78  help='choose a report method [default %default]')
79  parser.add_option('--common-tmpdir', action='store',
80  help='directory to be used as common temporary directory')
81  parser.add_option('-C', '--workdir', action='store',
82  help='directory to change to before starting the test')
83 
84  parser.add_option('--skip-return-code', type='int',
85  help='return code to use to flag a test as skipped '
86  '[default %default]')
87 
88  verbosity_opts = OptionGroup(parser, 'Verbosity Level',
89  'set the verbosity level of messages')
90  verbosity_opts.add_option('--silent',
91  action='store_const', dest='log_level',
92  const=logging.CRITICAL,
93  help='only critical error messages')
94  verbosity_opts.add_option('--quiet',
95  action='store_const', dest='log_level',
96  const=logging.ERROR,
97  help='error messages')
98  verbosity_opts.add_option('--warning',
99  action='store_const', dest='log_level',
100  const=logging.WARNING,
101  help='warning and error messages')
102  verbosity_opts.add_option('--verbose',
103  action='store_const', dest='log_level',
104  const=logging.INFO,
105  help='progress information messages')
106  verbosity_opts.add_option('--debug',
107  action='store_const', dest='log_level',
108  const=logging.DEBUG,
109  help='debugging messages')
110  parser.add_option_group(verbosity_opts)
111 
112  parser.set_defaults(log_level=logging.WARNING,
113  report='basic',
114  workdir=os.curdir,
115  skip_return_code=0)
116 
117  opts, args = parser.parse_args()
118  if len(args) != 1:
119  parser.error('only one test allowed')
120  filename = args[0]
121 
122  logging.basicConfig(level=opts.log_level)
123 
124  if opts.common_tmpdir:
125  if not os.path.isdir(opts.common_tmpdir):
126  os.makedirs(opts.common_tmpdir)
127  GT.BaseTest._common_tmpdir = opts.common_tmpdir
128 
129  os.chdir(opts.workdir)
130 
131  # FIXME: whithout this, we get some spurious '\x1b[?1034' in the std out on SLC6
132  if "slc6" in (os.environ.get('BINARY_TAG', '') or
133  os.environ.get('CMTCONFIG', '')):
134  os.environ['TERM'] = 'dumb'
135 
136  # Testing the file beginning with "Test" or if it is a qmt file and doing the test
137  logging.debug('processing %s', filename)
138  if filename.endswith('_test.py'):
139  indexFilePart = filename.rfind("/")
140  fileToImport = filename[indexFilePart + 1:]
141  sys.path.append(GT.RationalizePath(filename)[:-len(fileToImport) - 1])
142  imp = __import__(fileToImport[:-3])
143  fileToExec = imp.Test()
144  results = fileToExec.run()
145  elif filename.endswith(".qmt"):
146  # Check which class should be used to instantiate QMTests
147  # by default it is QMTTest but this can be overwritten via the environment
148  try:
149  test_module = os.environ.get(
150  'GAUDI_QMTEST_MODULE', 'GaudiTesting.QMTTest')
151  test_class = os.environ.get('GAUDI_QMTEST_CLASS', 'QMTTest')
152  exec 'from {} import {} as test_class'.format(
153  test_module, test_class)
154  fileToTest = test_class(filename)
155  results = fileToTest.run()
156  except Exception, e:
157  logging.error(
158  'Exception caught when trying to instantiate qmt test python object')
159  logging.error(e)
160  return 1
161 
162  report = globals()[opts.report + '_report']
163  report(results)
164 
165  if results.get('Status') == 'failed':
166  logging.debug('test failed: unexpected %s',
167  ', '.join(results['Causes']))
168  return int(results.get('Exit Code', '1'))
169  elif results.get('Status') == 'skipped':
170  return opts.skip_return_code
171  return 0
172 
173 
174 if __name__ == '__main__':
175  sys.exit(main())
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:120
def pprint_report(results)
Definition: Run.py:59
def basic_report(results)
Definition: Run.py:12
def ctest_report(results)
Definition: Run.py:34
def quiet_report(results)
Definition: Run.py:27
def main()
Definition: Run.py:68