default_version = '1.2.0'
-copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009'
+copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010'
# In the checked-in source, the value of SConsVersion in the following
# line must remain "__ VERSION __" (without the spaces) so the built
kw['program'] = 'scons'
else:
kw['program'] = 'scons.py'
+ elif not os.path.isabs(kw['program']):
+ kw['program'] = os.path.join(self.orig_cwd, kw['program'])
if not kw.has_key('interpreter') and not os.environ.get('SCONS_EXEC'):
kw['interpreter'] = [python, '-tt']
if not kw.has_key('match'):
sconsflags = []
if self.ignore_python_version and deprecated_python_version():
sconsflags = sconsflags + ['--warn=no-python-version']
- sconsflags = sconsflags + ['--warn=no-visual-c-missing']
+ # Provide a way to suppress or provide alternate flags for
+ # TestSCons purposes by setting TESTSCONS_SCONSFLAGS.
+ # (The intended use case is to set it to null when running
+ # timing tests of earlier versions of SCons which don't
+ # support the --warn=no-visual-c-missing warning.)
+ sconsflags = sconsflags + [os.environ.get('TESTSCONS_SCONSFLAGS',
+ '--warn=no-visual-c-missing')]
os.environ['SCONSFLAGS'] = string.join(sconsflags)
try:
result = apply(TestCommon.run, (self,)+args, kw)
kw['match'] = self.match_re_dotall
apply(self.run, [], kw)
+ def option_not_yet_implemented(self, option, arguments=None, **kw):
+ """
+ Verifies expected behavior for options that are not yet implemented:
+ a warning message, and exit status 1.
+ """
+ msg = "Warning: the %s option is not yet implemented\n" % option
+ kw['stderr'] = msg
+ if arguments:
+ # If it's a long option and the argument string begins with '=',
+ # it's of the form --foo=bar and needs no separating space.
+ if option[:2] == '--' and arguments[0] == '=':
+ kw['arguments'] = option + arguments
+ else:
+ kw['arguments'] = option + ' ' + arguments
+ # TODO(1.5)
+ #return self.run(**kw)
+ return apply(self.run, (), kw)
+
def diff_substr(self, expect, actual, prelen=20, postlen=40):
i = 0
for x, y in zip(expect, actual):
import sys
import string
import re
-cmd_opts, args = getopt.getopt(sys.argv[1:], 'io:', [])
+# -w and -z are fake options used in test/QT/QTFLAGS.py
+cmd_opts, args = getopt.getopt(sys.argv[1:], 'io:wz', [])
output = None
impl = 0
opt_string = ''
if opt == '-o': output = open(arg, 'wb')
elif opt == '-i': impl = 1
else: opt_string = opt_string + ' ' + opt
+output.write("/* mymoc.py%s */\\n" % opt_string)
for a in args:
contents = open(a, 'rb').read()
a = string.replace(a, '\\\\', '\\\\\\\\')
impl_arg = 0
impl = None
source = None
+opt_string = ''
for arg in sys.argv[1:]:
if output_arg:
output = open(arg, 'wb')
output_arg = 1
elif arg == "-impl":
impl_arg = 1
+ elif arg[0:1] == "-":
+ opt_string = opt_string + ' ' + arg
else:
if source:
sys.exit(1)
source = open(arg, 'rb')
sourceFile = arg
+output.write("/* myuic.py%s */\\n" % opt_string)
if impl:
output.write( '#include "' + impl + '"\\n' )
includes = re.findall('<include.*?>(.*?)</include>', source.read())
#include "../include/my_qobject.h"
#include <stdio.h>
void my_qt_symbol(const char *arg) {
- printf( arg );
+ fputs( arg, stdout );
}
""")
return [python] + string.split(string.strip(self.stdout()), '\n')
+ def start(self, *args, **kw):
+ """
+ Starts SCons in the test environment.
+
+ This method exists to tell Test{Cmd,Common} that we're going to
+ use standard input without forcing every .start() call in the
+ individual tests to do so explicitly.
+ """
+ if not kw.has_key('stdin'):
+ kw['stdin'] = True
+ return apply(TestCommon.start, (self,) + args, kw)
+
def wait_for(self, fname, timeout=10.0, popen=None):
"""
Waits for the specified file name to exist.
return alt_cpp_suffix
-class Graph:
- def __init__(self, name, units, expression, sort=None):
+class Stat:
+ def __init__(self, name, units, expression, convert=None):
+ if convert is None:
+ convert = lambda x: x
self.name = name
self.units = units
self.expression = re.compile(expression)
- self.sort = sort
-
-GraphList = [
- Graph('TimeSCons-elapsed', 'seconds',
- r'TimeSCons elapsed time:\s+([\d.]+)',
- sort=0),
-
- Graph('memory-initial', 'bytes',
- r'Memory before reading SConscript files:\s+(\d+)'),
- Graph('memory-prebuild', 'bytes',
- r'Memory before building targets:\s+(\d+)'),
- Graph('memory-final', 'bytes',
- r'Memory after building targets:\s+(\d+)'),
-
- Graph('time-sconscript', 'seconds',
- r'Total SConscript file execution time:\s+([\d.]+) seconds'),
- Graph('time-scons', 'seconds',
- r'Total SCons execution time:\s+([\d.]+) seconds'),
- Graph('time-commands', 'seconds',
- r'Total command execution time:\s+([\d.]+) seconds'),
- Graph('time-total', 'seconds',
- r'Total build time:\s+([\d.]+) seconds'),
+ self.convert = convert
+
+StatList = [
+ Stat('memory-initial', 'kbytes',
+ r'Memory before reading SConscript files:\s+(\d+)',
+ convert=lambda s: int(s) / 1024),
+ Stat('memory-prebuild', 'kbytes',
+ r'Memory before building targets:\s+(\d+)',
+ convert=lambda s: int(s) / 1024),
+ Stat('memory-final', 'kbytes',
+ r'Memory after building targets:\s+(\d+)',
+ convert=lambda s: int(s) / 1024),
+
+ Stat('time-sconscript', 'seconds',
+ r'Total SConscript file execution time:\s+([\d.]+) seconds'),
+ Stat('time-scons', 'seconds',
+ r'Total SCons execution time:\s+([\d.]+) seconds'),
+ Stat('time-commands', 'seconds',
+ r'Total command execution time:\s+([\d.]+) seconds'),
+ Stat('time-total', 'seconds',
+ r'Total build time:\s+([\d.]+) seconds'),
]
directory containing the executing script to the temporary
working directory.
"""
- if not kw.has_key('verbose'):
+ self.variables = kw.get('variables')
+ if self.variables is not None:
+ for variable, value in self.variables.items():
+ value = os.environ.get(variable, value)
+ try:
+ value = int(value)
+ except ValueError:
+ try:
+ value = float(value)
+ except ValueError:
+ pass
+ self.variables[variable] = value
+ del kw['variables']
+
+ self.calibrate = os.environ.get('TIMESCONS_CALIBRATE', '0') != '0'
+
+ if not kw.has_key('verbose') and not self.calibrate:
kw['verbose'] = True
+
# TODO(1.5)
#TestSCons.__init__(self, *args, **kw)
apply(TestSCons.__init__, (self,)+args, kw)
The elapsed time to execute each build is printed after
it has finished.
"""
- # TODO(1.5)
- #self.help(*args, **kw)
- #self.full(*args, **kw)
- #self.null(*args, **kw)
- apply(self.help, args, kw)
- apply(self.full, args, kw)
- apply(self.null, args, kw)
+ if not kw.has_key('options') and self.variables:
+ options = []
+ for variable, value in self.variables.items():
+ options.append('%s=%s' % (variable, value))
+ kw['options'] = ' '.join(options)
+ if self.calibrate:
+ # TODO(1.5)
+ #self.calibration(*args, **kw)
+ apply(self.calibration, args, kw)
+ else:
+ self.uptime()
+ # TODO(1.5)
+ #self.help(*args, **kw)
+ #self.full(*args, **kw)
+ #self.null(*args, **kw)
+ apply(self.help, args, kw)
+ apply(self.full, args, kw)
+ apply(self.null, args, kw)
def trace(self, graph, name, value, units, sort=None):
fmt = "TRACE: graph=%s name=%s value=%s units=%s"
sys.stdout.write(line)
sys.stdout.flush()
- def report_traces(self, trace, input):
+ def report_traces(self, trace, stats):
self.trace('TimeSCons-elapsed',
trace,
self.elapsed_time(),
"seconds",
sort=0)
- for graph in GraphList:
- m = graph.expression.search(input)
+ for name, args in stats.items():
+ # TODO(1.5)
+ #self.trace(name, trace, *args)
+ apply(self.trace, (name, trace), args)
+
+ def uptime(self):
+ try:
+ fp = open('/proc/loadavg')
+ except EnvironmentError:
+ pass
+ else:
+ avg1, avg5, avg15 = fp.readline().split(" ")[:3]
+ fp.close()
+ self.trace('load-average', 'average1', avg1, 'processes')
+ self.trace('load-average', 'average5', avg5, 'processes')
+ self.trace('load-average', 'average15', avg15, 'processes')
+
+ def collect_stats(self, input):
+ result = {}
+ for stat in StatList:
+ m = stat.expression.search(input)
if m:
- self.trace(graph.name, trace, m.group(1), graph.units)
+ value = stat.convert(m.group(1))
+ # The dict keys match the keyword= arguments
+ # of the trace() method above so they can be
+ # applied directly to that call.
+ result[stat.name] = {'value':value, 'units':stat.units}
+ return result
def help(self, *args, **kw):
"""
"real work" is done.
"""
kw['options'] = kw.get('options', '') + ' --help'
+ # Ignore the exit status. If the --help run dies, we just
+ # won't report any statistics for it, but we can still execute
+ # the full and null builds.
+ kw['status'] = None
# TODO(1.5)
#self.run(*args, **kw)
apply(self.run, args, kw)
sys.stdout.write(self.stdout())
- self.report_traces('help', self.stdout())
+ stats = self.collect_stats(self.stdout())
+ # Delete the time-commands, since no commands are ever
+ # executed on the help run and it is (or should be) always 0.0.
+ del stats['time-commands']
+ self.report_traces('help', stats)
def full(self, *args, **kw):
"""
#self.run(*args, **kw)
apply(self.run, args, kw)
sys.stdout.write(self.stdout())
- self.report_traces('full', self.stdout())
+ stats = self.collect_stats(self.stdout())
+ self.report_traces('full', stats)
+ # TODO(1.5)
+ #self.trace('full-memory', 'initial', **stats['memory-initial'])
+ #self.trace('full-memory', 'prebuild', **stats['memory-prebuild'])
+ #self.trace('full-memory', 'final', **stats['memory-final'])
+ apply(self.trace, ('full-memory', 'initial'), stats['memory-initial'])
+ apply(self.trace, ('full-memory', 'prebuild'), stats['memory-prebuild'])
+ apply(self.trace, ('full-memory', 'final'), stats['memory-final'])
+
+ def calibration(self, *args, **kw):
+ """
+ Runs a full build of SCons, but only reports calibration
+ information (the variable(s) that were set for this configuration,
+ and the elapsed time to run.
+ """
+ # TODO(1.5)
+ #self.run(*args, **kw)
+ apply(self.run, args, kw)
+ if self.variables:
+ for variable, value in self.variables.items():
+ sys.stdout.write('VARIABLE: %s=%s\n' % (variable, value))
+ sys.stdout.write('ELAPSED: %s\n' % self.elapsed_time())
def null(self, *args, **kw):
"""
kw['arguments'] = '.'
apply(self.up_to_date, (), kw)
sys.stdout.write(self.stdout())
- self.report_traces('null', self.stdout())
+ stats = self.collect_stats(self.stdout())
+ # time-commands should always be 0.0 on a null build, because
+ # no commands should be executed. Remove it from the stats
+ # so we don't trace it, but only if it *is* 0 so that we'll
+ # get some indication if a supposedly-null build actually does
+ # build something.
+ if float(stats['time-commands']['value']) == 0.0:
+ del stats['time-commands']
+ self.report_traces('null', stats)
+ # TODO(1.5)
+ #self.trace('null-memory', 'initial', **stats['memory-initial'])
+ #self.trace('null-memory', 'prebuild', **stats['memory-prebuild'])
+ #self.trace('null-memory', 'final', **stats['memory-final'])
+ apply(self.trace, ('null-memory', 'initial'), stats['memory-initial'])
+ apply(self.trace, ('null-memory', 'prebuild'), stats['memory-prebuild'])
+ apply(self.trace, ('null-memory', 'final'), stats['memory-final'])
def elapsed_time(self):
"""