tools/e32test-driver/qemuruntest.py
author johnathan.white@2718R8BGH51.accenture.com
Mon, 08 Mar 2010 18:45:03 +0000
changeset 46 b6935a90ca64
parent 34 92d87f2e53c2
permissions -rwxr-xr-x
Modify framebuffer and NGA framebuffer to read screen size from board model dtb file. Optimise memory usuage of frame buffer Add example minigui application with hooks to profiler (which writes results to S:\). Modified NGA framebuffer to run its own dfc queue at high priority

#
# 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"