• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Gathers output from test runs and create an XML file in JUnit format.
2
3The output files from the individual tests have been written in a directory
4structure like:
5
6  $DIR/joblog  (output from "parallel --joblog joblog")
7  $DIR/logs/1/cpp/stdout
8  $DIR/logs/1/cpp/stderr
9  $DIR/logs/1/csharp/stdout
10  $DIR/logs/1/csharp/stderr
11  $DIR/logs/1/java_jdk7/stdout
12  $DIR/logs/1/java_jdk7/stderr
13  etc.
14
15This script bundles them into a single output XML file so Jenkins can show
16detailed test results.  It runs as the last step before the Jenkins build
17finishes.
18"""
19
20import os
21import sys
22from yattag import Doc
23from collections import defaultdict
24
25
26def readtests(basedir):
27  tests = defaultdict(dict)
28
29  # Sample input (note: separators are tabs).
30  #
31  # Seq	Host	Starttime	Runtime	Send	Receive	Exitval	Signal	Command
32  # 1	:	1456263838.313	0.005	0	0	0	0	echo A
33  with open(basedir + "/joblog") as jobs:
34    firstline = next(jobs)
35    for line in jobs:
36      values = line.split("\t")
37
38      name = values[8].split()[-1]
39      test = tests[name]
40      test["name"] = name
41      test["time"] = values[3]
42
43      exitval = values[6]
44      if int(exitval):
45        # We don't have a more specific message.  User should look at stderr.
46        test["failure"] = "TEST FAILURE"
47      else:
48        test["failure"] = False
49
50  for testname in os.listdir(basedir + "/logs/1"):
51    test = tests[testname]
52
53    with open(basedir + "/logs/1/" + testname + "/stdout") as f:
54      test["stdout"] = f.read()
55
56    with open(basedir + "/logs/1/" + testname + "/stderr") as f:
57      test["stderr"] = f.read()
58
59  # The cpp test is special since it doesn't run under parallel so doesn't show
60  # up in the job log.
61  tests["cpp"]["name"] = "cpp"
62
63  with open(basedir + '/logs/1/cpp/build_time', 'r') as f:
64    tests["cpp"]["time"] = f.read().strip()
65  tests["cpp"]["failure"] = False
66
67  ret = tests.values()
68  ret.sort(key=lambda x: x["name"])
69
70  return ret
71
72
73def genxml(tests):
74  doc, tag, text = Doc().tagtext()
75
76  with tag("testsuites"):
77    with tag("testsuite", name="Protobuf Tests"):
78      for test in tests:
79        with tag("testcase", name=test["name"], classname=test["name"],
80                             time=test["time"]):
81          with tag("system-out"):
82            text(test["stdout"])
83          with tag("system-err"):
84            text(test["stderr"])
85          if test["failure"]:
86            with tag("failure"):
87              text(test["failure"])
88
89  return doc.getvalue()
90
91
92sys.stderr.write("make_test_output.py: writing XML from directory: " +
93                 sys.argv[1] + "\n")
94print(genxml(readtests(sys.argv[1])))
95