blob: f603d4002bb20f42af8bb210c2e10859a473b62f [file] [log] [blame]
#!/usr/bin/env python3
"""Runs test within Qemu and Renode simulators."""
import argparse
import os
import re
import sys
import tempfile
import io
import pexpect
parser = argparse.ArgumentParser(
description="Run a springbok test on an simulator.")
parser.add_argument('simulator',
help='Select a simulator',
choices=['renode', 'qemu'])
parser.add_argument('elf',
help='Elf to execute on a simulator')
parser.add_argument('--renode-path',
help="Path to renode simulator")
parser.add_argument('--qemu-path',
help="Path to qemu simulator")
parser.add_argument('--timeout', type=int,
help="Timeout for test", default=1000)
class Simulation: # pylint: disable=too-few-public-methods
""" Base class for simulation """
def __init__(self, simulator_cmd):
self.simulator_cmd = simulator_cmd
self.buffer = io.StringIO()
self.child = None
self.termination_strings = ["main returned", "Exception occurred"]
def run(self, timeout=1000):
""" Run the simulation command and quit the simulation."""
self.child = pexpect.spawn(self.simulator_cmd, encoding='utf-8')
self.child.logfile = self.buffer
self.child.expect(self.termination_strings, timeout=timeout)
self.child.send("\nq\n")
self.child.expect(pexpect.EOF, timeout=timeout)
self.child.close()
self.buffer.seek(0)
return self.buffer.read()
class QemuSimulation(Simulation): # pylint: disable=too-few-public-methods
""" Qemu simulation """
def __init__(self, path, elf):
self.qemu_simulator_cmd = (
"%(sim)s -M springbok -nographic -d springbok -device loader,file=%(elf)s")
self.sim_params = {"sim": path, "elf": elf}
super().__init__(self.qemu_simulator_cmd % self.sim_params)
class RenodeSimulation(Simulation): # pylint: disable=too-few-public-methods
""" Renode Simulation """
def __init__(self, path, elf):
# Get the ROOTDIR path if it exists
self.rootdir = os.environ.get('ROOTDIR', default=None)
if self.rootdir is None:
parser.error("ROOTDIR environment variable not set.")
renode_script = """
path set @%(rootdir)s
$bin=@%(elf)s
include @sim/config/springbok.resc
sysbus.cpu2 PerformanceInMips 2000
emulation SetGlobalQuantum "1"
start
sysbus.vec_controlblock WriteDoubleWord 0xc 0"""
self.script_params = {
"rootdir": self.rootdir,
"elf":elf
}
self.renode_script = renode_script % self.script_params
self.renode_args = [
"mono",
"%s" % path,
'--disable-xwt',
' --console',
'--plain',
]
self.renode_simulator_cmd = " ".join(self.renode_args)
super().__init__(self.renode_simulator_cmd)
def run(self, timeout=120):
file_desc, script_path = tempfile.mkstemp(suffix=".resc")
try:
with os.fdopen(file_desc, 'w') as tmp:
tmp.write(self.renode_script)
tmp.flush()
self.simulator_cmd += " %s" % script_path
test_output = super().run()
finally:
os.remove(script_path)
return test_output
Simulators = {
"qemu": QemuSimulation,
"renode": RenodeSimulation
}
args = parser.parse_args()
simulators_paths = {
"renode": args.renode_path,
"qemu": args.qemu_path
}
def main():
""" Run a test and check for Pass or Fail """
simulator_path = simulators_paths[args.simulator]
if simulator_path is None:
parser.error(
"Must provide path to simulator %s, use argument --%s-path" % (args.simulator,
args.simulator))
simulator_class = Simulators[args.simulator]
simulator = simulator_class(simulator_path, args.elf)
output = simulator.run(timeout=args.timeout)
# mono API generates escape characters at the termination. Need to clean up.
# TODO(hcindyl): Remove this when Renode fix the mono call.
ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
output = ansi_escape.sub("", output)
print(output)
failure_strings = ["FAILED", "Exception occurred"]
if any(x in output for x in failure_strings):
sys.exit(1)
if __name__ == "__main__":
main()