SF Bug 1284 - QEMU has faulty instruction emulation for VMOV (between two ARM core registers and two single-precision registers)
#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Launch QEMU for SVP with a specified ROM image and core using a COM port for IO
# Uses Python's Popen class for process control.
# Test output is captured by invoking QEMU in -nographic mode. This redirects serial output to stdout which can then be PIPE'd
# using Popen.
# Tests which hang(or crash into the the crash debugger) are detected using a trivial 'watchdog'. IWBN to use e.g. 'select'
# with a timeout, but this won't work on Windoze, which only supports timeout's on sockets. If the watchdog timeouts out QEMU is killed.
# When the test suite runs to (recognizable) completion QEMU is killed. Unfortunately this appears to require an OS specific
# solution. NB unrecognized completion will result in the watchdog killing QEMU.
# QemuTestRunner collects output into LineTimeInfo objects. These record the time at which each line was received. The time can be used as a crude
# measure of how long a test took to execute.
# The raw data gathered from running the tests can be retrieved using GetResults. This returns a list of LineTimeInfo objects.
import sys
mswindows = (sys.platform == "win32")
# import the following so we can kill QEMU
if mswindows:
# import win32api
import signal
else:
import signal
import os
import time
import re
import subprocess
from subprocess import *
from stat import *
import watchdog
__all__ = ["QemuTestRunner"]
class LineTimeInfo(object):
def __init__(self, line, atime):
self.line = line
self.time = atime
def GetLine(self):
return self.line
def GetTime(self):
return self.time
class QemuTestRunner(object):
def __init__(self, qemupath, cpu, rompath, board = 'syborg', endOfTestFn=None, displayp=False, dataFile = None):
"""Create new QemuTestRunner instance."""
self.qemupath = qemupath
self.board = board
self.cpu = cpu
self.rompath = rompath
self.endOfTestFn = endOfTestFn
self.displayp = displayp
#self.cmd = qemupath + " -M syborg -cpu " + cpu + " -kernel " + rompath + " -nographic"
self.cmd = "%s -M %s -cpu %s -kernel %s -nographic" % (qemupath, board, cpu, rompath)
self.endOfTestPattern = re.compile('RUNTESTS: Completed test script')
self.lineTimeInfo = []
self.id = None
self.dataFile = dataFile
self.watchdog = watchdog.WatchDog(900, lambda : self.KillSim())
def Run(self):
self.lineTimeInfo = []
output = False
self.timeStarted = time.gmtime()
self.id = time.strftime("%d-%m%--%Y-%H-%M-%S", self.timeStarted)
if self.dataFile != None:
filename = self.dataFile + "-" + self.GetRunId() + "-data.txt"
self.dataFileName = filename
output = open(filename, 'wb')
p = Popen( self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE )
self.popen = p
stdin = p.stdin
stdout = p.stdout
stop = False
if self.displayp:
print >> sys.stdout, self.cmd
self.watchdog.Start()
try:
while p.poll() == None and not stop:
line = stdout.readline()
atime = time.clock()
self.watchdog.Reset()
if self.displayp and p.returncode == None:
print >> sys.stdout , line
if output and p.returncode == None:
print >> output , line
if p.returncode == None:
self.lineTimeInfo.append(LineTimeInfo(line, atime))
if self.endOfTestFn != None:
stop = self.endOfTestFn(line)
else:
stop = self.EndOfTestp(line)
finally:
self.timeEnded = time.gmtime()
self.watchdog.Stop()
if output:
output.close()
self.testSuiteFinished = stop;
if p.returncode == None:
self.KillSim()
return True
else:
return False
def GetDataFileName(self):
return self.dataFileName
def TestSuiteFinishedp(self):
return self.testSuiteFinished
def EndOfTestp(self, l):
return re.match(self.endOfTestPattern,l) != None
def KillSim(self):
# if mswindows:
# win32api.TerminateProcess(int(self.popen._handle), -1)
# else:
os.kill(slef.popen.pid, signal.SIGKILL)
def GetResults(self):
return self.lineTimeInfo
def GetRomName(self):
return self.rompath
def GetRunId(self):
return self.id
def GetSummary(self):
simStat = os.stat(self.qemupath)
simSummary = "QEMU Executable: %s size: %d creation time: %d\n" % (self.qemupath, simStat[ST_SIZE], simStat[ST_CTIME])
boardSummary ="Board: %s\n" % self.board
cpuSummary = "CPU: %s\n" % self.cpu
romStat = os.stat(self.rompath)
romSummary = "ROM image: %s size: %d creation date: %d\n" % (self.rompath, romStat[ST_SIZE], romStat[ST_CTIME])
timeFormat = "%d-%m%--%Y %H:%M:%S"
startTime = "Start time: " + time.strftime(timeFormat, self.timeStarted) + "\n"
endTime = "End time: " + time.strftime(timeFormat, self.timeEnded) + "\n"
status = "Testsuite did not complete\n"
if self.TestSuiteFinishedp():
status = "Testsuite completed\n"
return simSummary + boardSummary + cpuSummary + romSummary + startTime + endTime + status
def GetReportFileName(self):
return self.GetRomName() + "-" + self.GetRunId() + "-results-summary.txt"
class PseudoRunner(QemuTestRunner):
def __init__(self, input):
#self.qemupath = qemupath
#self.board = board
#self.cpu = cpu
#self.rompath = rompath
#self.endOfTestFn = endOfTestFn
#self.displayp = displayp
#self.cmd = qemupath + " -M syborg -cpu " + cpu + " -kernel " + rompath + " -nographic"
#self.endOfTestPattern = re.compile('RUNTESTS: Completed test script')
self.lineTimeInfo = []
#self.id = None
self.dataFile = input
for line in open(input):
self.lineTimeInfo.append(LineTimeInfo(line, 0))
def GetRomName(self):
return "Unknown"
def GetRunId(self):
return None
def GetSummary(self):
return ""
def GetReportFileName(self):
return "Runtest-Summary.txt"