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