blob: bf322965eca44667cc823c8e2533e94e81113e05 [file] [log] [blame]
Andrew Scullbc7189d2018-08-14 09:35:13 +01001#!/usr/bin/env python
2"""Run tests.
3
4Runs tests on QEMU.
5"""
6
7from __future__ import print_function
8
Andrew Scull3b62f2b2018-08-21 14:26:12 +01009import xml.etree.ElementTree as ET
10
Andrew Scullbc7189d2018-08-14 09:35:13 +010011import argparse
Andrew Scull04502e42018-09-03 14:54:52 +010012import datetime
Andrew Scullbc7189d2018-08-14 09:35:13 +010013import json
14import os
15import re
16import subprocess
17import sys
18
19
20def qemu(hafnium, initrd, args, log):
21 qemu_args = [
22 "timeout", "--foreground", "5s",
23 "./prebuilts/linux-x64/qemu/qemu-system-aarch64", "-M", "virt", "-cpu",
Andrew Scullabcf1fa2018-10-05 17:45:21 +010024 "cortex-a57", "-m", "16M", "-machine", "virtualization=true",
Andrew Scullbc7189d2018-08-14 09:35:13 +010025 "-nographic", "-nodefaults", "-serial", "stdio", "-kernel", hafnium,
26 "-initrd", initrd
27 ]
28 if args:
29 qemu_args += ["-append", args]
30 # Save the log to a file.
31 with open(log, "w") as f:
32 f.write("$ {}\r\n".format(" ".join(qemu_args)))
33 f.flush()
34 subprocess.check_call(qemu_args, stdout=f, stderr=f)
35 # Return that log for processing.
36 with open(log, "r") as f:
37 return f.read()
38
39
40def ensure_dir(path):
41 try:
42 os.makedirs(path)
43 except OSError:
44 if not os.path.isdir(path):
45 raise
46
47
48def hftest_lines(raw):
49 prefix = "[hftest] "
50 return [
51 line[len(prefix):]
52 for line in raw.splitlines()
53 if line.startswith(prefix)
54 ]
55
56
57def Main():
58 parser = argparse.ArgumentParser()
59 parser.add_argument("--out", required=True)
60 parser.add_argument("--initrd", required=True)
61 parser.add_argument("--suite")
62 parser.add_argument("--test")
63 args = parser.parse_args()
64 # Resolve some paths.
65 hafnium = os.path.join(args.out, "hafnium.bin")
66 initrd = os.path.join(args.out, "initrd", args.initrd + ".img")
67 log = os.path.join(args.out, "test_log", args.initrd)
68 ensure_dir(log)
69 print("Logs saved under", log)
Andrew Scull3b62f2b2018-08-21 14:26:12 +010070 log_file = os.path.join(log, "sponge_log.log")
71 with open(log_file, "w") as sponge_log:
72 # Query the tests in the image.
73 out = qemu(hafnium, initrd, "json", os.path.join(log, "json.log"))
74 sponge_log.write(out)
75 sponge_log.write("\r\n\r\n")
76 hftest_json = "\n".join(hftest_lines(out))
77 tests = json.loads(hftest_json)
78 # Run the selected tests.
79 tests_run = 0
80 failures = 0
81 suite_re = re.compile(args.suite or ".*")
82 test_re = re.compile(args.test or ".*")
83 sponge = ET.Element("testsuites")
84 sponge.set("name", args.initrd)
Andrew Scull04502e42018-09-03 14:54:52 +010085 sponge.set(
86 "timestamp",
87 datetime.datetime.now().replace(microsecond=0).isoformat())
Andrew Scull3b62f2b2018-08-21 14:26:12 +010088 for suite in tests["suites"]:
89 if not suite_re.match(suite["name"]):
Andrew Scullbc7189d2018-08-14 09:35:13 +010090 continue
Andrew Scull3b62f2b2018-08-21 14:26:12 +010091 tests_run_from_suite = 0
92 failures_from_suite = 0
93 sponge_suite = ET.SubElement(sponge, "testsuite")
94 sponge_suite.set("name", suite["name"])
95 for test in suite["tests"]:
96 if not test_re.match(test):
97 continue
98 sponge_test = ET.SubElement(sponge_suite, "testcase")
99 sponge_test.set("name", test)
Andrew Scull04502e42018-09-03 14:54:52 +0100100 sponge_test.set("classname", suite['name'])
Andrew Scull3b62f2b2018-08-21 14:26:12 +0100101 sponge_test.set("status", "run")
102 tests_run_from_suite += 1
103 if tests_run_from_suite == 1:
104 print(" SUITE", suite["name"])
105 print(" RUN", test)
106 test_log = os.path.join(log,
107 suite["name"] + "." + test + ".log")
108 out = qemu(hafnium, initrd, "run {} {}".format(
109 suite["name"], test), test_log)
110 sponge_log.write(out)
111 sponge_log.write("\r\n\r\n")
112 hftest_out = hftest_lines(out)
113 if hftest_out[-1] == "PASS":
114 print(" PASS")
115 else:
116 failures_from_suite += 1
117 sponge_failure = ET.SubElement(sponge_test, "failure")
118 # TODO: set a meaningful message and put log in CDATA
119 sponge_failure.set("message", "Test failed")
120 print("[x] FAIL --", test_log)
121 tests_run += tests_run_from_suite
122 failures += failures_from_suite
123 sponge_suite.set("tests", str(tests_run_from_suite))
124 sponge_suite.set("failures", str(failures_from_suite))
125 sponge.set("tests", str(tests_run))
126 sponge.set("failures", str(failures))
127 with open(os.path.join(log, "sponge_log.xml"), "w") as f:
128 ET.ElementTree(sponge).write(f, encoding='utf-8', xml_declaration=True)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100129 # If none were run, this is probably a mistake.
130 if tests_run == 0:
131 print("Error: no tests match")
132 return 10
133 # Exit with 0 on success and 1 if any test failed.
134 if failures:
135 print("[x] FAIL:", failures, "of", tests_run, "tests failed")
136 return 1
137 else:
138 print(" PASS: all", tests_run, "tests passed")
139 return 0
140
141
142if __name__ == "__main__":
143 sys.exit(Main())