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