2
0
mirror of https://github.com/boostorg/build.git synced 2026-01-26 18:32:33 +00:00
Files
build/test/BoostBuild.py
Dave Abrahams 2bf1779f95 Bug fixes
[SVN r13693]
2002-05-06 18:54:24 +00:00

348 lines
11 KiB
Python

import TestCmd
from tree import build_tree, trees_difference
import copy
import fnmatch
import os
import shutil
import string
import types
import time
#
# FIXME: this is copy-pasted from TestSCons.py
# Should be moved to TestCmd.py?
#
if os.name == 'posix':
def _failed(self, status = 0):
if self.status is None:
return None
if os.WIFSIGNALED(status):
return None
return _status(self) != status
def _status(self):
if os.WIFEXITED(self.status):
return os.WEXITSTATUS(self.status)
else:
return None
elif os.name == 'nt':
def _failed(self, status = 0):
return not self.status is None and self.status != status
def _status(self):
return self.status
class Tester(TestCmd.TestCmd):
"""Class for testing Boost.Build.
Optional argument `executable` indicates the name of the
executable to invoke. Set this to "jam" to test Boost.Build v1
behavior.
"""
def __init__(self, arguments="", executable = 'bjam', match =
TestCmd.match_exact, boost_build_path = None):
self.original_workdir = os.getcwd()
jam_build_dir = ""
if os.name == 'nt':
jam_build_dir = "bin.ntx86"
elif os.name == 'posix':
jam_build_dir = "bin.linuxx86"
else:
raise "Don't know directory where jam is build for this system"
if boost_build_path is None:
boost_build_path = os.path.join(self.original_workdir, "..", "new")
TestCmd.TestCmd.__init__(
self
, program=os.path.join(
'..', 'jam_src', jam_build_dir, executable)
+ ' -sBOOST_BUILD_PATH=' + boost_build_path
+ ' -d0 --debug --quiet'
+ ' ' + arguments
, match=match
, workdir='')
os.chdir(self.workdir)
#
# Methods that change working directory's content
#
def set_tree(self, tree_location):
# Seem like it's not possible to remove a directory which is
# current.
d = os.getcwd()
os.chdir(os.path.dirname(self.workdir))
shutil.rmtree(self.workdir, ignore_errors=0)
if not os.path.isabs(tree_location):
tree_location = os.path.join(self.original_workdir, tree_location)
shutil.copytree(tree_location, self.workdir)
os.chdir(d)
def make_writable(unused, dir, entries):
for e in entries:
name = os.path.join(dir, e)
os.chmod(name, os.stat(name)[0] | 0222)
os.path.walk(".", make_writable, None)
def write(self, file, content):
try:
os.makedirs(os.path.dirname(file))
except:
pass
open(self.native_file_name(file), "wb").write(content)
def copy(self, src, dst):
self.write(dst, self.read(src))
def touch(self, names):
if not type(names) == types.ListType:
names = [names]
for name in names:
os.utime(self.native_file_name(name), None)
#
# FIXME: Large portion copied from TestSCons.py, should be moved?
#
def run_build_system(
self, extra_args='', subdir='', stdout = None, stderr = '',
status = 0, match = None, **kw):
self.previous_tree = build_tree(self.workdir)
if match is None:
match = self.match
try:
kw['program'] = self.program + ' ' + extra_args
kw['chdir'] = subdir
apply(TestCmd.TestCmd.run, [self], kw)
except:
print "STDOUT ============"
print self.stdout()
print "STDERR ============"
print self.stderr()
raise
if status != None and _failed(self, status):
expect = ''
if status != 0:
expect = " (expected %d)" % status
print '"%s %s" returned %d%s' % (
self.program, extra_args, _status(self), expect)
print "STDOUT ============"
print self.stdout()
print "STDERR ============"
print self.stderr()
self.fail_test(1)
if not stdout is None and not match(self.stdout(), stdout):
print "Expected STDOUT =========="
print stdout
print "Actual STDOUT ============"
print self.stdout()
stderr = self.stderr()
if stderr:
print "STDERR ==================="
print stderr
self.fail_test(1)
if not stderr is None and not match(self.stderr(), stderr):
print "STDOUT ==================="
print self.stdout()
print "Expected STDERR =========="
print stderr
print "Actual STDERR ============"
print self.stderr()
self.fail_test(1)
self.tree = build_tree(self.workdir)
self.difference = trees_difference(self.previous_tree, self.tree)
self.unexpected_difference = copy.deepcopy(self.difference)
# We want to assure that modifications to the working dir will be
# detected by jam, so we wait till current time becomes more that
# the time when the last target was built.
time.sleep(1.1)
def read(self, name):
return open(self.native_file_name(name), "rb").read()
# A number of methods below check expectations with actual difference
# between directory trees before and after build.
# All the 'expect*' methods require exact names to be passed.
# All the 'ignore*' methods allow wildcards.
# All names can be lists, which are taken to be directory components
def expect_addition(self, names):
if type(names) == types.StringType:
names = [names]
for name in names:
try:
self.unexpected_difference.added_files.remove(name)
except:
print "File %s not added as expected" % (name,)
self.fail_test(1)
def ignore_addition(self, wildcard):
ignore_elements(self.unexpected_difference.added_files, wildcard)
def expect_removal(self, names):
if type(names) == types.StringType:
names = [names]
for name in names:
try:
self.unexpected_difference.removed_files.remove(name)
except:
print "File %s not removed as expected" % (name,)
self.fail_test(1)
def ignore_removal(self, wildcard):
ignore_elements(self.unexpected_difference.removed_files, wildcard)
def expect_modification(self, names):
if type(names) == types.StringType:
names = [names]
for name in names:
try:
self.unexpected_difference.modified_files.remove(name)
except:
print "File %s not modified as expected" % (name,)
self.fail_test(1)
def ignore_modification(self, wildcard):
ignore_elements(self.unexpected_difference.modified_files, wildcard)
def expect_touch(self, names):
if type(names) == types.StringType:
names = [names]
for name in names:
try:
self.unexpected_difference.touched_files.remove(name)
except:
print "File %s not touched as expected" % (name,)
self.fail_test(1)
def ignore_touch(self, wildcard):
ignore_elements(self.unexpected_difference.touched_files, wildcard)
def ignore(self, wildcard):
ignore_elements(self.unexpected_difference.added_files, wildcard)
ignore_elements(self.unexpected_difference.removed_files, wildcard)
ignore_elements(self.unexpected_difference.modified_files, wildcard)
ignore_elements(self.unexpected_difference.touched_files, wildcard)
def expect_nothing(self, names):
if type(names) == types.StringType:
names = [names]
for name in names:
if name in self.difference.added_files:
print "File %s is added, but no action was expected" % (name,)
self.fail_test(1)
if name in self.difference.removed_files:
print "File %s is removed, but no action was expected" % (name,)
self.fail_test(1)
pass
if name in self.difference.modified_files:
print "File %s is modified, but no action was expected" % (name,)
self.fail_test(1)
if name in self.difference.touched_files:
print "File %s is touched, but no action was expected" % (name,)
self.fail_test(1)
def expect_nothing_more(self):
if not self.unexpected_difference.empty():
self.fail_test(1)
# Helpers
def mul(self, *arguments):
if len(arguments) == 0:
return None
else:
here = arguments[0]
if type(here) == type(''):
here = [here]
if len(arguments) > 1:
there = apply(self.mul, arguments[1:])
result = []
for i in here:
for j in there:
result.append(i + j)
return result
else:
return here
# Internal methods
def ignore_elements(list, wildcard):
"""Removes in-place, element of 'list' that match the given wildcard."""
w = fnmatch.translate(wildcard)
list[:] = filter(lambda x, w=w: not w(x), list)
def native_file_name(self, name):
elements = string.split(name, "/")
return apply(os.path.join, [self.workdir]+elements)
class List:
def __init__(self, s=""):
# Have to handle espaced spaces correctly
s = string.replace(s, "\ ", '\001')
self.l = []
for e in string.split(s):
self.l.append(string.replace(e, '\001', ' '))
def __len__(self):
return len(l)
def __getitem__(self, key):
return self.l[key]
def __setitem__(self, key, value):
self.l[key] = value
def __delitem__(self, key):
del self.l[key]
def __coerce__(self, other):
if isinstance(other, type("")):
return (self,List(other))
else:
return None
def __str__(self):
return str(self.l)
def __repr__(self):
return ( self.__module__ + '.List('
+ repr(string.join(self.l, ' '))
+ ')')
def __mul__(self, other):
result = List()
for f in self:
for s in other:
result.l.append(f + s)
return result
# quickie tests. Should use doctest instead.
if __name__ == '__main__':
assert str(List("foo bar") * "/baz") == "['foo/baz', 'bar/baz']"
assert repr("foo/" * List("bar baz")) == "__main__.List('foo/bar foo/baz')"
print 'tests passed'