All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qmtest_summarize.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Simple script to loop over the packages providing tests and collect
4 # the result summaries
5 #
6 # @author: Marco Clemencic <marco.clemencic@cern.ch>
7 # @date: 3/11/2007
8 #
9 import os, sys, re
10 
11 def parse_summary(output):
12  report = { "results":[], "not_passed":[], "statistics": {} }
13  current_block = None
14  for l in output.splitlines():
15  if l.startswith("--- TEST RESULTS"):
16  current_block = "results"
17  elif l.startswith("--- TESTS THAT DID NOT PASS"):
18  current_block = "not_passed"
19  elif l.startswith("--- STATISTICS"):
20  current_block = "statistics"
21  else:
22  if current_block in ["results","not_passed"]:
23  report[current_block].append(l)
24  elif current_block == "statistics":
25  tkns = l.split()
26  if tkns:
27  report["statistics"][tkns[-1]] = int(tkns[0])
28 
29  report["results"] = report["results"][:-1]
30  report["not_passed"] = report["not_passed"][:-2]
31  if report["not_passed"][-1].strip() == "None.":
32  report["not_passed"] = []
33  return report
34 
36  # I assume that this script is run from a CMT action, which implies few other
37  # things:
38  # - we are in the cmt directory of a package
39  # - CMTCONFIG etc. are correctly defined
40  # - we can call cmt
41 
42  # If the use specifies a directory where to collect all the results
43  # (e.g. because running from a read-only location) we must use it
44  if "QMTESTRESULTSDIR" in os.environ:
45  outputdir = os.path.normpath(os.path.expandvars(os.environ["QMTESTRESULTSDIR"]))
46  else:
47  outputdir = None
48 
49  ## Directory where to store the report
50  #if "CMTINSTALLAREA" not in os.environ:
51  # os.environ["CMTINSTALLAREA"] = os.popen("cmt show macro_value CMTINSTALLAREA","r").read().strip()
52 
53  # Find the packages (their cmt dirs)
54  cmt_br_header_re = re.compile(r"^# Now trying.*in (.*) \([0-9]+/[0-9]+\)")
55  dirs = []
56 
57  # Hack to work around a problem with cmt broadcast and CMTUSERCONTEXT.
58  old_CMTUSERCONTEXT = None
59  if "CMTUSERCONTEXT" in os.environ:
60  old_CMTUSERCONTEXT = os.environ["CMTUSERCONTEXT"]
61  del os.environ["CMTUSERCONTEXT"]
62 
63  for l in os.popen("cmt broadcast","r"):
64  m = cmt_br_header_re.match(l)
65  if m:
66  dirs.append(m.group(1))
67 
68  # Restore original CMTUSERCONTEXT, if it was set.
69  if old_CMTUSERCONTEXT is not None:
70  os.environ["CMTUSERCONTEXT"] = old_CMTUSERCONTEXT
71 
72  # Find the results.qmr files
73  if not outputdir:
74  results = filter(os.path.isfile,[ os.path.realpath(os.path.join(d,'..',os.environ["CMTCONFIG"],"results.qmr")) for d in dirs ])
75  else:
76  results = []
77  for d in dirs:
78  pkg = os.path.basename(os.path.dirname(d))
79  r = os.path.join(outputdir, "%s.%s.qmr" % (pkg, os.environ.get("CMTCONFIG", "noConfig")))
80  if os.path.isfile(r):
81  results.append(r)
82 
83  return results
84 
86  results = []
87  for r, ds, fs in os.walk(os.getcwd()):
88  for f in fs:
89  if f.endswith('.qmr'):
90  results.append(os.path.join(r, f))
91  return results
92 
94  if os.path.exists('CMakeCache.txt'):
95  return find_results_cmake()
96  else:
97  return find_results_cmt()
98 
99 def main():
100  results = find_results()
101 
102  # Check if the result files have been found
103  if not results:
104  print "Warning: no result file found! (Did you run the tests?)"
105  sys.exit()
106 
107  # parse and collect the summaries
108  # FIXME: (MCl) with QMTest 2.3 we need a test database to be able to run "qmtest summarize", while it
109  # is not needed with QMTest 2.4
110  from tempfile import mkdtemp
111  from shutil import rmtree
112  tmpdir = mkdtemp()
113  origdir = os.getcwd()
114  report = None
115  try:
116  os.chdir(tmpdir)
117  os.popen("qmtest create-tdb","r").read()
118 
119  for r in results:
120  out = os.popen("qmtest summarize -f brief %s"%r,"r").read()
121  rep = parse_summary(out)
122  if report is None:
123  report = rep
124  else:
125  report["results"] += rep["results"]
126  if rep["not_passed"]:
127  report["not_passed"] += rep["not_passed"]
128  for k in rep["statistics"]:
129  if k in report["statistics"]:
130  report["statistics"][k] += rep["statistics"][k]
131  else:
132  report["statistics"][k] = rep["statistics"][k]
133  finally:
134  os.chdir(origdir)
135  rmtree(tmpdir,ignore_errors=True)
136 
137  if report is None:
138  print "Warning: I could not generate the report"
139  sys.exit()
140 
141  # Finalize the report
142  report["results"].append('')
143  if not report["not_passed"]:
144  report["not_passed"] = ['',' None.']
145  report["not_passed"] += ['','']
146 
147  statistics_output = ['--- STATISTICS ---------------------------------------------------------------','']
148  # order: total, FAIL, UNTESTED, PASS
149  #" 2 tests total"
150  tot = report["statistics"]["total"]
151  statistics_output.append("%8d tests total"%(tot))
152  success = True
153  for k in [ "ERROR", "FAIL", "UNTESTED", "PASS" ]:
154  if k in report["statistics"]:
155  n = report["statistics"][k]
156  p = round(100. * n / tot)
157  statistics_output.append("%8d (%3d%%) tests %s"%(n,p,k))
158  if k in ["ERROR", "FAIL"]:
159  success = False
160  statistics_output.append('')
161 
162  results_output = ['--- TEST RESULTS -------------------------------------------------------------']
163  results_output += report["results"]
164 
165  not_passed_output = ['--- TESTS THAT DID NOT PASS --------------------------------------------------']
166  if not report["not_passed"]:
167  not_passed_output
168  not_passed_output += report["not_passed"]
169 
170  output = statistics_output + not_passed_output + results_output + not_passed_output + statistics_output
171  print '\n'.join(output)
172  return success
173 
174 
175 if __name__ == '__main__':
176  if not main():
177  # failure
178  sys.exit(1)