All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
run_qmtest.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Small wrapper script to simplify the execution of QMTest tests.
4 #
5 # @author: Marco Clemencic <marco.clemencic@cern.ch>
6 # @date: 22/10/2007
7 #
8 import os, sys
9 
10 class Options(object):
11  pass
12 
13 def parseOptions(argv = None):
14  if argv is None:
15  argv = sys.argv[1:]
16  # Defaults
17  opts = Options()
18  opts.package = "Unknown"
19  opts.qmtest_args = []
20  opts.have_user_options = False
21  opts.output = os.path.normpath(os.path.expandvars(os.environ["QMTESTRESULTS"]))
22  opts.qmtest_dir = os.path.normpath(os.path.expandvars(os.environ["QMTESTLOCALDIR"]))
23  opts.dry_run = False
24  if "GAUDI_QMTEST_HTML_OUTPUT" in os.environ:
25  opts.html_output = os.path.normpath(os.path.expandvars(os.environ.get("GAUDI_QMTEST_HTML_OUTPUT")))
26  else:
27  opts.html_output = None
28  if "GAUDI_QMTEST_XML_OUTPUT" in os.environ:
29  opts.xml_output = os.path.normpath(os.path.expandvars(os.environ.get("GAUDI_QMTEST_XML_OUTPUT")))
30  else:
31  opts.xml_output = None
32 
33  # First argument is the package name:
34  if argv:
35  opts.package = argv.pop(0)
36 
37  # If the use specifies a directory where to collect all the results
38  # (e.g. because running from a read-only location) we must use it
39  if "QMTESTRESULTSDIR" in os.environ:
40  opts.output = os.path.normpath(os.path.expandvars(os.environ["QMTESTRESULTSDIR"]))
41  opts.output = os.path.join(opts.output,
42  "%s.%s.qmr" % (opts.package, os.environ.get("CMTCONFIG", "noConfig")))
43 
44  # Do we have user options?
45  opts.have_user_options = len(argv)
46  # Scan the user options (if any) to look for options we must intercept
47  while argv:
48  o = argv.pop(0)
49  if o in ['-o','--output']:
50  # make the path absolute
51  opts.output = os.path.realpath(argv.pop(0))
52  opts.have_user_options -= 2
53  elif o in ["--no-output"]:
54  opts.output = None
55  opts.have_user_options -= 1
56  elif o in ["--dry-run"]:
57  opts.dry_run = True
58  opts.have_user_options -= 1
59  elif o in ["--html-output"]:
60  opts.html_output = os.path.realpath(argv.pop(0))
61  opts.have_user_options -= 2
62  # Add xml output option
63  elif o in ["--xml-output"]:
64  opts.xml_output = os.path.realpath(argv.pop(0))
65  opts.have_user_options -= 2
66  else:
67  opts.qmtest_args.append(o)
68  # Add the option for the output to the qmtest_args
69  if opts.output:
70  opts.qmtest_args = ["-o", opts.output] + opts.qmtest_args
71  else:
72  opts.qmtest_args.insert(0, "--no-output")
73  return opts
74 
75 def main(argv = None):
76  opts = parseOptions(argv)
77 
78  print "==========> Running tests for package %s" % opts.package
79 
80  # create the destination directory if necessary
81  if opts.output:
82  results_dest_dir = os.path.realpath(os.path.join(opts.qmtest_dir, os.path.dirname(opts.output)))
83  if not os.path.exists(results_dest_dir):
84  print "==========> Creating '%s'" % results_dest_dir
85  os.makedirs(results_dest_dir, 0755)
86 
87  print "==========> Entering '%s'" % opts.qmtest_dir
88  os.chdir(opts.qmtest_dir)
89 
90  qmtest_cmd = ["qmtest"]
91 
92  if not os.path.isdir("QMTest"):
93  # If the test-db directory is not initialized, we have to initialize it
94  try:
95  os.mkdir("QMTest")
96  except OSError:
97  # we cannot create the directory... we need a temporary test database
98  from tempfile import mkdtemp
99  from shutil import copytree
100  # the extra level is needed because of a limitation in copytree
101  tdb = os.path.join(mkdtemp("GaudiTest"), "qmtest")
102  copytree(".", tdb)
103  os.chmod(tdb, 0700) # This is needed because copytree will copy also the restrictive permissions
104  qmtest_cmd += ["--tdb", tdb]
105  print "==========> Initializing QMTest database"
106  os.system(" ".join(qmtest_cmd + ["create-tdb"]))
107 
108  if opts.xml_output:
109  opts.qmtest_args.insert(0, '''--result-stream "GaudiTest.XMLResultStream(dir='%s',prefix='%s_')"'''
110  % (opts.xml_output.replace("\\","\\\\"), opts.package))
111 
112  if opts.html_output:
113  opts.qmtest_args.insert(0, '''--result-stream "GaudiTest.HTMLResultStream(dir='%s')"'''
114  % opts.html_output.replace("\\","\\\\"))
115 
116  # prepare the qmtest command
117  cmd = " ".join(qmtest_cmd + ["run"] + opts.qmtest_args)
118 
119  if not opts.have_user_options:
120  # If there are no user options, we should check for a default test suite
121  # to run.
122  # The suite to run is the first one available in the list passed via
123  # the environment variable GAUDI_QMTEST_DEFAULT_SUITE (comma-separated list)
124  # or the suite with the same name as the package.
125  # If none of them is present, no argument is passed to qmtest, so all the tests
126  # are run.
127  suites = []
128  if "GAUDI_QMTEST_DEFAULT_SUITE" in os.environ:
129  suites.extend([s.strip().lower()
130  for s in os.environ["GAUDI_QMTEST_DEFAULT_SUITE"].split(",")])
131  suites.append(opts.package.lower())
132  for s in suites:
133  real_name = os.path.join(*[x + '.qms' for x in s.split('.')])
134  if os.path.exists(real_name):
135  cmd += " %s" % s
136  break
137 
138  if opts.dry_run:
139  print "==========> Would run '%s'"%cmd
140  else:
141  print "==========> Running '%s'"%cmd
142  os.system(cmd)
143 
144  # drop the temporary test DB if needed
145  if "--tdb" in qmtest_cmd:
146  from shutil import rmtree
147  def onerror(func, path, exc_info):
148  """
149  Change the permissions and try again to remove a file or a dir.
150  Ignore failures.
151  """
152  if func in [os.remove, os.rmdir]:
153  # change permissions and try again
154  try:
155  os.chmod(path, 0600)
156  os.chmod(os.path.dirname(path), 0700)
157  func(path)
158  except os.error:
159  pass
160  rmtree(os.path.dirname(qmtest_cmd[-1]), onerror = onerror)
161 
162 # Note: the return code of qmtest is not propagated to avoid that
163 # CMT stops if we have a non-PASS tests (e.g. UNTESTED).
164 if __name__ == '__main__':
165  main()
def parseOptions
Definition: run_qmtest.py:13