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  if not os.path.isdir(opts.qmtest_dir):
81  print "==========> No test directory, exiting"
82  return
83 
84  # create the destination directory if necessary
85  if opts.output:
86  results_dest_dir = os.path.realpath(os.path.join(opts.qmtest_dir, os.path.dirname(opts.output)))
87  if not os.path.exists(results_dest_dir):
88  print "==========> Creating '%s'" % results_dest_dir
89  os.makedirs(results_dest_dir, 0755)
90 
91  print "==========> Entering '%s'" % opts.qmtest_dir
92  os.chdir(opts.qmtest_dir)
93 
94  qmtest_cmd = ["qmtest"]
95 
96  if not os.path.isdir("QMTest"):
97  # If the test-db directory is not initialized, we have to initialize it
98  try:
99  os.mkdir("QMTest")
100  except OSError:
101  # we cannot create the directory... we need a temporary test database
102  from tempfile import mkdtemp
103  from shutil import copytree
104  # the extra level is needed because of a limitation in copytree
105  tdb = os.path.join(mkdtemp("GaudiTest"), "qmtest")
106  copytree(".", tdb)
107  os.chmod(tdb, 0700) # This is needed because copytree will copy also the restrictive permissions
108  qmtest_cmd += ["--tdb", tdb]
109  print "==========> Initializing QMTest database"
110  os.system(" ".join(qmtest_cmd + ["create-tdb"]))
111 
112  if opts.xml_output:
113  opts.qmtest_args.insert(0, '''--result-stream "GaudiTest.XMLResultStream(dir='%s',prefix='%s_')"'''
114  % (opts.xml_output.replace("\\","\\\\"), opts.package))
115 
116  if opts.html_output:
117  opts.qmtest_args.insert(0, '''--result-stream "GaudiTest.HTMLResultStream(dir='%s')"'''
118  % opts.html_output.replace("\\","\\\\"))
119 
120  # prepare the qmtest command
121  cmd = " ".join(qmtest_cmd + ["run"] + opts.qmtest_args)
122 
123  if not opts.have_user_options:
124  # If there are no user options, we should check for a default test suite
125  # to run.
126  # The suite to run is the first one available in the list passed via
127  # the environment variable GAUDI_QMTEST_DEFAULT_SUITE (comma-separated list)
128  # or the suite with the same name as the package.
129  # If none of them is present, no argument is passed to qmtest, so all the tests
130  # are run.
131  suites = []
132  if "GAUDI_QMTEST_DEFAULT_SUITE" in os.environ:
133  suites.extend([s.strip().lower()
134  for s in os.environ["GAUDI_QMTEST_DEFAULT_SUITE"].split(",")])
135  suites.append(opts.package.lower())
136  for s in suites:
137  real_name = os.path.join(*[x + '.qms' for x in s.split('.')])
138  if os.path.exists(real_name):
139  cmd += " %s" % s
140  break
141 
142  if opts.dry_run:
143  print "==========> Would run '%s'"%cmd
144  else:
145  print "==========> Running '%s'"%cmd
146  os.system(cmd)
147 
148  # drop the temporary test DB if needed
149  if "--tdb" in qmtest_cmd:
150  from shutil import rmtree
151  def onerror(func, path, exc_info):
152  """
153  Change the permissions and try again to remove a file or a dir.
154  Ignore failures.
155  """
156  if func in [os.remove, os.rmdir]:
157  # change permissions and try again
158  try:
159  os.chmod(path, 0600)
160  os.chmod(os.path.dirname(path), 0700)
161  func(path)
162  except os.error:
163  pass
164  rmtree(os.path.dirname(qmtest_cmd[-1]), onerror = onerror)
165 
166 # Note: the return code of qmtest is not propagated to avoid that
167 # CMT stops if we have a non-PASS tests (e.g. UNTESTED).
168 if __name__ == '__main__':
169  main()
def parseOptions
Definition: run_qmtest.py:13