[Proctor-checkins] CVS: Proctor/proctorlib background_runner.py,NONE,1.1
Status: Alpha
Brought to you by:
doughellmann
|
From: Doug H. <dou...@us...> - 2003-05-04 22:35:44
|
Update of /cvsroot/proctor/Proctor/proctorlib
In directory sc8-pr-cvs1:/tmp/cvs-serv424/proctorlib
Added Files:
background_runner.py
Log Message:
New classes to manage proctorbatch execution in the background.
--- NEW FILE: background_runner.py ---
#
# $Id: background_runner.py,v 1.1 2003/05/04 22:35:41 doughellmann Exp $
#
# Copyright 2003 Racemi, Inc.
#
"""Background test runner.
Spawns off a 'proctorbatch' job to run the tests based on its
arguments, and returns a result set with the test results.
"""
#
# Import system modules
#
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
import popen2
import re
#
# Import Local modules
#
#
# Module
#
class TestInfo:
"Collect information about the test."
def __init__(self, name, description):
self.name = name
self.description = description
self.setStatus('NOT RUN')
self.output = ''
return
def setStatus(self, status):
"Set the status of the test."
self.status = status
return
def feed(self, line):
"Feed text to the test output buffer."
self.output = self.output + line
return
def __str__(self):
return '%s - %s\n%s\n' % (self.name, self.status, self.output)
class BackgroundTestRunner:
"""Background test runner.
Spawns off a 'proctorbatch' job to run the tests based on its
arguments, and returns a result set with the test results.
"""
def __init__(self,
inputPaths=[],
progressFunc=None,
runTests=1,
appName='proctorbatch',
appDefaultArgs='--parsable --no-coverage --list',
):
"""Constructor
Parameters
runTests=1 -- Boolean controlling whether tests are actually
run. If false, a list of tests is made available but they
are not executed.
"""
self.input_paths = inputPaths
self.progress_func = progressFunc
self.run_tests = runTests
self.app_name = appName
self.app_default_args = appDefaultArgs
self.test_results = {}
self.test_names = []
self.mode = 'not_running'
return
def getCommand(self):
"Returns a command string to be used for this runner."
if self.run_tests:
run_arg = ''
else:
run_arg = '--no-run'
if self.input_paths:
input_names = ' '.join(self.input_paths)
else:
input_names = ''
command = '%s %s %s %s' % (self.app_name,
self.app_default_args,
run_arg,
input_names,
)
return command
def start(self):
"Begin the tests running."
command = self.getCommand()
self.pipe = popen2.Popen4(command)
self._results_buffer = StringIO()
return
TRANSITIONS = [
(re.compile('^__PROCTOR__ Start list'), 'getting_list'),
(re.compile('^__PROCTOR__ End list'), 'not_running'),
(re.compile('^__PROCTOR__ Start run'), 'running'),
(re.compile('^__PROCTOR__ End run'), 'not_running'),
(re.compile('^__PROCTOR__ Start test'), 'in_test'),
(re.compile('^__PROCTOR__ End test'), 'running'),
(re.compile('^__PROCTOR__ Start results'), 'test_results'),
(re.compile('^__PROCTOR__ End results'), 'in_test'),
(re.compile('^__PROCTOR__ Start progress'), 'progress'),
(re.compile('^__PROCTOR__ End progress'), 'running'),
]
def isStillRunning(self):
"Return true value if the tests are still running, or false if they are done."
poll_results = self.pipe.poll()
#
# Accumulate the entire output buffer
#
incremental_output = self.pipe.fromchild.readline()
self._results_buffer.write(incremental_output)
#
# Do we need to change modes?
#
mode_changed = 0
for pattern, new_mode in self.TRANSITIONS:
if pattern.match(incremental_output):
self.mode = new_mode
mode_changed = 1
break
#
# Deal with this individual line
# using the current mode.
#
if not mode_changed:
handler_name = 'lineHandler_%s' % self.mode
handler = getattr(self, handler_name)
handler(incremental_output)
return (poll_results == -1)
def lineHandler_not_running(self, line):
"No-op"
return
def lineHandler_progress(self, line):
"No-op"
line = line.strip()
if line:
if self.progress_func:
parts = line.split('/')
if len(parts) == 2:
current, total = parts
current = int(current)
total = int(total)
self.progress_func(current, total)
return
def lineHandler_getting_list(self, line):
"Handle one test name in the list."
line_parts = line.split(' ')
test_name = line_parts[0]
self.test_names.append(test_name)
description = ' '.join(line_parts[1:]).strip()
if description and description[0] == '(':
description = description[1:]
if description and description[-1] == '>':
description = description[:-1]
test_info = TestInfo(test_name, description)
self.test_results[test_name] = test_info
return
def lineHandler_running(self, line):
"No-op"
#
# (Re)Set the current test name
#
self._current_test_name = None
line = line.strip()
return
def lineHandler_in_test(self, line):
"Add line to the output buffer for the individual test."
if self._current_test_name is None:
line = line.strip()
if line:
# This is the test name.
self._current_test_name = line
else:
#
# We know the test, so just add
# to its output buffer.
#
test_info = self.test_results[self._current_test_name]
test_info.feed(line)
return
def lineHandler_test_results(self, line):
"Set the result for the test."
line = line.strip()
if line:
test_info = self.test_results[self._current_test_name]
test_info.setStatus(line.strip())
return
def end(self):
"End the tests running."
return
if __name__ == '__main__':
import time
def progress_handler(current, total):
print 'CURRENT_PROGRESS:', ((current * 1.0 / total) * 100)
btr = BackgroundTestRunner(['.'],
progressFunc=progress_handler,
runTests=1,
appName='./proctorbatch',
)
btr.start()
while btr.isStillRunning():
pass
btr.end()
for test_name in btr.test_names:
print btr.test_results[test_name]
|