diff options
Diffstat (limited to 'test')
101 files changed, 5007 insertions, 844 deletions
diff --git a/test/Actions/addpost-link.py b/test/Actions/addpost-link.py index f97d4a3..0a08cda 100644 --- a/test/Actions/addpost-link.py +++ b/test/Actions/addpost-link.py @@ -32,11 +32,20 @@ This is a test for fix of Issue 1004, reported by Matt Doar and packaged by Gary Oberbrunner. """ +import string + import TestSCons +_python_ = TestSCons._python_ test = TestSCons.TestSCons() +test.write('strip.py', """\ +import string +import sys +print "strip.py: %s" % string.join(sys.argv[1:]) +""") + test.write('SConstruct', """\ env = Environment() @@ -44,10 +53,12 @@ mylib = env.StaticLibrary('mytest', 'test_lib.c') myprog = env.Program('test1.c', LIBPATH = ['.'], - LIBS = ['mytest']) + LIBS = ['mytest'], + OBJSUFFIX = '.obj', + PROGSUFFIX = '.exe') if ARGUMENTS['case']=='2': - AddPostAction(myprog, Action('strip ' + myprog[0].abspath)) -""") + AddPostAction(myprog, Action(r'%(_python_)s strip.py ' + myprog[0].abspath)) +""" % locals()) test.write('test1.c', """\ extern void test_lib_fn(); @@ -69,8 +80,11 @@ test.run(arguments="-Q case=1", stderr=None) test.run(arguments="-Q -c case=1") -test.must_not_exist('test1.o') +test.must_not_exist('test1.obj') test.run(arguments="-Q case=2", stderr=None) +expect = 'strip.py: %s' % test.workpath('test1.exe') +test.fail_test(string.find(test.stdout(), expect) == -1) + test.pass_test() diff --git a/test/Actions/exitstatfunc.py b/test/Actions/exitstatfunc.py new file mode 100644 index 0000000..c52e1f5 --- /dev/null +++ b/test/Actions/exitstatfunc.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that setting exitstatfunc on an Action works as advertised. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +def always_succeed(s): + # Always return 0, which indicates success. + return 0 + +def copy_fail(target, source, env): + content = open(str(source[0]), 'rb').read() + open(str(target[0]), 'wb').write(content) + return 2 + +a = Action(copy_fail, exitstatfunc=always_succeed) +Alias('test1', Command('test1.out', 'test1.in', a)) + +def fail(target, source, env): + return 2 + +t2 = Command('test2.out', 'test2.in', Copy('$TARGET', '$SOURCE')) +AddPostAction(t2, Action(fail, exitstatfunc=always_succeed)) +Alias('test2', t2) +""") + +test.write('test1.in', "test1.in\n") +test.write('test2.in', "test2.in\n") + +test.run(arguments = 'test1') + +test.must_match('test1.out', "test1.in\n") + +test.run(arguments = 'test2') + +test.must_match('test2.out', "test2.in\n") + +test.pass_test() diff --git a/test/Actions/timestamp.py b/test/Actions/timestamp.py new file mode 100644 index 0000000..ee93596 --- /dev/null +++ b/test/Actions/timestamp.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that changing an Action causes rebuilds when using timestamp +signatures. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +env.Decider('timestamp-match') +env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('file.in', "file.in\n") + +test.not_up_to_date(arguments = 'file.out') + +test.write('SConstruct', """\ +def my_copy(target, source, env): + open(str(target[0]), 'w').write(open(str(source[0]), 'r').read()) +env = Environment() +env.Decider('timestamp-match') +env.Command('file.out', 'file.in', my_copy) +""") + +test.not_up_to_date(arguments = 'file.out') + +test.pass_test() diff --git a/test/AddMethod.py b/test/AddMethod.py index ef4a8d0..584ab4c 100644 --- a/test/AddMethod.py +++ b/test/AddMethod.py @@ -36,7 +36,7 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ def foo(self): - return 'foo-' + env['FOO'] + return 'foo-' + self['FOO'] AddMethod(Environment, foo) env = Environment(FOO = '111') @@ -46,14 +46,20 @@ env = Environment(FOO = '222') print env.foo() env.AddMethod(foo, 'bar') -print env.bar() +env['FOO'] = '333' + +e = env.Clone() +e['FOO'] = '444' +print env.bar() +print e.bar() """) expect = """\ foo-111 foo-222 -foo-222 +foo-333 +foo-444 """ test.run(arguments = '-Q -q', stdout = expect) diff --git a/test/Alias/Depends.py b/test/Alias/Depends.py new file mode 100644 index 0000000..b4ea95c --- /dev/null +++ b/test/Alias/Depends.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import sys +import TestSCons +import TestCmd + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons(match=TestCmd.match_re) + +test.subdir('sub1', 'sub2') + +test.write('build.py', r""" +import sys +open(sys.argv[1], 'wb').write(open(sys.argv[2], 'rb').read()) +sys.exit(0) +""") + +test.write('SConstruct', """ +B = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES') +env = Environment() +env['BUILDERS']['B'] = B +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +env.B(target = 'f3.out', source = 'f3.in') +SConscript('sub1/SConscript', "env") +SConscript('sub2/SConscript', "env") + +foo = Alias('foo') +foo2 = env.Alias('foo', ['f2.out', 'sub1']) +assert foo == foo2 +bar = Alias('bar', ['sub2', 'f3.out']) +env.Alias('blat', ['sub2', 'f3.out']) +env.Alias('blat', ['f2.out', 'sub1']) +env.Depends('f1.out', 'bar') + +Alias('a1', 'a1-file.in') +Depends(Alias('a2'), 'a1') +env.B('a2-file.out', 'a2-file.in') +Depends('a2-file.out', 'a2') +""" % locals()) + +test.write(['sub1', 'SConscript'], """ +Import("env") +env.B(target = 'f4.out', source = 'f4.in') +env.B(target = 'f5.out', source = 'f5.in') +env.B(target = 'f6.out', source = 'f6.in') +""") + +test.write(['sub2', 'SConscript'], """ +Import("env") +env.B(target = 'f7.out', source = 'f7.in') +env.B(target = 'f8.out', source = 'f8.in') +env.B(target = 'f9.out', source = 'f9.in') +""") + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") + +test.write(['sub1', 'f4.in'], "sub1/f4.in\n") +test.write(['sub1', 'f5.in'], "sub1/f5.in\n") +test.write(['sub1', 'f6.in'], "sub1/f6.in\n") + +test.write(['sub2', 'f7.in'], "sub2/f7.in\n") +test.write(['sub2', 'f8.in'], "sub2/f8.in\n") +test.write(['sub2', 'f9.in'], "sub2/f9.in\n") + + + +test.run(arguments = 'foo') + +test.must_not_exist(test.workpath('f1.out')) +test.must_exist(test.workpath('f2.out')) +test.must_not_exist(test.workpath('f3.out')) + +test.must_exist(test.workpath('sub1', 'f4.out')) +test.must_exist(test.workpath('sub1', 'f5.out')) +test.must_exist(test.workpath('sub1', 'f6.out')) + +test.must_not_exist(test.workpath('sub2', 'f7.out')) +test.must_not_exist(test.workpath('sub2', 'f8.out')) +test.must_not_exist(test.workpath('sub2', 'f9.out')) + +test.up_to_date(arguments = 'foo') + +test.write(['sub1', 'f5.in'], "sub1/f5.in 2\n") + +test.not_up_to_date(arguments = 'foo') + + + +test.run(arguments = 'f1.out') + +test.must_exist(test.workpath('f1.out')) +test.must_exist(test.workpath('f3.out')) + +test.up_to_date(arguments = 'f1.out') + + + +os.unlink(test.workpath('f2.out')) +os.unlink(test.workpath('f3.out')) + +test.run(arguments = 'blat') + +test.must_exist(test.workpath('f2.out')) +test.must_exist(test.workpath('f3.out')) + +test.write('f3.in', "f3.in 2 \n") + +expect = """.* build.py f3.out f3.in +.* build.py f1.out f1.in +""" + +test.run(arguments = '-Q f1.out', stdout = expect) + +test.up_to_date(arguments = 'f1.out') + + + +test.write('a1-file.in', "a1-file.in\n") +test.write('a2-file.in', "a2-file.in\n") + +test.run(arguments = 'a2-file.out') + +test.must_match(test.workpath('a2-file.out'), "a2-file.in\n") + +test.up_to_date(arguments = 'a2-file.out') + +test.write('a1-file.in', "a1-file.in 2\n") + +test.not_up_to_date(arguments = 'a2-file.out') + + + +test.pass_test() diff --git a/test/BuildDir/errors.py b/test/BuildDir/errors.py index 44096a1..3954f2b 100644 --- a/test/BuildDir/errors.py +++ b/test/BuildDir/errors.py @@ -70,7 +70,6 @@ env = Environment(BUILDERS={'Build':Builder(action=cat)}, # Do some Node test operations to ensure no side-effects cause failures File('file.in').exists() File('file.in').is_derived() -File('file.in').is_pseudo_derived() env.Build('file.out', 'file.in') """) diff --git a/test/Builder/ensure_suffix.py b/test/Builder/ensure_suffix.py new file mode 100644 index 0000000..ee23635 --- /dev/null +++ b/test/Builder/ensure_suffix.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the ensure_suffix argument to causes us to add the suffix +configured for the Builder even if it looks like the target already has +a different suffix. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() + +tbuilder = Builder(action=Copy('$TARGET', '$SOURCE'), + suffix='.dll', + ensure_suffix=True) + +env['BUILDERS']['TBuilder'] = tbuilder + +env.TBuilder("aa.bb.cc.dd","aa.aa.txt") +""") + +test.write('aa.aa.txt', "clean test\n") + +test.run(arguments = '.') + +test.must_match('aa.bb.cc.dd.dll', "clean test\n") + +test.pass_test() diff --git a/test/CacheDir/multiple-targets.py b/test/CacheDir/multiple-targets.py new file mode 100644 index 0000000..77b8f6f --- /dev/null +++ b/test/CacheDir/multiple-targets.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that multiple target files get retrieved from a CacheDir correctly. +""" + +import os.path +import shutil + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('cache') + +test.write('SConstruct', """\ +def touch(env, source, target): + open('foo', 'w').write("") + open('bar', 'w').write("") +CacheDir(r'%s') +env = Environment() +env.Command(['foo', 'bar'], ['input'], touch) +""" % (test.workpath('cache'))) + +test.write('input', "multiple/input\n") + +test.run() + +test.must_exist(test.workpath('foo')) +test.must_exist(test.workpath('bar')) + +test.run(arguments = '-c') + +test.must_not_exist(test.workpath('foo')) +test.must_not_exist(test.workpath('bar')) + +test.run() + +test.must_exist(test.workpath('foo')) +test.must_exist(test.workpath('bar')) + +test.pass_test() diff --git a/test/CacheDir/scanner-target.py b/test/CacheDir/scanner-target.py new file mode 100644 index 0000000..33930d8 --- /dev/null +++ b/test/CacheDir/scanner-target.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the case (reported by Jeff Petkau, bug #694744) where a target +is source for another target with a scanner, which used to cause us +to push the file to the CacheDir after the build signature had already +been cleared (as a sign that the built file should now be rescanned). +""" + +import os.path +import shutil + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('cache') + +test.write('SConstruct', """\ +import SCons + +CacheDir(r'%s') + +def docopy(target,source,env): + data = source[0].get_contents() + f = open(target[0].rfile().get_abspath(), "wb") + f.write(data) + f.close() + +def sillyScanner(node, env, dirs): + print 'This is never called (unless we build file.out)' + return [] + +SillyScanner = SCons.Scanner.Base(function = sillyScanner, skeys = ['.res']) + +env = Environment(tools=[], + SCANNERS = [SillyScanner], + BUILDERS = {}) + +r = env.Command('file.res', 'file.ma', docopy) + +env.Command('file.out', r, docopy) + +# make r the default. Note that we don't even try to build file.out, +# and so SillyScanner never runs. The bug is the same if we build +# file.out, though. +Default(r) +""" % test.workpath('cache')) + +test.write('file.ma', "file.ma\n") + +test.run() + +test.must_not_exist(test.workpath('cache', 'N', 'None')) + +test.pass_test() diff --git a/test/CacheDir/timestamp.py b/test/CacheDir/timestamp.py new file mode 100644 index 0000000..b0d45b6 --- /dev/null +++ b/test/CacheDir/timestamp.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that CacheDir() works even when using timestamp signatures. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +SourceSignatures('timestamp') +TargetSignatures('content') +CacheDir('cache') +Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('file.in', "file.in\n") + +test.run() + +test.must_match('file.out', "file.in\n") + +test.pass_test() diff --git a/test/Configure/clean.py b/test/Configure/clean.py new file mode 100644 index 0000000..5b8e43d --- /dev/null +++ b/test/Configure/clean.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we don't perform Configure context actions when the +-c or --clean options have been specified. +""" + +import string + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConstruct', """\ +env = Environment() +import os +env.AppendENVPath('PATH', os.environ['PATH']) +conf = Configure(env) +r1 = conf.CheckCHeader( 'math.h' ) +r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error +env = conf.Finish() +Export( 'env' ) +SConscript( 'SConscript' ) +""") + +test.write('SConscript', """\ +Import( 'env' ) +env.Program( 'TestProgram', 'TestProgram.c' ) +""") + +test.write('TestProgram.c', """\ +#include <stdio.h> + +int main() { + printf( "Hello\\n" ); +} +""") + +lines = [ + "Checking for C header file math.h... ", + "Checking for C header file no_std_c_header.h... " +] + +unexpected = [] + +test.run(arguments = '-c') + +for line in lines: + if string.find(test.stdout(), line) != -1: + unexpected.append(line) + +if unexpected: + print "Unexpected lines in standard output:" + print string.join(unexpected, '\n') + print "STDOUT ============================================================" + print test.stdout() + test.fail_test() + +test.run(arguments = '--clean') + +for line in lines: + if string.find(test.stdout(), line) != -1: + unexpected.append(line) + +if unexpected: + print "Unexpected lines in standard output:" + print string.join(unexpected, '\n') + print "STDOUT ============================================================" + print test.stdout() + test.fail_test() + +test.pass_test() diff --git a/test/Configure/help.py b/test/Configure/help.py new file mode 100644 index 0000000..f79831c --- /dev/null +++ b/test/Configure/help.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we don't perform Configure context actions when the +-H, -h or --help options have been specified. +""" + +import string + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConstruct', """\ +env = Environment() +import os +env.AppendENVPath('PATH', os.environ['PATH']) +conf = Configure(env) +r1 = conf.CheckCHeader( 'math.h' ) +r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error +env = conf.Finish() +Export( 'env' ) +SConscript( 'SConscript' ) +""") + +test.write('SConscript', """\ +Import( 'env' ) +env.Program( 'TestProgram', 'TestProgram.c' ) +""") + +test.write('TestProgram.c', """\ +#include <stdio.h> + +int main() { + printf( "Hello\\n" ); +} +""") + +lines = [ + "Checking for C header file math.h... ", + "Checking for C header file no_std_c_header.h... " +] + +unexpected = [] + +test.run(arguments = '-H') + +for line in lines: + if string.find(test.stdout(), line) != -1: + unexpected.append(line) + +if unexpected: + print "Unexpected lines in standard output:" + print string.join(unexpected, '\n') + print "STDOUT ============================================================" + print test.stdout() + test.fail_test() + +test.run(arguments = '-h') + +for line in lines: + if string.find(test.stdout(), line) != -1: + unexpected.append(line) + +if unexpected: + print "Unexpected lines in standard output:" + print string.join(unexpected, '\n') + print "STDOUT ============================================================" + print test.stdout() + test.fail_test() + +test.run(arguments = '--help') + +for line in lines: + if string.find(test.stdout(), line) != -1: + unexpected.append(line) + +if unexpected: + print "Unexpected lines in standard output:" + print string.join(unexpected, '\n') + print "STDOUT ============================================================" + print test.stdout() + test.fail_test() + +test.pass_test() diff --git a/test/Copy.py b/test/Copy.py index 4da725e..6659d93 100644 --- a/test/Copy.py +++ b/test/Copy.py @@ -79,6 +79,11 @@ test.write('f11.in', "f11.in\n") test.subdir('d5') test.write(['d5', 'f12.in'], "f12.in\n") +d4_f10_in = os.path.join('d4', 'f10.in') +d4_f11_out = os.path.join('d4', 'f11.out') +d4_f12_out = os.path.join('d4', 'f12.out') +d5_f12_in = os.path.join('d5', 'f12.in') + expect = test.wrap_stdout(read_str = """\ Copy("f1.out", "f1.in") Copy("d2.out", "d2.in") @@ -89,14 +94,14 @@ cat(["bar.out"], ["bar.in"]) Copy("f4.out", "f4.in") Copy("d5.out", "d5.in") Copy("d6.out", "f6.in") -Copy file(s): "f10.in" to "d4/f10.in" -Copy file(s): "f11.in" to "d4/f11.out" -Copy file(s): "d5/f12.in" to "d4/f12.out" +Copy file(s): "f10.in" to "%(d4_f10_in)s" +Copy file(s): "f11.in" to "%(d4_f11_out)s" +Copy file(s): "%(d5_f12_in)s" to "%(d4_f12_out)s" Copy("f7.out", "f7.in") cat(["f8.out"], ["f8.in"]) cat(["f9.out"], ["f9.in"]) Copy("f9.out-Copy", "f9.in") -""") +""" % locals()) test.run(options = '-n', arguments = '.', stdout = expect) test.must_not_exist('f1.out') diff --git a/test/Decider/Environment.py b/test/Decider/Environment.py new file mode 100644 index 0000000..989e187 --- /dev/null +++ b/test/Decider/Environment.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify use of an up-to-date Decider method through a construction +environment. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import os.path +env = Environment() +env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +def my_decider(dependency, target, prev_ni): + return os.path.exists('has-changed') +env.Decider(my_decider) +""") + +test.write('file.in', "file.in\n") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + +test.write('has-changed', "\n") + +test.not_up_to_date(arguments = '.') + +test.not_up_to_date(arguments = '.') + +test.unlink('has-changed') + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Decider/MD5-timestamp.py b/test/Decider/MD5-timestamp.py new file mode 100644 index 0000000..d31a2db --- /dev/null +++ b/test/Decider/MD5-timestamp.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify behavior of the MD5-timestamp Decider() setting. +""" + +import os +import stat + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +m = Environment() +m.Decider('MD5-timestamp') +m.Command('content1.out', 'content1.in', Copy('$TARGET', '$SOURCE')) +m.Command('content2.out', 'content2.in', Copy('$TARGET', '$SOURCE')) +m.Command('content3.out', 'content3.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('content1.in', "content1.in 1\n") +test.write('content2.in', "content2.in 1\n") +test.write('content3.in', "content3.in 1\n") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + + + +test.sleep() + +test.write('content1.in', "content1.in 2\n") + +test.touch('content2.in') + +time_content = os.stat('content3.in')[stat.ST_MTIME] +test.write('content3.in', "content3.in 2\n") +test.touch('content3.in', time_content) + +# We should only see content1.out rebuilt. The timestamp of content2.in +# has changed, but its content hasn't, so the follow-on content check says +# to not rebuild it. The content of content3.in has changed, but that's +# masked by the fact that its timestamp is the same as the last run. + +expect = test.wrap_stdout("""\ +Copy("content1.out", "content1.in") +""") + +test.run(arguments = '.', stdout=expect) + +test.up_to_date(arguments = '.') + + + +test.pass_test() diff --git a/test/Decider/Node.py b/test/Decider/Node.py new file mode 100644 index 0000000..b11e223 --- /dev/null +++ b/test/Decider/Node.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify use of an up-to-date Decider method on a Node. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import os.path +file_in = File('file.in') +file_out = File('file.out') +Command(file_out, file_in, Copy('$TARGET', '$SOURCE')) +def my_decider(dependency, target, prev_ni): + return os.path.exists('has-changed') +file_in.Decider(my_decider) +""") + +test.write('file.in', "file.in\n") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + +test.write('has-changed', "\n") + +test.not_up_to_date(arguments = '.') + +test.not_up_to_date(arguments = '.') + +test.unlink('has-changed') + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Decider/default.py b/test/Decider/default.py new file mode 100644 index 0000000..c2886fb --- /dev/null +++ b/test/Decider/default.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify use of a default up-to-date Decider method. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import os.path +Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +def my_decider(dependency, target, prev_ni): + return os.path.exists('has-changed') +Decider(my_decider) +""") + +test.write('file.in', "file.in\n") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + +test.write('has-changed', "\n") + +test.not_up_to_date(arguments = '.') + +test.not_up_to_date(arguments = '.') + +test.unlink('has-changed') + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Decider/mixed.py b/test/Decider/mixed.py new file mode 100644 index 0000000..7a83c74 --- /dev/null +++ b/test/Decider/mixed.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify use of an up-to-date Decider method through a construction +environment. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import os.path +denv = Environment() +env = Environment() +n1_in = File('n1.in') +n2_in = File('n2.in') +n3_in = File('n3.in') +Command( 'ccc.out', 'ccc.in', Copy('$TARGET', '$SOURCE')) +Command( 'n1.out', n1_in, Copy('$TARGET', '$SOURCE')) +denv.Command('ddd.out', 'ddd.in', Copy('$TARGET', '$SOURCE')) +denv.Command('n2.out', n2_in, Copy('$TARGET', '$SOURCE')) +env.Command( 'eee.out', 'eee.in', Copy('$TARGET', '$SOURCE')) +env.Command( 'n3.out', n3_in, Copy('$TARGET', '$SOURCE')) +def default_decider(dependency, target, prev_ni): + return os.path.exists('default-has-changed') +def env_decider(dependency, target, prev_ni): + return os.path.exists('env-has-changed') +def node_decider(dependency, target, prev_ni): + return os.path.exists('node-has-changed') +Decider(default_decider) +env.Decider(env_decider) +n1_in.Decider(node_decider) +n2_in.Decider(node_decider) +n3_in.Decider(node_decider) +""") + +test.write('ccc.in', "ccc.in\n") +test.write('ddd.in', "ddd.in\n") +test.write('eee.in', "eee.in\n") +test.write('n1.in', "n1.in\n") +test.write('n2.in', "n2.in\n") +test.write('n3.in', "n3.in\n") + + + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + + + +test.write('env-has-changed', "\n") + +test.not_up_to_date(arguments = 'eee.out') +test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out') + +test.not_up_to_date(arguments = 'eee.out') +test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out') + +test.unlink('env-has-changed') + + + +test.write('default-has-changed', "\n") + +test.not_up_to_date(arguments = 'ccc.out ddd.out') +test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out') + +test.not_up_to_date(arguments = 'ccc.out ddd.out') +test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out') + +test.unlink('default-has-changed') + + + +test.up_to_date(arguments = '.') + +test.write('node-has-changed', "\n") + +test.not_up_to_date(arguments = 'n1.out n2.out n3.out') +test.up_to_date(arguments = 'ccc.out ddd.out eee.out') + +test.not_up_to_date(arguments = 'n1.out n2.out n3.out') +test.up_to_date(arguments = 'ccc.out ddd.out eee.out') + +test.unlink('node-has-changed') + + + +test.pass_test() diff --git a/test/Decider/timestamp.py b/test/Decider/timestamp.py new file mode 100644 index 0000000..6975607 --- /dev/null +++ b/test/Decider/timestamp.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify various interactions of the timestamp-match and timestamp-newer +Decider() settings:. +""" + +import os +import stat + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +m = Environment() +m.Decider('timestamp-match') +m.Command('match1.out', 'match1.in', Copy('$TARGET', '$SOURCE')) +m.Command('match2.out', 'match2.in', Copy('$TARGET', '$SOURCE')) +n = Environment() +n.Decider('timestamp-newer') +n.Command('newer1.out', 'newer1.in', Copy('$TARGET', '$SOURCE')) +n.Command('newer2.out', 'newer2.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('match1.in', "match1.in\n") +test.write('match2.in', "match2.in\n") +test.write('newer1.in', "newer1.in\n") +test.write('newer2.in', "newer2.in\n") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + +time_match = os.stat('match2.out')[stat.ST_MTIME] +time_newer = os.stat('newer2.out')[stat.ST_MTIME] + + + +# Now make all the source files newer than (different timestamps from) +# the last time the targets were built, and touch the target files +# of match1.out and newer1.out to see the different effects. + +test.sleep() + +test.touch('match1.in') +test.touch('newer1.in') +test.touch('match2.in') +test.touch('newer2.in') + +test.sleep() + +test.touch('match1.out') +test.touch('newer1.out') + +# We should see both match1.out and match2.out rebuilt, because the +# source file timestamps do not match the last time they were built, +# but only newer2.out rebuilt. newer1.out is *not* rebuilt because +# the actual target file timestamp is, in fact, newer than the +# source file (newer1.in) timestamp. + +expect = test.wrap_stdout("""\ +Copy("match1.out", "match1.in") +Copy("match2.out", "match2.in") +Copy("newer2.out", "newer2.in") +""") + +test.run(arguments = '.', stdout=expect) + +# Now, for the somewhat pathological case, reset the match2.out and +# newer2.out timestamps to the older timestamp when the targets were +# first built. This will cause newer2.out to be rebuilt, because +# the newer1.in timestamp is now newer than the older, reset target +# file timestamp, but match2.out is *not* rebuilt because its source +# file (match2.in) timestamp still exactly matches the timestamp +# recorded when the target file was last built. + +test.touch('match2.out', time_match) +test.touch('newer2.out', time_newer) + +expect = test.wrap_stdout("""\ +Copy("newer2.out", "newer2.in") +""") + +test.run(arguments = '.', stdout=expect) + + + +test.pass_test() diff --git a/test/Decider/unknown.py b/test/Decider/unknown.py new file mode 100644 index 0000000..b6d071d --- /dev/null +++ b/test/Decider/unknown.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the error when the Decider() function is handed an unknown
+function string.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+Decider('fiddle-dee-dee')
+""")
+
+expect = r"""
+scons: \*\*\* Unknown Decider value 'fiddle-dee-dee'
+""" + TestSCons.file_expr
+
+test.run(arguments = '.', status = 2, stderr = expect)
+
+test.pass_test()
diff --git a/test/Delete.py b/test/Delete.py index 138dc95..31febbe 100644 --- a/test/Delete.py +++ b/test/Delete.py @@ -53,14 +53,18 @@ env.Command('f8.out', 'f8.in', [Delete("$FILE"), Delete("$DIR"), Cat]) env.Command('f9.out', 'f9.in', [Cat, Delete("Delete-$SOURCE"), Delete("$TARGET-Delete")]) -env.Command('f10-nonexistent.out', 'f10.in', [Delete("$TARGET"), - Cat]) -env.Command('d11-nonexistent.out', 'd11.in', [Delete("$TARGET"), - Mkdir("$TARGET")]) -env.Command('f12-nonexistent.out', 'f12.in', [Delete("$TARGET", must_exist=0), - Cat]) -env.Command('d13-nonexistent.out', 'd13.in', [Delete("$TARGET", must_exist=0), - Mkdir("$TARGET")]) + +env.Command('f10-nonexistent.out', 'f10.in', + [Delete("$TARGET"), Cat]) + +env.Command(Dir('d11-nonexistent.out'), 'd11.in', + [Delete("$TARGET"), Mkdir("$TARGET")]) + +env.Command('f12-nonexistent.out', 'f12.in', + [Delete("$TARGET", must_exist=0), Cat]) + +env.Command(Dir('d13-nonexistent.out'), 'd13.in', + [Delete("$TARGET", must_exist=0), Mkdir("$TARGET")]) """) test.write('f1', "f1\n") diff --git a/test/Depends.py b/test/Depends.py index d0b2199..4870739 100644 --- a/test/Depends.py +++ b/test/Depends.py @@ -143,6 +143,9 @@ file2 = File('file2') env.Depends(file1, [[file2, 'file3']]) """) +test.write('file2', "file2\n") +test.write('file3', "file3\n") + test.up_to_date(arguments = '.') test.pass_test() diff --git a/test/Dir/source.py b/test/Dir/source.py index fa07a88..9852660 100644 --- a/test/Dir/source.py +++ b/test/Dir/source.py @@ -165,8 +165,6 @@ test.up_to_date(arguments='cmd-csig-noscan.out') test.write('junk.txt', 'junk.txt 2\n') test.not_up_to_date(arguments='bsig.out') -# XXX For some reason, 'csig' is still reported as up to date. -# XXX Comment out this test until someone can look at it. -#test.not_up_to_date(arguments='csig.out') +test.not_up_to_date(arguments='csig.out') test.pass_test() diff --git a/test/Errors/preparation.py b/test/Errors/preparation.py index 3f98894..9857f99 100644 --- a/test/Errors/preparation.py +++ b/test/Errors/preparation.py @@ -35,19 +35,18 @@ import TestSCons test = TestSCons.TestSCons() -install = test.workpath('install') -install_file = test.workpath('install', 'file') -work_file = test.workpath('work', 'file') +work_file_out = test.workpath('work', 'file.out') test.subdir('install', 'work') test.write(['work', 'SConstruct'], """\ -Alias("install", Install(r"%(install)s", File('file'))) +file_out = Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +Alias("install", file_out) # Make a directory where we expect the File() to be. This causes an # IOError or OSError when we try to open it to read its signature. import os -os.mkdir(r'%(work_file)s') +os.mkdir('file.in') """ % locals()) if sys.platform == 'win32': @@ -56,7 +55,7 @@ else: error_message = "Is a directory" expect = """\ -scons: *** [%(install_file)s] %(work_file)s: %(error_message)s +scons: *** [install] %(work_file_out)s: %(error_message)s """ % locals() test.run(chdir = 'work', diff --git a/test/Install/Install.py b/test/Install/Install.py index f7f8e26..6d44c45 100644 --- a/test/Install/Install.py +++ b/test/Install/Install.py @@ -91,18 +91,18 @@ test.write(['work', 'sub', 'f4.in'], "sub/f4.in\n") test.write(f5_txt, "f5.txt\n") test.write(f6_txt, "f6.txt\n") -test.run(chdir = 'work', arguments = '--debug=stacktrace .') +test.run(chdir = 'work', arguments = '.') -test.fail_test(test.read(f1_out) != "f1.in\n") -test.fail_test(test.read(f2_out) != "f2.in\n") -test.fail_test(test.read(f3_out) != "f3.in\n") -test.fail_test(test.read(f4_out) != "sub/f4.in\n") -test.fail_test(test.read(['work', 'f5.txt']) != "f5.txt\n") -test.fail_test(test.read(['work', 'export', 'f5.txt']) != "f5.txt\n") -test.fail_test(test.read(['work', 'f6.txt']) != "f6.txt\n") -test.fail_test(test.read(['work', 'export', 'f6.txt']) != "f6.txt\n") +test.must_match(f1_out, "f1.in\n") +test.must_match(f2_out, "f2.in\n") +test.must_match(f3_out, "f3.in\n") +test.must_match(f4_out, "sub/f4.in\n") +test.must_match(['work', 'f5.txt'], "f5.txt\n") +test.must_match(['work', 'export', 'f5.txt'], "f5.txt\n") +test.must_match(['work', 'f6.txt'], "f6.txt\n") +test.must_match(['work', 'export', 'f6.txt'], "f6.txt\n") -test.fail_test(test.read(['work', 'my_install.out']) != os.path.join('export', 'f3.out')) +test.must_match(['work', 'my_install.out'], os.path.join('export', 'f3.out')) # make sure the programs didn't get rebuilt, because nothing changed: oldtime1 = os.path.getmtime(f1_out) @@ -119,7 +119,7 @@ test.fail_test(oldtime2 != os.path.getmtime(f2_out)) # Verify that we didn't link to the Installed file. open(f2_out, 'wb').write("xyzzy\n") -test.fail_test(test.read(['work', 'f2.out']) != "f2.in\n") +test.must_match(['work', 'f2.out'], "f2.in\n") # Verify that scons prints an error message # if a target can not be unlinked before building it: diff --git a/test/Install/tool.py b/test/Install/tool.py new file mode 100644 index 0000000..4f09b73 --- /dev/null +++ b/test/Install/tool.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we can still call Install() and InstallAs() even when +no Tool modules have been loaded. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('iii') + +test.write('SConstruct', """ +env = Environment(tools = []) +env.Install('iii', 'foo.in') +env.InstallAs('foo.out', 'foo.in') +""") + +test.write('foo.in', "foo.in\n") + +test.run(arguments = '.') + +test.must_match(['iii', 'foo.in'], "foo.in\n") +test.must_match('foo.out', "foo.in\n") + +test.pass_test() diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py new file mode 100644 index 0000000..7723224 --- /dev/null +++ b/test/Java/JAVABOOTCLASSPATH.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that use of $JAVABOOTCLASSPATH sets the -bootclasspath option +on javac compilations. +""" + +import os +import string + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +ENV = test.java_ENV() + +if test.detect_tool('javac', ENV=ENV): + where_javac = test.detect('JAVAC', 'javac', ENV=ENV) +else: + where_javac = test.where_is('javac') +if not where_javac: + test.skip_test("Could not find Java javac, skipping test(s).\n") + +if test.detect_tool('javah', ENV=ENV): + where_javah = test.detect('JAVAH', 'javah', ENV=ENV) +else: + where_javah = test.where_is('javah') +if not where_javah: + test.skip_test("Could not find Java javah, skipping test(s).\n") + +test.write('SConstruct', """ +env = Environment(tools = ['javac', 'javah'], + JAVAC = r'%(where_javac)s', + JAVABOOTCLASSPATH = ['dir1', 'dir2']) +j1 = env.Java(target = 'class', source = 'com/Example1.java') +j2 = env.Java(target = 'class', source = 'com/Example2.java') +""" % locals()) + +test.subdir('com') + +test.write(['com', 'Example1.java'], """\ +package com; + +public class Example1 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'Example2.java'], """\ +package com; + +public class Example2 +{ + + public static void main(String[] args) + { + + } + +} +""") + +# Setting -bootclasspath messes with the Java runtime environment, so +# we'll just take the easy way out and examine the -n output to see if +# the expected option shows up on the command line. + +bootclasspath = string.join(['dir1', 'dir2'], os.pathsep) + +expect = """\ +%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example1.java +%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example2.java +""" % locals() + +test.run(arguments = '-Q -n .', stdout = expect) + +test.pass_test() diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index 1b69838..d185b4d 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -43,6 +43,13 @@ else: if not where_javac: test.skip_test("Could not find Java javac, skipping test(s).\n") +if test.detect_tool('javah', ENV=ENV): + where_javah = test.detect('JAVAH', 'javah', ENV=ENV) +else: + where_javah = test.where_is('javah') +if not where_javah: + test.skip_test("Could not find Java javah, skipping test(s).\n") + swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') @@ -70,7 +77,9 @@ test.subdir(['src'], test.write(['SConstruct'], """\ import os,sys -env=Environment(tools = ['default', 'javac', 'javah']) +env=Environment(tools = ['default', 'javac', 'javah'], + JAVAC = r'%(where_javac)s', + JAVAH = r'%(where_javah)s') Export('env') env.PrependENVPath('PATH',os.environ.get('PATH',[])) env['INCPREFIX']='-I' @@ -94,7 +103,7 @@ env.SConscript(['buildout/server/JavaSource/SConscript', 'buildout/HelloApplet/SConscript', 'buildout/jni/SConscript', 'buildout/javah/SConscript']) -""") +""" % locals()) test.write(['src', 'HelloApplet', 'Hello.html'], """\ <HTML> @@ -559,9 +568,16 @@ test.must_exist(['buildout', 'jni', 'Sample.class']) test.must_exist(['buildout', 'jni', 'Sample.java']) test.must_exist(['buildout', 'jni', 'SampleJNI.class']) test.must_exist(['buildout', 'jni', 'SampleJNI.java']) -test.must_exist(['buildout', 'jni', 'SampleTest.class']) test.must_exist(['buildout', 'jni', 'SampleTest.java']) +# Some combinations of Java + SWIG apparently don't actually generate +# a SampleTest.class file, while others do. Only issue a warning if +# it doesn't exist. +p = test.workpath('buildout', 'jni', 'SampleTest.class') +import os.path +if not os.path.exists(p): + print 'Warning: %s does not exist' % p + test.up_to_date(arguments = '.') test.pass_test() diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py index c6961f2..8df5e09 100644 --- a/test/Java/swig-dependencies.py +++ b/test/Java/swig-dependencies.py @@ -35,6 +35,7 @@ import TestSCons test = TestSCons.TestSCons() ENV = test.java_ENV() + if test.detect_tool('javac', ENV=ENV): where_javac = test.detect('JAVAC', 'javac', ENV=ENV) else: @@ -42,6 +43,13 @@ else: if not where_javac: test.skip_test("Could not find Java javac, skipping test(s).\n") +if test.detect_tool('javah', ENV=ENV): + where_javah = test.detect('JAVAH', 'javah', ENV=ENV) +else: + where_javah = test.where_is('javah') +if not where_javah: + test.skip_test("Could not find Java javah, skipping test(s).\n") + if test.detect_tool('jar', ENV=ENV): where_jar = test.detect('JAR', 'jar', ENV=ENV) else: @@ -57,7 +65,9 @@ test.subdir(['foo'], test.write(['SConstruct'], """\ import os -env = Environment(ENV = os.environ) +env = Environment(ENV = os.environ, + JAVAC = r'%(where_javac)s', + JAVAH = r'%(where_javah)s') env.Append(CPPFLAGS = ' -g -Wall') @@ -65,7 +75,7 @@ Export('env') SConscript('#foo/SConscript') SConscript('#java/SConscript') -""") +""" % locals()) test.write(['foo', 'SConscript'], """\ Import('env') @@ -123,7 +133,10 @@ env['JARCHDIR'] = 'java/classes' foopack_jar = env.Jar(target = 'foopack.jar', source = 'classes') """) -test.run(arguments = '.') +# Disable looking at stderr because some combinations of SWIG/gcc +# generate a warning about the sWIG_JavaThrowException() function +# being defined but not used. +test.run(arguments = '.', stderr=None) #test.must_exist(['java', 'classes', 'foopack', 'foopack.class']) #test.must_exist(['java', 'classes', 'foopack', 'foopackJNI.class']) diff --git a/test/LIBS.py b/test/LIBS.py index 708ce63..e9f6545 100644 --- a/test/LIBS.py +++ b/test/LIBS.py @@ -272,7 +272,7 @@ test.write(['src', 'component2', 'message2.c'], """\ #include <stdio.h> #include "message1.h" -int DisplayMessage2 (void) +void DisplayMessage2 (void) { DisplayMessage1(); printf ("src/component2/hello.c\\n"); diff --git a/test/MinGW/RCCOM.py b/test/MinGW/RCCOM.py index 2db0563..a272af7 100644 --- a/test/MinGW/RCCOM.py +++ b/test/MinGW/RCCOM.py @@ -29,13 +29,15 @@ Test the ability to configure the $RCCOM construction variable when using MinGW. """ +import sys import TestSCons _python_ = TestSCons._python_ test = TestSCons.TestSCons() - +if sys.platform in ('irix6',): + test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform) test.write('myrc.py', """ import sys diff --git a/test/MinGW/RCCOMSTR.py b/test/MinGW/RCCOMSTR.py index 96565f1..d04c5d6 100644 --- a/test/MinGW/RCCOMSTR.py +++ b/test/MinGW/RCCOMSTR.py @@ -29,13 +29,15 @@ Test that the $RCCOMSTR construction variable allows you to customize the displayed string when rc is called. """ +import sys import TestSCons _python_ = TestSCons._python_ test = TestSCons.TestSCons() - +if sys.platform in ('irix6',): + test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform) test.write('myrc.py', """ import sys diff --git a/test/NodeOps.py b/test/NodeOps.py index 3869228..7e656f7 100644 --- a/test/NodeOps.py +++ b/test/NodeOps.py @@ -32,9 +32,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # However, this should *not* occur during a dryrun (-n). When not # performed during a dryrun, this should not affect buildability. # 2) Calling is_derived() should not affect buildability. -# 3) Calling is_pseudo_derived() may cause the sbuilder to be set, and -# it may caues the builder to be set as well, but it should not -# adversely affect buildability. import sys import TestSCons @@ -73,13 +70,11 @@ SConscript('bld/SConscript', ['Nodes']) if %(_E)s: import os derived = map(lambda N: N.is_derived(), Nodes) - p_derived = map(lambda N: N.is_pseudo_derived(), Nodes) real1 = map(lambda N: os.path.exists(str(N)), Nodes) exists = map(lambda N: N.exists(), Nodes) real2 = map(lambda N: os.path.exists(str(N)), Nodes) - for N,D,P,R,E,F in map(None, Nodes, derived, p_derived, - real1, exists, real2): - print '%%s: %%s %%s %%s %%s %%s'%%(N,D,P,R,E,F) + for N,D,R,E,F in map(None, Nodes, derived, real1, exists, real2): + print '%%s: %%s %%s %%s %%s'%%(N,D,R,E,F) foo.SharedLibrary(target = 'foo', source = 'foo%(_obj)s') bar.SharedLibrary(target = 'bar', source = 'bar%(_obj)s') @@ -147,7 +142,6 @@ def exists_test(node): via_node = node.exists() # side effect causes copy from src after = os.path.exists(str(node)) node.is_derived() - node.is_pseudo_derived() import SCons.Script if GetOption('no_exec'): if (before,via_node,after) != (False,False,False): diff --git a/test/Parallel/duplicate-target.py b/test/Parallel/duplicate-target.py new file mode 100644 index 0000000..5d4f5e1 --- /dev/null +++ b/test/Parallel/duplicate-target.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that, when a file is specified multiple times in a target +list, we still build all of the necessary targets. + +This used to cause a target to "disappear" from the DAG when its reference +count dropped below 0, because we were subtracting the duplicated target +mutiple times even though we'd only visit it once. This was particularly +hard to track down because the DAG itself (when printed with --tree=prune, +for example) doesn't show the duplication in the *target* list. +""" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.subdir('work') + +tar_output = test.workpath('work.tar') + +test.write(['work', 'copy.py'], """\ +import sys +import time +time.sleep(int(sys.argv[1])) +open(sys.argv[2], 'wb').write(open(sys.argv[3], 'rb').read()) +""") + +test.write(['work', 'SConstruct'], """\ +env = Environment() +out1 = File('f1.out') +out2 = File('f2.out') +env.Command([out1, out1], 'f1.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE') +env.Command([out2, out2], 'f2.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE') + +env.Tar(r'%(tar_output)s', Dir('.')) +""" % locals()) + +test.write(['work', 'f1.in'], "work/f1.in\n") +test.write(['work', 'f2.in'], "work/f2.in\n") + +test.run(chdir = 'work', arguments = tar_output + ' -j2') + +test.must_match(['work', 'f1.out'], "work/f1.in\n") +test.must_match(['work', 'f2.out'], "work/f2.in\n") +test.must_exist(tar_output) + +test.pass_test() diff --git a/test/Progress/TARGET.py b/test/Progress/TARGET.py new file mode 100644 index 0000000..e45f859 --- /dev/null +++ b/test/Progress/TARGET.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify substition of the $TARGET string in progress output, including +overwriting it by setting the overwrite= keyword argument. +""" + +import os +import string + +import TestSCons + +test = TestSCons.TestSCons(universal_newlines=None) + +test.write('SConstruct', """\ +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +Progress('$TARGET\\r', overwrite=True) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect = """\ +S1.in\r \rS1.out\rCopy("S1.out", "S1.in") + \rS2.in\r \rS2.out\rCopy("S2.out", "S2.in") + \rS3.in\r \rS3.out\rCopy("S3.out", "S3.in") + \rS4.in\r \rS4.out\rCopy("S4.out", "S4.in") + \rSConstruct\r \r.\r""" + +if os.linesep != '\n': + expect = string.replace(expect, '\n', os.linesep) + +test.run(arguments = '-Q .', stdout=expect) + +test.pass_test() diff --git a/test/Progress/dots.py b/test/Progress/dots.py new file mode 100644 index 0000000..23b3e72 --- /dev/null +++ b/test/Progress/dots.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test expected behavior of just telling a Progress() object to print +a dot for every visited Node. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +Progress('.') +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect = """\ +..Copy("S1.out", "S1.in") +..Copy("S2.out", "S2.in") +..Copy("S3.out", "S3.in") +..Copy("S4.out", "S4.in") +..""" + +test.run(arguments = '-Q .', stdout=expect) + +test.pass_test() diff --git a/test/Progress/file.py b/test/Progress/file.py new file mode 100644 index 0000000..f0116c0 --- /dev/null +++ b/test/Progress/file.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the file= argument to Progress() allows us to redirect the +progress output. +""" + +import os +import string + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +Progress('stderr: $TARGET\\n', file=open('progress.out', 'w')) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect = """\ +Copy("S1.out", "S1.in") +Copy("S2.out", "S2.in") +Copy("S3.out", "S3.in") +Copy("S4.out", "S4.in") +""" + +test.run(arguments = '-Q .', stdout=expect) + +expect = """\ +stderr: S1.in +stderr: S1.out +stderr: S2.in +stderr: S2.out +stderr: S3.in +stderr: S3.out +stderr: S4.in +stderr: S4.out +stderr: SConstruct +stderr: . +""" + +if os.linesep != '\n': + expect = string.replace(expect, '\n', os.linesep) + +test.must_match('progress.out', expect) + +test.pass_test() diff --git a/test/Progress/function.py b/test/Progress/function.py new file mode 100644 index 0000000..2fcb671 --- /dev/null +++ b/test/Progress/function.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify the behavior of passing our own function to Progress(). +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +import sys +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +def my_progress_function(node, *args, **kw): + sys.stderr.write('mpf: %s\\n' % node) +Progress(my_progress_function) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect_stdout = """\ +Copy("S1.out", "S1.in") +Copy("S2.out", "S2.in") +Copy("S3.out", "S3.in") +Copy("S4.out", "S4.in") +""" + +expect_stderr = """\ +mpf: S1.in +mpf: S1.out +mpf: S2.in +mpf: S2.out +mpf: S3.in +mpf: S3.out +mpf: S4.in +mpf: S4.out +mpf: SConstruct +mpf: . +""" + +test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr) + +test.pass_test() diff --git a/test/Progress/interval.py b/test/Progress/interval.py new file mode 100644 index 0000000..767bf20 --- /dev/null +++ b/test/Progress/interval.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the "interval=" parameter to Progress skips Nodes. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +import sys +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +Progress('stderr: $TARGET\\n', file=sys.stderr, interval=2) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect_stdout = """\ +Copy("S1.out", "S1.in") +Copy("S2.out", "S2.in") +Copy("S3.out", "S3.in") +Copy("S4.out", "S4.in") +""" + +expect_stderr = """\ +stderr: S1.out +stderr: S2.out +stderr: S3.out +stderr: S4.out +stderr: . +""" + +test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr) + +test.pass_test() diff --git a/test/Progress/object.py b/test/Progress/object.py new file mode 100644 index 0000000..4dad1a1 --- /dev/null +++ b/test/Progress/object.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify the behavior of passing a callable object to Progress(). +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +import sys +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +class my_progress: + count = 0 + def __call__(self, node, *args, **kw): + self.count = self.count + 1 + sys.stderr.write('%s: %s\\n' % (self.count, node)) +Progress(my_progress()) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect_stdout = """\ +Copy("S1.out", "S1.in") +Copy("S2.out", "S2.in") +Copy("S3.out", "S3.in") +Copy("S4.out", "S4.in") +""" + +expect_stderr = """\ +1: S1.in +2: S1.out +3: S2.in +4: S2.out +5: S3.in +6: S3.out +7: S4.in +8: S4.out +9: SConstruct +10: . +""" + +test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr) + +test.pass_test() diff --git a/test/Progress/spinner.py b/test/Progress/spinner.py new file mode 100644 index 0000000..c600b67 --- /dev/null +++ b/test/Progress/spinner.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify output when a Progress() call is initialized with the list +that represents a canonical "spinner" on the output. +""" + +import os +import string + +import TestSCons + +test = TestSCons.TestSCons(universal_newlines=None) + +test.write('SConstruct', r""" +env = Environment() +env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE')) +Progress(['-\r', '\\\r', '|\r', '/\r']) +env.C('S1.out', 'S1.in') +env.C('S2.out', 'S2.in') +env.C('S3.out', 'S3.in') +env.C('S4.out', 'S4.in') +""") + +test.write('S1.in', "S1.in\n") +test.write('S2.in', "S2.in\n") +test.write('S3.in', "S3.in\n") +test.write('S4.in', "S4.in\n") + +expect = """\ +\\\r|\rCopy("S1.out", "S1.in") +/\r-\rCopy("S2.out", "S2.in") +\\\r|\rCopy("S3.out", "S3.in") +/\r-\rCopy("S4.out", "S4.in") +\\\r|\r""" + +if os.linesep != '\n': + expect = string.replace(expect, '\n', os.linesep) + +test.run(arguments = '-Q .', stdout=expect) + +test.pass_test() diff --git a/test/QT/installed.py b/test/QT/installed.py index 8cb9ab1..d746d9e 100644 --- a/test/QT/installed.py +++ b/test/QT/installed.py @@ -191,10 +191,11 @@ if test.stdout() != "Hello World\n" or test.stderr() != '' or test.status: # If so, then print whatever it showed us (which is in and of itself # an indication that it built correctly) but don't fail the test. expect = 'cannot connect to X server' - test.fail_test(test.stdout() != '' or - string.find(test.stderr(), expect) == -1 or \ - (test.status>>8) != 1) - + test.fail_test(test.stdout()) + test.fail_test(string.find(test.stderr(), expect) == -1) + if test.status != 1 and (test.status>>8) != 1: + sys.stdout.write('test_realqt returned status %s\n' % test.status) + test.fail_test() QTDIR = os.environ['QTDIR'] PATH = os.environ['PATH'] diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py index 1dbcd0f..2878136 100644 --- a/test/QT/moc-from-header.py +++ b/test/QT/moc-from-header.py @@ -92,7 +92,6 @@ test.must_exist(test.workpath('build', moc)) test.run(arguments = "build_dir=1 chdir=1 dup=0 " + test.workpath('build_dup0', aaa_exe) ) -test.must_exist(['build_dup0', moc], - ['build_dup0', aaa_exe]) +test.must_exist(['build_dup0', moc]) test.pass_test() diff --git a/test/SConscript/Return.py b/test/SConscript/Return.py new file mode 100644 index 0000000..453c0b8 --- /dev/null +++ b/test/SConscript/Return.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the Return() function stops processing the SConscript file +at the point is called, unless the stop= keyword argument is supplied. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +SConscript('SConscript1') +x = SConscript('SConscript2') +y, z = SConscript('SConscript3') +a4, b4 = SConscript('SConscript4') +print "x =", x +print "y =", y +print "z =", z +print "a4 =", a4 +print "b4 =", b4 +""") + +test.write('SConscript1', """\ +print "line 1" +Return() +print "line 2" +""") + +test.write('SConscript2', """\ +print "line 3" +x = 7 +Return('x') +print "line 4" +""") + +test.write('SConscript3', """\ +print "line 5" +y = 8 +z = 9 +Return('y z') +print "line 6" +""") + +test.write('SConscript4', """\ +a4 = 'aaa' +b4 = 'bbb' +print "line 7" +Return('a4', 'b4', stop=False) +b4 = 'b-after' +print "line 8" +""") + +expect = """\ +line 1 +line 3 +line 5 +line 7 +line 8 +x = 7 +y = 8 +z = 9 +a4 = aaa +b4 = bbb +""" + +test.run(arguments = '-q -Q', stdout=expect) + +test.pass_test() diff --git a/test/SWIG/build-dir.py b/test/SWIG/build-dir.py index 593a26a..58ad0cd 100644 --- a/test/SWIG/build-dir.py +++ b/test/SWIG/build-dir.py @@ -37,6 +37,11 @@ import TestSCons test = TestSCons.TestSCons() +swig = test.where_is('swig') + +if not swig: + test.skip_test('Can not find installed "swig", skipping test.\n') + # swig-python expects specific filenames. # the platform specific suffix won't necessarily work. if sys.platform == 'win32': @@ -129,9 +134,6 @@ public: %extend { const char* __str__() { return "linalg.Vector()"; } - int __len__() { return $self->size(); } - double __getitem__(int key) { return $self->operator[](key); } - void __setitem__(int key, double value) { $self->operator[](key) = value; } %pythoncode %{ def __iter__(self): diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py index 2dfd322..dd2c938 100644 --- a/test/Scanner/generated.py +++ b/test/Scanner/generated.py @@ -411,18 +411,17 @@ int g_3() test.run(stderr=TestSCons.noisy_ar, match=TestSCons.match_re_dotall) -# XXX Note that the generated .h files still get scanned twice, -# once before they're generated and once after. That's the -# next thing to fix here. +# Note that the generated .h files still get scanned twice, +# but that's really once each as a child of libg_1.o and libg_2.o. test.must_match("MyCScan.out", """\ libg_1.c: 1 libg_2.c: 1 libg_3.c: 1 -libg_gx.h: 1 +libg_gx.h: 2 libg_gy.h: 1 libg_gz.h: 1 -libg_w.h: 1 +libg_w.h: 2 """) test.pass_test() diff --git a/test/Sig.py b/test/Sig.py new file mode 100644 index 0000000..8565735 --- /dev/null +++ b/test/Sig.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we generate the proper warning, but don't die, when someone +tries to import the SCons.Sig module (which no longer exists) and +use the things we used to define therein. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +SConstruct = test.workpath('SConstruct') + +test.write(SConstruct, """ +import SCons.Sig +x = SCons.Sig.default_calc +x = SCons.Sig.default_module +x = SCons.Sig.MD5.current() +x = SCons.Sig.MD5.collect() +x = SCons.Sig.MD5.signature() +x = SCons.Sig.MD5.to_string() +x = SCons.Sig.MD5.from_string() +x = SCons.Sig.TimeStamp.current() +x = SCons.Sig.TimeStamp.collect() +x = SCons.Sig.TimeStamp.signature() +x = SCons.Sig.TimeStamp.to_string() +x = SCons.Sig.TimeStamp.from_string() +""") + +expect = """ +scons: warning: The SCons.Sig module no longer exists. + Remove the following "import SCons.Sig" line to eliminate this warning: +""" + test.python_file_line(SConstruct, 2) + +test.run(arguments = '.', stderr=expect) + +test.pass_test() diff --git a/test/SourceCode.py b/test/SourceCode.py index 86cc2a6..b74f8b1 100644 --- a/test/SourceCode.py +++ b/test/SourceCode.py @@ -59,7 +59,7 @@ env = Environment(BUILDERS={'Cat':Builder(action=cat)}, SUBDIR='sub') env.SourceCode('$SUBDIR', Builder(action=sc_cat, env=env)) env.Cat('aaa.out', 'sub/aaa.in') bbb_in = File('sub/bbb.in') -bbb_in.is_pseudo_derived() +bbb_in.is_derived() env.Cat('bbb.out', bbb_in) env.Cat('ccc.out', 'sub/ccc.in') env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) diff --git a/test/SourceSignatures.py b/test/SourceSignatures.py deleted file mode 100644 index b85f8ec..0000000 --- a/test/SourceSignatures.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import imp -import os -import os.path -import time - -import TestSCons - -test = TestSCons.TestSCons() - -test.write('SConstruct', """ -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -env.B(target = 'f3.out', source = 'f3.in') -env.B(target = 'f4.out', source = 'f4.in') - -SourceSignatures('timestamp') -""") - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -test.run(arguments = 'f1.out f3.out') - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout("""\ -scons: `f1.out' is up to date. -build(["f2.out"], ["f2.in"]) -scons: `f3.out' is up to date. -build(["f4.out"], ["f4.in"]) -""")) - -os.utime(test.workpath('f1.in'), - (os.path.getatime(test.workpath('f1.in')), - os.path.getmtime(test.workpath('f1.in'))+10)) -os.utime(test.workpath('f3.in'), - (os.path.getatime(test.workpath('f3.in')), - os.path.getmtime(test.workpath('f3.in'))+10)) - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout("""\ -build(["f1.out"], ["f1.in"]) -scons: `f2.out' is up to date. -build(["f3.out"], ["f3.in"]) -scons: `f4.out' is up to date. -""")) - -test.write('SConstruct', """ -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -env.B(target = 'f3.out', source = 'f3.in') -env.B(target = 'f4.out', source = 'f4.in') - -SourceSignatures('MD5') -""") - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -test.run(arguments = 'f1.out f3.out') - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = test.wrap_stdout("""\ -scons: `f1.out' is up to date. -build(["f2.out"], ["f2.in"]) -scons: `f3.out' is up to date. -build(["f4.out"], ["f4.in"]) -""")) - -os.utime(test.workpath('f1.in'), - (os.path.getatime(test.workpath('f1.in')), - os.path.getmtime(test.workpath('f1.in'))+10)) -os.utime(test.workpath('f3.in'), - (os.path.getatime(test.workpath('f3.in')), - os.path.getmtime(test.workpath('f3.in'))+10)) - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') - -test.write('SConstruct', """ -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -env.B(target = 'f3.out', source = 'f3.in') -env.B(target = 'f4.out', source = 'f4.in') -""") - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') - -test.write('SConstruct', """ -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env2 = env.Clone() -env2.SourceSignatures('MD5') -env.B(target = 'f5.out', source = 'f5.in') -env.B(target = 'f6.out', source = 'f6.in') -env2.B(target = 'f7.out', source = 'f7.in') -env2.B(target = 'f8.out', source = 'f8.in') - -SourceSignatures('timestamp') -""") - -test.write('f5.in', "f5.in\n") -test.write('f6.in', "f6.in\n") -test.write('f7.in', "f7.in\n") -test.write('f8.in', "f8.in\n") - -test.run(arguments = 'f5.out f7.out') - -test.run(arguments = 'f5.out f6.out f7.out f8.out', - stdout = test.wrap_stdout("""\ -scons: `f5.out' is up to date. -build(["f6.out"], ["f6.in"]) -scons: `f7.out' is up to date. -build(["f8.out"], ["f8.in"]) -""")) - -os.utime(test.workpath('f5.in'), - (os.path.getatime(test.workpath('f5.in')), - os.path.getmtime(test.workpath('f5.in'))+10)) -os.utime(test.workpath('f7.in'), - (os.path.getatime(test.workpath('f7.in')), - os.path.getmtime(test.workpath('f7.in'))+10)) - -test.run(arguments = 'f5.out f6.out f7.out f8.out', - stdout = test.wrap_stdout("""\ -build(["f5.out"], ["f5.in"]) -scons: `f6.out' is up to date. -scons: `f7.out' is up to date. -scons: `f8.out' is up to date. -""")) - -test.up_to_date(arguments = 'f5.out f6.out f7.out f8.out') - -# Ensure that switching signature types causes a rebuild: -test.write('SConstruct', """ -SourceSignatures('MD5') - -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'switch.out', source = 'switch.in') -""") - -test.write('switch.in', "switch.in\n") - -switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n') - -test.run(arguments = 'switch.out', stdout = switch_out_switch_in) - -test.up_to_date(arguments = 'switch.out') - -test.write('SConstruct', """ -SourceSignatures('timestamp') - -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'switch.out', source = 'switch.in') -""") - -test.run(arguments = 'switch.out', stdout = switch_out_switch_in) - -test.up_to_date(arguments = 'switch.out') - -test.write('SConstruct', """ -SourceSignatures('MD5') - -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'switch.out', source = 'switch.in') -""") - -test.run(arguments = 'switch.out', stdout = switch_out_switch_in) - -test.up_to_date(arguments = 'switch.out') - -test.write('switch.in', "switch.in 2\n") - -test.run(arguments = 'switch.out', stdout = switch_out_switch_in) - - -# Test both implicit_cache and timestamp signatures at the same time: -test.write('SConstruct', """ -SetOption('implicit_cache', 1) -SourceSignatures('timestamp') - -def build(env, target, source): - open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'both.out', source = 'both.in') -""") - -test.write('both.in', "both.in 1\n") - -both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n') - -test.run(arguments = 'both.out', stdout = both_out_both_in) - -time.sleep(2) - -test.write('both.in', "both.in 2\n") - -test.run(arguments = 'both.out', stdout = both_out_both_in) - -time.sleep(2) - -test.write('both.in', "both.in 3\n") - -test.run(arguments = 'both.out', stdout = both_out_both_in) - -time.sleep(2) - -test.write('both.in', "both.in 4\n") - -test.run(arguments = 'both.out', stdout = both_out_both_in) - -time.sleep(2) - -test.up_to_date(arguments = 'both.out') - -test.pass_test() diff --git a/test/SourceSignatures/basic.py b/test/SourceSignatures/basic.py new file mode 100644 index 0000000..7042fac --- /dev/null +++ b/test/SourceSignatures/basic.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import os.path + +import TestSCons + +test = TestSCons.TestSCons() + + + +base_sconstruct_contents = """\ +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +env.B(target = 'f3.out', source = 'f3.in') +env.B(target = 'f4.out', source = 'f4.in') +""" + +def write_SConstruct(test, sigtype): + contents = base_sconstruct_contents + if sigtype: + contents = contents + ("\nSourceSignatures('%s')\n" % sigtype) + test.write('SConstruct', contents) + + + +write_SConstruct(test, 'timestamp') + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.run(arguments = 'f1.out f3.out') + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = test.wrap_stdout("""\ +scons: `f1.out' is up to date. +build(["f2.out"], ["f2.in"]) +scons: `f3.out' is up to date. +build(["f4.out"], ["f4.in"]) +""")) + + + +os.utime(test.workpath('f1.in'), + (os.path.getatime(test.workpath('f1.in')), + os.path.getmtime(test.workpath('f1.in'))+10)) +os.utime(test.workpath('f3.in'), + (os.path.getatime(test.workpath('f3.in')), + os.path.getmtime(test.workpath('f3.in'))+10)) + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = test.wrap_stdout("""\ +build(["f1.out"], ["f1.in"]) +scons: `f2.out' is up to date. +build(["f3.out"], ["f3.in"]) +scons: `f4.out' is up to date. +""")) + + + +# Switching to content signatures from timestamps should rebuild, +# because we didn't record the content signatures last time. + +write_SConstruct(test, 'MD5') + +test.not_up_to_date(arguments = 'f1.out f2.out f3.out f4.out') + + + +test.sleep() + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') + + + +test.touch('f1.in', os.path.getmtime(test.workpath('f1.in'))+10) +test.touch('f3.in', os.path.getmtime(test.workpath('f3.in'))+10) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') + + + +write_SConstruct(test, None) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') + + + +test.pass_test() diff --git a/test/SourceSignatures/env.py b/test/SourceSignatures/env.py new file mode 100644 index 0000000..3bef2a6 --- /dev/null +++ b/test/SourceSignatures/env.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that use of env.SourceSignatures() correctly overrides the +default behavior. +""" + +import os +import os.path + +import TestSCons + +test = TestSCons.TestSCons() + +base_sconstruct_contents = """\ +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env2 = env.Copy() +env2.SourceSignatures('%s') +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +env2.B(target = 'f3.out', source = 'f3.in') +env2.B(target = 'f4.out', source = 'f4.in') + +SourceSignatures('%s') +""" + +def write_SConstruct(test, env_sigtype, default_sigtype): + contents = base_sconstruct_contents % (env_sigtype, default_sigtype) + test.write('SConstruct', contents) + + + +write_SConstruct(test, 'MD5', 'timestamp') + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.run(arguments = 'f1.out f3.out') + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = test.wrap_stdout("""\ +scons: `f1.out' is up to date. +build(["f2.out"], ["f2.in"]) +scons: `f3.out' is up to date. +build(["f4.out"], ["f4.in"]) +""")) + + + +test.sleep() + +test.touch('f1.in') +test.touch('f3.in') + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = test.wrap_stdout("""\ +build(["f1.out"], ["f1.in"]) +scons: `f2.out' is up to date. +scons: `f3.out' is up to date. +scons: `f4.out' is up to date. +""")) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out') + + + +test.pass_test() diff --git a/test/SourceSignatures/implicit-cache.py b/test/SourceSignatures/implicit-cache.py new file mode 100644 index 0000000..de66b72 --- /dev/null +++ b/test/SourceSignatures/implicit-cache.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the simultaneous use of implicit_cache and +SourceSignatures('timestamp') +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +SetOption('implicit_cache', 1) +SourceSignatures('timestamp') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'both.out', source = 'both.in') +""") + +both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n') + + + +test.write('both.in', "both.in 1\n") + +test.run(arguments = 'both.out', stdout = both_out_both_in) + + + +test.sleep(2) + +test.write('both.in', "both.in 2\n") + +test.run(arguments = 'both.out', stdout = both_out_both_in) + + + +test.sleep(2) + +test.write('both.in', "both.in 3\n") + +test.run(arguments = 'both.out', stdout = both_out_both_in) + + + +test.sleep(2) + +test.write('both.in', "both.in 4\n") + +test.run(arguments = 'both.out', stdout = both_out_both_in) + + + +test.sleep(2) + +test.up_to_date(arguments = 'both.out') + + + +test.pass_test() diff --git a/test/SourceSignatures/no-csigs.py b/test/SourceSignatures/no-csigs.py new file mode 100644 index 0000000..3702901 --- /dev/null +++ b/test/SourceSignatures/no-csigs.py @@ -0,0 +1,70 @@ + +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import os.path + +import TestSConsign + +test = TestSConsign.TestSConsign(match = TestSConsign.match_re) + + +test.write('SConstruct', """\ +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +SourceSignatures('timestamp') +""") + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") + +test.run(arguments = '.') + + + +expect = r"""=== .: +SConstruct: None \d+ \d+ +f1.in: None \d+ \d+ +f1.out: \S+ \d+ \d+ + f1.in: None \d+ \d+ + \S+ \[build\(target, source, env\)\] +f2.in: None \d+ \d+ +f2.out: \S+ \d+ \d+ + f2.in: None \d+ \d+ + \S+ \[build\(target, source, env\)\] +""" + +test.run_sconsign(arguments = test.workpath('.sconsign'), + stdout = expect) + + + +test.pass_test() diff --git a/test/SourceSignatures/overrides.py b/test/SourceSignatures/overrides.py new file mode 100644 index 0000000..cf83488 --- /dev/null +++ b/test/SourceSignatures/overrides.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Make sure that SourceSignatures() works when overrides are used on a +Builder call. (Previous implementations used methods that would stay +bound to the underlying construction environment, which in this case +meant ignoring the 'timestamp' setting and still using the underlying +content signature.) +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +DefaultEnvironment().SourceSignatures('MD5') +env = Environment() +env.SourceSignatures('timestamp') +env.Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=1) +""") + +test.write('foo.in', "foo.in 1\n") + +test.run(arguments = 'foo.out') + +test.sleep() + +test.write('foo.in', "foo.in 1\n") + +test.not_up_to_date(arguments = 'foo.out') + +test.pass_test() diff --git a/test/SourceSignatures/switch-rebuild.py b/test/SourceSignatures/switch-rebuild.py new file mode 100644 index 0000000..85c2b22 --- /dev/null +++ b/test/SourceSignatures/switch-rebuild.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that switching SourceSignature() types no longer causes rebuilds. +""" + +import TestSCons + +test = TestSCons.TestSCons() + + +base_sconstruct_contents = """\ +SourceSignatures('%s') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'switch.out', source = 'switch.in') +""" + +def write_SConstruct(test, sig_type): + contents = base_sconstruct_contents % sig_type + test.write('SConstruct', contents) + + +write_SConstruct(test, 'MD5') + +test.write('switch.in', "switch.in\n") + +switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n') + +test.run(arguments = 'switch.out', stdout = switch_out_switch_in) + +test.up_to_date(arguments = 'switch.out') + + + +write_SConstruct(test, 'timestamp') + +test.up_to_date(arguments = 'switch.out') + + + +write_SConstruct(test, 'MD5') + +test.not_up_to_date(arguments = 'switch.out') + + + +test.write('switch.in', "switch.in 2\n") + +test.run(arguments = 'switch.out', stdout = switch_out_switch_in) + + + +test.pass_test() diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py index e189d57..8df2e79 100644 --- a/test/TEX/auxiliaries.py +++ b/test/TEX/auxiliaries.py @@ -141,7 +141,7 @@ if pdf_output_1 != pdf_output_2: import sys test.write(['build', 'docs', 'test.normalized.1.pdf'], pdf_output_1) test.write(['build', 'docs', 'test.normalized.2.pdf'], pdf_output_2) - sys.stdout.write("***** 1 and 2 are different!\n") + sys.stdout.write("***** 1.pdf and 2.pdf are different!\n") sys.stdout.write(test.diff_substr(pdf_output_1, pdf_output_2, 80, 80) + '\n') sys.stdout.write("Output from run 1:\n") sys.stdout.write(test.stdout(-1) + '\n') @@ -150,7 +150,16 @@ if pdf_output_1 != pdf_output_2: sys.stdout.flush() test.fail_test() -assert ps_output_1 == ps_output_2, test.diff_substr(ps_output_1, ps_output_2, 80, 80) +if ps_output_1 != ps_output_2: + import sys + sys.stdout.write("***** 1.ps and 2.ps are different!\n") + sys.stdout.write(test.diff_substr(ps_output_1, ps_output_2, 80, 80) + '\n') + sys.stdout.write("Output from run 1:\n") + sys.stdout.write(test.stdout(-1) + '\n') + sys.stdout.write("Output from run 2:\n") + sys.stdout.write(test.stdout() + '\n') + sys.stdout.flush() + test.fail_test() diff --git a/test/TEX/clean.py b/test/TEX/clean.py new file mode 100644 index 0000000..6615fc9 --- /dev/null +++ b/test/TEX/clean.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Check that all auxilary files created by LaTeX are properly cleaned by scons -c. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +latex = test.where_is('latex') + +if not latex: + test.skip_test("Could not find tex or latex; skipping test(s).\n") + +# package hyperref generates foo.out +# package comment generates comment.cut +# todo: add makeindex etc. +input_file = r""" +\documentclass{article} +\usepackage{hyperref} +\usepackage{comment} +\specialcomment{foocom}{}{} +\begin{document} +\begin{foocom} +Hi +\end{foocom} +As stated in \cite{X}, this is a bug-a-boo. +\bibliography{fooref} +\bibliographystyle{plain} +\end{document} +""" + +bibfile = r""" +@Article{X, + author = "Mr. X", + title = "A determination of bug-a-boo-ness", + journal = "Journal of B.a.B.", + year = 1920, + volume = 62, + pages = 291 +} +""" + +test.write('SConstruct', """\ +DVI( "foo.ltx" ) +""") + +test.write('foo.ltx', input_file) +test.write('fooref.bib', bibfile) + +test.run() + +test.must_exist('foo.log') +test.must_exist('foo.aux') +test.must_exist('foo.bbl') +test.must_exist('foo.blg') +test.must_exist('comment.cut') +test.must_exist('foo.out') + +test.run(arguments = '-c') + +test.must_not_exist('foo.log') +test.must_not_exist('foo.aux') +test.must_not_exist('foo.bbl') +test.must_not_exist('foo.blg') +test.must_not_exist('comment.cut') +test.must_not_exist('foo.out') + +test.pass_test() diff --git a/test/TargetSignatures.py b/test/TargetSignatures/build-content.py index c3b506b..2cd7a89 100644 --- a/test/TargetSignatures.py +++ b/test/TargetSignatures/build-content.py @@ -24,17 +24,26 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Verify basic interaction of the historic TargetSignatures('build') +and TargetSignatures('content') settings, overriding one with +the other in specific construction environments. +""" + import TestSCons test = TestSCons.TestSCons() -test.write('SConstruct', """ + + +sconstruct_contents = """\ env = Environment() def copy1(env, source, target): open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) def copy2(env, source, target): + %s return copy1(env, source, target) env['BUILDERS']['Copy1'] = Builder(action=copy1) @@ -44,12 +53,20 @@ env.Copy2('foo.mid', 'foo.in') env.Copy1('foo.out', 'foo.mid') env2 = env.Clone() -env2.TargetSignatures('build') +env2.TargetSignatures('%s') env2.Copy2('bar.mid', 'bar.in') env2.Copy1('bar.out', 'bar.mid') -TargetSignatures('content') -""") +TargetSignatures('%s') +""" + +def write_SConstruct(test, *args): + contents = sconstruct_contents % args + test.write('SConstruct', contents) + + + +write_SConstruct(test, '', 'build', 'content') test.write('foo.in', 'foo.in') test.write('bar.in', 'bar.in') @@ -64,29 +81,12 @@ copy1(["foo.out"], ["foo.mid"]) test.up_to_date(arguments='bar.out foo.out') -test.write('SConstruct', """ -env = Environment() - -def copy1(env, source, target): - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) - -def copy2(env, source, target): - x = 2 # added this line - return copy1(env, source, target) - -env['BUILDERS']['Copy1'] = Builder(action=copy1) -env['BUILDERS']['Copy2'] = Builder(action=copy2) -env.Copy2('foo.mid', 'foo.in') -env.Copy1('foo.out', 'foo.mid') -env2 = env.Clone() -env2.TargetSignatures('build') -env2.Copy2('bar.mid', 'bar.in') -env2.Copy1('bar.out', 'bar.mid') +# Change the code in the the copy2() function, which should change +# its content and trigger a rebuild of the targets built with it. -TargetSignatures('content') -""") +write_SConstruct(test, 'x = 2 # added this line', 'build', 'content') test.run(arguments="bar.out foo.out", stdout=test.wrap_stdout("""\ @@ -96,58 +96,21 @@ copy2(["foo.mid"], ["foo.in"]) scons: `foo.out' is up to date. """)) -test.write('SConstruct', """ -env = Environment() - -def copy1(env, source, target): - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) - -def copy2(env, source, target): - x = 2 # added this line - return copy1(env, source, target) - -env['BUILDERS']['Copy1'] = Builder(action=copy1) -env['BUILDERS']['Copy2'] = Builder(action=copy2) - -env.Copy2('foo.mid', 'foo.in') -env.Copy1('foo.out', 'foo.mid') - -env2 = env.Copy() -env2.TargetSignatures('content') -env2.Copy2('bar.mid', 'bar.in') -env2.Copy1('bar.out', 'bar.mid') - -TargetSignatures('build') -""") -test.run(arguments="bar.out foo.out", - stdout=test.wrap_stdout("""\ -copy1(["bar.out"], ["bar.mid"]) -copy1(["foo.out"], ["foo.mid"]) -""")) -test.write('SConstruct', """ -env = Environment() +# Swapping content and build signatures no longer causes a rebuild +# because we record the right underlying information regardless. -def copy1(env, source, target): - open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) +write_SConstruct(test, 'x = 2 # added this line', 'content', 'build') -def copy2(env, source, target): - return copy1(env, source, target) +test.up_to_date(arguments="bar.out foo.out") -env['BUILDERS']['Copy1'] = Builder(action=copy1) -env['BUILDERS']['Copy2'] = Builder(action=copy2) -env.Copy2('foo.mid', 'foo.in') -env.Copy1('foo.out', 'foo.mid') -env2 = env.Copy() -env2.TargetSignatures('content') -env2.Copy2('bar.mid', 'bar.in') -env2.Copy1('bar.out', 'bar.mid') +# Change the code in the the copy2() function back again, which should +# trigger another rebuild of the targets built with it. -TargetSignatures('build') -""") +write_SConstruct(test, '', 'content', 'build') test.run(arguments='bar.out foo.out', stdout=test.wrap_stdout("""\ @@ -158,4 +121,5 @@ copy1(["foo.out"], ["foo.mid"]) """)) + test.pass_test() diff --git a/test/TargetSignatures/content.py b/test/TargetSignatures/content.py new file mode 100644 index 0000000..8d9f213 --- /dev/null +++ b/test/TargetSignatures/content.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify use of the TargetSignatures('content') setting to override +SourceSignatures('timestamp') settings. +""" + +import TestSCons + +test = TestSCons.TestSCons() + + + +test.write('SConstruct', """\ +env = Environment() + +def copy(env, source, target): + fp = open(str(target[0]), 'wb') + for s in source: + fp.write(open(str(s), 'rb').read()) + fp.close() + +copyAction = Action(copy, "Copying $TARGET") + +SourceSignatures('timestamp') + +env['BUILDERS']['Copy'] = Builder(action=copyAction) + +env.Copy('foo.out', 'foo.in') + +env2 = env.Clone() +env2.TargetSignatures('content') +env2.Copy('bar.out', 'bar.in') +AlwaysBuild('bar.out') + +env.Copy('final', ['foo.out', 'bar.out', 'extra.in']) +env.Ignore('final', 'extra.in') +""") + +test.write('foo.in', "foo.in\n") +test.write('bar.in', "bar.in\n") +test.write('extra.in', "extra.in 1\n") + +test.run() + +test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") + +test.sleep() +test.write('extra.in', "extra.in 2\n") + +test.run() + +test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") + + + +test.pass_test() diff --git a/test/TargetSignatures/overrides.py b/test/TargetSignatures/overrides.py new file mode 100644 index 0000000..5d9dd99 --- /dev/null +++ b/test/TargetSignatures/overrides.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Make sure that TargetSignatures() works when overrides are used on a +Builder call. Previous implementations used methods that would stay +bound to the underlying construction environment and cause weird +behavior like infinite recursion. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +env.TargetSignatures('content') +env.Command('foo.out', 'foo.mid', Copy('$TARGET', '$SOURCE'), FOO=1) +env.Command('foo.mid', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=2) +""") + +test.write('foo.in', "foo.in\n") + +test.run(arguments = '.') + +test.must_match('foo.mid', "foo.in\n") +test.must_match('foo.out', "foo.in\n") + +test.pass_test() diff --git a/test/Value.py b/test/Value.py index 85fcbd1..fd7afb7 100644 --- a/test/Value.py +++ b/test/Value.py @@ -35,13 +35,9 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons(match=TestCmd.match_re) -# Run all of the tests with both types of source signature -# to make sure there's no difference in behavior. -for source_signature in ['MD5', 'timestamp']: +python = TestSCons.python - print "Testing Value node with source signatures:", source_signature - - test.write('SConstruct', """ +SConstruct_content = """ SourceSignatures(r'%(source_signature)s') class Custom: @@ -57,7 +53,7 @@ def create(target, source, env): env = Environment() env['BUILDERS']['B'] = Builder(action = create) -env['BUILDERS']['S'] = Builder(action = '%(_python_)s put $SOURCES into $TARGET') +env['BUILDERS']['S'] = Builder(action = r'%(_python_)s put.py $SOURCES into $TARGET') env.B('f1.out', Value(P)) env.B('f2.out', env.Value(L)) env.B('f3.out', Value(C)) @@ -75,15 +71,23 @@ env['BUILDERS']['B3'] = Builder(action = create_value_file) V = Value('my value') env.B2(V, 'f3.out') env.B3('f5.out', V) -""" % locals()) +""" - test.write('put', """ +test.write('put.py', """\ import os import string import sys open(sys.argv[-1],'wb').write(string.join(sys.argv[1:-2])) """) +# Run all of the tests with both types of source signature +# to make sure there's no difference in behavior. +for source_signature in ['MD5', 'timestamp']: + + print "Testing Value node with source signatures:", source_signature + + test.write('SConstruct', SConstruct_content % locals()) + test.run(arguments='-c') test.run() diff --git a/test/bad-drive.py b/test/bad-drive.py index a642a7c..f07da2b 100644 --- a/test/bad-drive.py +++ b/test/bad-drive.py @@ -93,7 +93,7 @@ test.fail_test(test.read('aaa.out') != "aaa.in\n") # becomes an issue or some refactoring restores the old behavior. test.run(arguments = bad_drive + 'not_mentioned', - stderr = "scons: *** No drive `%s' for target `%snot_mentioned'. Stop.\n" % (bad_drive, bad_drive), + stderr = "scons: *** Do not know how to make target `%snot_mentioned'. Stop.\n" % (bad_drive), status = 2) test.run(arguments = bad_drive + 'no_target_1', diff --git a/test/chained-build.py b/test/chained-build.py index 9d87347..6ec9d1c 100644 --- a/test/chained-build.py +++ b/test/chained-build.py @@ -59,6 +59,7 @@ test.write(['w1', 'foo.in'], "foo.in 1") test.run(chdir='w1', arguments="--max-drift=0 -f SConstruct1 foo.mid", stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n')) + test.run(chdir='w1', arguments="--max-drift=0 -f SConstruct2 foo.out", stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n')) @@ -66,6 +67,7 @@ test.run(chdir='w1', test.up_to_date(chdir='w1', options="--max-drift=0 -f SConstruct1", arguments="foo.mid") + test.up_to_date(chdir='w1', options="--max-drift=0 -f SConstruct2", arguments="foo.out") @@ -73,28 +75,23 @@ test.up_to_date(chdir='w1', test.sleep() # make sure foo.in rewrite has new mod-time test.write(['w1', 'foo.in'], "foo.in 2") -test.run(chdir='w1', - arguments="--max-drift=0 -f SConstruct1 foo.mid", - stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n')) # Because we're using --max-drift=0, we use the cached csig value -# and think that foo.mid hasn't changed even though it has on disk. +# and think that foo.in hasn't changed even though it has on disk. test.up_to_date(chdir='w1', - options="--max-drift=0 -f SConstruct2", - arguments="foo.out") + options="--max-drift=0 -f SConstruct1", + arguments="foo.mid") +# Now try with --max-drift disabled. The build of foo.out should still +# be considered up-to-date, but the build of foo.mid now detects the +# change and rebuilds, too, which then causes a rebuild of foo.out. test.up_to_date(chdir='w1', - options="--max-drift=0 -f SConstruct1", - arguments="foo.mid") -test.up_to_date(chdir='w1', - options="--max-drift=0 -f SConstruct2", + options="--max-drift=-1 -f SConstruct2", arguments="foo.out") -# Now try with --max-drift disabled. The build of foo.mid should still -# be considered up-to-date, but the build of foo.out now detects the -# change and rebuilds, too. -test.up_to_date(chdir='w1', - options="--max-drift=-1 -f SConstruct1", - arguments="foo.mid") +test.run(chdir='w1', + arguments="--max-drift=-1 -f SConstruct1 foo.mid", + stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n')) + test.run(chdir='w1', arguments="--max-drift=-1 -f SConstruct2 foo.out", stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n')) diff --git a/test/exceptions.py b/test/exceptions.py index 34c24f4..c4bfb37 100644 --- a/test/exceptions.py +++ b/test/exceptions.py @@ -65,7 +65,7 @@ test.run(arguments = "-j2 foo.out", stderr = expected_stderr, status = 2) # Verify that exceptions caused by exit values of builder actions are -# correectly signalled, for both Serial and Parallel jobs. +# correctly signalled, for both Serial and Parallel jobs. test.write('myfail.py', r"""\ import sys @@ -75,12 +75,12 @@ sys.exit(1) test.write(SConstruct_path, """ Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE') env = Environment(BUILDERS = { 'Fail' : Fail }) -env.Fail(target = 'f1', source = 'f1.in') +env.Fail(target = 'out.f1', source = 'in.f1') """ % locals()) -test.write('f1.in', "f1.in\n") +test.write('in.f1', "in.f1\n") -expected_stderr = "scons: \*\*\* \[f1\] Error 1\n" +expected_stderr = "scons: \\*\\*\\* \\[out.f1\\] Error 1\n" test.run(arguments = '.', status = 2, stderr = expected_stderr) test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr) @@ -93,13 +93,14 @@ test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr) test.write(SConstruct_path, """ Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE') env = Environment(BUILDERS = { 'Fail' : Fail }) -env.Fail(target = 'f1', source = 'f1.in') -env.Fail(target = 'f2', source = 'f2.in') -env.Fail(target = 'f3', source = 'f3.in') +env.Fail(target = 'out.f1', source = 'in.f1') +env.Fail(target = 'out.f2', source = 'in.f2') +env.Fail(target = 'out.f3', source = 'in.f3') """ % locals()) -# f2.in is not created to cause a Task.prepare exception -test.write('f3.in', 'f3.in\n') +# in.f2 is not created to cause a Task.prepare exception +test.write('in.f1', 'in.f1\n') +test.write('in.f3', 'in.f3\n') # In Serial task mode, get the first exception and stop test.run(arguments = '.', status = 2, stderr = expected_stderr) @@ -107,24 +108,32 @@ test.run(arguments = '.', status = 2, stderr = expected_stderr) # In Parallel task mode, we will get all three exceptions. expected_stderr_list = [ - expected_stderr, - "scons: \*\*\* Source `f2\.in' not found, needed by target `f2'\. Stop\.\n", - string.replace(expected_stderr, 'f1', 'f3') - ] - -# Unfortunately, we aren't guaranteed what order we will get the -# exceptions in... -orders = [ (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1) ] -otexts = [] -for A,B,C in orders: - otexts.append("%s%s%s"%(expected_stderr_list[A-1], - expected_stderr_list[B-1], - expected_stderr_list[C-1])) - - -expected_stderrs = "(" + string.join(otexts, "|") + ")" - -test.run(arguments = '-j3 .', status = 2, stderr = expected_stderrs) + "scons: *** [out.f1] Error 1\n", + "scons: *** Source `in.f2' not found, needed by target `out.f2'. Stop.\n", + "scons: *** [out.f3] Error 1\n", +] + +# To get all three exceptions simultaneously, we execute -j7 to create +# one thread each for the SConstruct file and {in,out}.f[123]. Note that +# it's important that the input (source) files sort earlier alphabetically +# than the output files, so they're visited first in the dependency graph +# walk of '.' and are already considered up-to-date when we kick off the +# "simultaneous" builds of the output (target) files. + +test.run(arguments = '-j7 .', status = 2, stderr = None) + +missing = [] +for es in expected_stderr_list: + if string.find(test.stderr(), es) == -1: + missing.append(es) + +if missing: + sys.stderr.write("Missing the following lines from stderr:\n") + for m in missing: + sys.stderr.write(m) + sys.stderr.write('STDERR ===============================================\n') + sys.stderr.write(test.stderr()) + test.fail_test(1) test.pass_test() diff --git a/test/explain/get_csig.py b/test/explain/get_csig.py new file mode 100644 index 0000000..4bf4981 --- /dev/null +++ b/test/explain/get_csig.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we can call get_csig() from a function action without +causing problems. (This messed up a lot of internal state before +the Big Signature Refactoring.) + +Test case courtesy of Damyan Pepper. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +args = "--debug=explain" + +test.write('SConstruct', """\ +env = Environment() + +def action( source, target, env ): + target[0].get_csig() + f = open( str(target[0]), 'w' ) + for s in source: + f.write( s.get_contents() ) + f.close() + +builder = env.Builder( action=action ) + +builder( env, target = "target.txt", source = "source.txt" ) +""") + +test.write("source.txt", "source.txt 1\n") + +test.run(arguments=args) + + + +test.write("source.txt", "source.txt 2") + + + +expect_rebuild = test.wrap_stdout("""\ +scons: rebuilding `target.txt' because `source.txt' changed +action(["target.txt"], ["source.txt"]) +""") + +test.not_up_to_date(arguments=args) + + + +test.pass_test() diff --git a/test/implicit-cache/basic.py b/test/implicit-cache/basic.py index 0c9196c..265f589 100644 --- a/test/implicit-cache/basic.py +++ b/test/implicit-cache/basic.py @@ -41,7 +41,13 @@ test = TestSCons.TestSCons() test.subdir('include', 'subdir', ['subdir', 'include'], 'inc2') +# Set TargetSignatures('build') because a lot of the test below expect +# the old behavior of non-essential changes in .h files will propagate +# and cause the executable file to be re-linked as well (even if the +# object file was rebuilt to the exact same contents as last time). + test.write('SConstruct', """ +TargetSignatures('build') env = Environment(CPPPATH = Split('inc2 include')) obj = env.Object(target='prog', source='subdir/prog.c') env.Program(target='prog', source=obj) diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py new file mode 100644 index 0000000..47acc2f --- /dev/null +++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that the $IMPLICIT_COMMAND_DEPENDENCIES variable controls +whether or not the implicit dependency on executed commands +is added to targets. +""" + +import TestSCons + +python = TestSCons.python +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +generate_build_py_py_contents = """\ +#!%(python)s +import os +import sys + +open(sys.argv[1], 'w').write('''\ +#!/usr/bin/env %(python)s +import os.path +import string +import sys +fp = open(sys.argv[1], 'wb') +args = [os.path.split(sys.argv[0])[1]] + sys.argv[1:] +fp.write(string.join(args) + '\\\\n' + '%(extra)s') +for infile in sys.argv[2:]: + fp.write(open(infile, 'rb').read()) +fp.close() +''') +os.chmod(sys.argv[1], 0755) + +""" + +extra = '' +test.write('generate_build_py.py', generate_build_py_py_contents % locals()) + +test.write('SConstruct', """ +generate = Builder(action = r'%(_python_)s $GENERATE $TARGET') +build = Builder(action = r'$BUILD_PY $TARGET $SOURCES') +env = Environment(BUILDERS = { + 'GenerateBuild' : generate, + 'BuildFile' : build, + }, + GENERATE = 'generate_build_py.py', + BUILD_PY = 'build.py', + ) +env.PrependENVPath('PATH', '.') +env.PrependENVPath('PATHEXT', '.PY') +env0 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0) +env1 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 1) +envNone = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = None) +envFalse = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = False) +envTrue = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = True) + +build_py = env.GenerateBuild('${BUILD_PY}', []) +AlwaysBuild(build_py) + +env.BuildFile('file.out', 'file.in') +env0.BuildFile('file0.out', 'file.in') +env1.BuildFile('file1.out', 'file.in') +envNone.BuildFile('fileNone.out', 'file.in') +envFalse.BuildFile('fileFalse.out', 'file.in') +envTrue.BuildFile('fileTrue.out', 'file.in') +""" % locals()) + + + +test.write('file.in', "file.in\n") + +test.run(arguments = '--tree=all .') + +expect_none = 'build.py %s file.in\nfile.in\n' + +test.must_match('file.out', expect_none % 'file.out') +test.must_match('file0.out', expect_none % 'file0.out') +test.must_match('file1.out', expect_none % 'file1.out') +test.must_match('fileNone.out', expect_none % 'fileNone.out') +test.must_match('fileFalse.out', expect_none % 'fileFalse.out') +test.must_match('fileTrue.out', expect_none % 'fileTrue.out') + + + +extra = 'xyzzy\\\\n' +test.write('generate_build_py.py', generate_build_py_py_contents % locals()) + +test.run(arguments = '--tree=all .') + +expect_extra = 'build.py %s file.in\nxyzzy\nfile.in\n' + +test.must_match('file.out', expect_extra % 'file.out') +test.must_match('file0.out', expect_none % 'file0.out') +test.must_match('file1.out', expect_extra % 'file1.out') +test.must_match('fileNone.out', expect_none % 'fileNone.out') +test.must_match('fileFalse.out', expect_none % 'fileFalse.out') +test.must_match('fileTrue.out', expect_extra % 'fileTrue.out') + + +test.pass_test() diff --git a/test/implicit/asynchronous-modification.py b/test/implicit/asynchronous-modification.py new file mode 100644 index 0000000..d10f823 --- /dev/null +++ b/test/implicit/asynchronous-modification.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify expected behavior when an implicit dependency is modified +asynchronously (that is, mid-build and without our knowledge). + +Test case courtesy Greg Noel. +""" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.write(['SConstruct'], """\ +import SCons.Defaults +env = Environment() +env['BUILDERS']['C'] = Builder(action = Copy('$TARGET', '$SOURCE'), + source_scanner = SCons.Defaults.CScan) +env['BUILDERS']['Mod'] = Builder(action = r'%(_python_)s mod.py') +Alias('seq', env.C('one.c')) +Alias('seq', env.Mod('mod', 'mod.py')) +Alias('seq', env.C('two.c')) +Default('seq') +""" % locals()) + +test.write(['hdr.h'], """\ +/* empty header */ +""") + +test.write(['mod.py'], """\ +open('mod', 'w').write(open('mod.py', 'r').read()) +open('hdr.h', 'w').write("/* modified */\\n") +""") + +test.write(['one.c'], """\ +#include "hdr.h" +""") + +test.write(['two.c'], """\ +#include "hdr.h" +""") + +# The first run builds the file 'one', then runs the 'mod' script +# (which update modifies the 'hdr.h' file) then builds the file 'two'. +test.run(arguments = 'seq') + +# The 'hdr.h' file had its original contents when 'one' was built, +# and modified contents when 'two' was built. Because we took a +# look at 'hdr.h' once, up front, we think both files are out of +# date and will rebuild both (even though 'two' is really up to date). +# +# A future enhancement might add some sort of verification mode that +# would examine 'hdr.h' again when 'two' was built, thereby avoiding +# the unnecessary rebuild. In that case, the second line below +# will need to change to "test.up_to_date(...)". +test.not_up_to_date(arguments = 'one') +test.not_up_to_date(arguments = 'two') + +# Regardless of what happened on the middle run(s), both files should +# be up to date now. +test.up_to_date(arguments = 'seq') + +test.pass_test() diff --git a/test/changed-node.py b/test/implicit/changed-node.py index 99a16ac..99a16ac 100644 --- a/test/changed-node.py +++ b/test/implicit/changed-node.py diff --git a/test/option-u.py b/test/option-u.py index 9b5e88c..439daa2 100644 --- a/test/option-u.py +++ b/test/option-u.py @@ -73,7 +73,6 @@ env.Cat(target = 'f4a.out', source = 'f4a.in') f4b_in = File('dir/f4b.in') f4b_in.exists() f4b_in.is_derived() -f4b_in.is_pseudo_derived() env.Cat(target = 'dir/f4b.out', source = f4b_in) """) diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py index 33f0f4d..8c8b2cf 100644 --- a/test/option/debug-memoizer.py +++ b/test/option/debug-memoizer.py @@ -69,7 +69,6 @@ expect = [ "Base.stat()", "Dir.srcdir_list()", "File.exists()", - "FS._doLookup()", "Node._children_get()", ] diff --git a/test/option/debug-stree.py b/test/option/debug-stree.py index 21ca386..d25b7fa 100644 --- a/test/option/debug-stree.py +++ b/test/option/debug-stree.py @@ -37,6 +37,10 @@ import time test = TestSCons.TestSCons() +CC = test.detect('CC') +LINK = test.detect('LINK') +if LINK is None: LINK = CC + test.write('SConstruct', """ env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') env.Program('foo', Split('foo.c bar.c')) @@ -75,14 +79,17 @@ test.write('bar.h', """ stree = """ [E B C ]+-foo.xxx [E B C ] +-foo.ooo -[E ] | +-foo.c -[E ] | +-foo.h -[E ] | +-bar.h +[E C ] | +-foo.c +[E C ] | +-foo.h +[E C ] | +-bar.h +[E C ] | +-%(CC)s [E B C ] +-bar.ooo -[E ] +-bar.c -[E ] +-bar.h -[E ] +-foo.h -""" +[E C ] | +-bar.c +[E C ] | +-bar.h +[E C ] | +-foo.h +[E C ] | +-%(CC)s +[E C ] +-%(LINK)s +""" % locals() test.run(arguments = "--debug=stree foo.xxx") test.fail_test(string.find(test.stdout(), stree) == -1) @@ -101,14 +108,17 @@ stree2 = """ [ B ]+-foo.xxx [ B ] +-foo.ooo -[E ] | +-foo.c -[E ] | +-foo.h -[E ] | +-bar.h +[E C ] | +-foo.c +[E C ] | +-foo.h +[E C ] | +-bar.h +[E C ] | +-%(CC)s [ B ] +-bar.ooo -[E ] +-bar.c -[E ] +-bar.h -[E ] +-foo.h -""" +[E C ] | +-bar.c +[E C ] | +-bar.h +[E C ] | +-foo.h +[E C ] | +-%(CC)s +[E C ] +-%(LINK)s +""" % locals() test.run(arguments = '-c foo.xxx') diff --git a/test/option/debug-time.py b/test/option/debug-time.py index e8873cf..8a975a3 100644 --- a/test/option/debug-time.py +++ b/test/option/debug-time.py @@ -64,6 +64,12 @@ test.write('f4.in', "f4.in\n") +# Before anything else, make sure we get valid --debug=time results +# when just running the help option. +test.run(arguments = "-h --debug=time") + + + def num(s, match): return float(re.search(match, s).group(1)) diff --git a/test/option/debug-tree.py b/test/option/debug-tree.py index 4f025c2..09cdffb 100644 --- a/test/option/debug-tree.py +++ b/test/option/debug-tree.py @@ -37,6 +37,10 @@ import time test = TestSCons.TestSCons() +CC = test.detect('CC') +LINK = test.detect('LINK') +if LINK is None: LINK = CC + test.write('SConstruct', """ env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') env.Program('Foo', Split('Foo.c Bar.c')) @@ -82,40 +86,57 @@ tree1 = """ | +-Foo.c | +-Foo.h | +-Bar.h + | +-%(CC)s +-Bar.ooo - +-Bar.c - +-Bar.h - +-Foo.h -""" + | +-Bar.c + | +-Bar.h + | +-Foo.h + | +-%(CC)s + +-%(LINK)s +""" % locals() test.run(arguments = "--debug=tree Foo.xxx") -test.fail_test(string.find(test.stdout(), tree1) == -1) +if string.find(test.stdout(), tree1) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() tree2 = """ +-. +-Bar.c + +-Bar.h +-Bar.ooo | +-Bar.c | +-Bar.h | +-Foo.h + | +-%(CC)s +-Foo.c + +-Foo.h +-Foo.ooo | +-Foo.c | +-Foo.h | +-Bar.h + | +-%(CC)s +-Foo.xxx | +-Foo.ooo | | +-Foo.c | | +-Foo.h | | +-Bar.h + | | +-%(CC)s | +-Bar.ooo - | +-Bar.c - | +-Bar.h - | +-Foo.h + | | +-Bar.c + | | +-Bar.h + | | +-Foo.h + | | +-%(CC)s + | +-%(LINK)s +-SConstruct -""" +""" % locals() + test.run(arguments = "--debug=tree .") -test.fail_test(string.find(test.stdout(), tree2) == -1) +if string.find(test.stdout(), tree2) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() # Make sure we print the debug stuff even if there's a build failure. test.write('Bar.h', """ @@ -129,6 +150,9 @@ THIS SHOULD CAUSE A BUILD FAILURE test.run(arguments = "--debug=tree Foo.xxx", status = 2, stderr = None) -test.fail_test(string.find(test.stdout(), tree1) == -1) +if string.find(test.stdout(), tree1) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() test.pass_test() diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py index 30faced..3139504 100644 --- a/test/option/taskmastertrace.py +++ b/test/option/taskmastertrace.py @@ -34,29 +34,35 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment() -env.Command('file.out', 'file.mid', Copy('$TARGET', '$SOURCE')) -env.Command('file.mid', 'file.in', Copy('$TARGET', '$SOURCE')) + +# We name the files 'Tfile' so that they will sort after the SConstruct +# file regardless of whether the test is being run on a case-sensitive +# or case-insensitive system. + +env.Command('Tfile.out', 'Tfile.mid', Copy('$TARGET', '$SOURCE')) +env.Command('Tfile.mid', 'Tfile.in', Copy('$TARGET', '$SOURCE')) """) -test.write('file.in', "file.in\n") +test.write('Tfile.in', "Tfile.in\n") expect_stdout = test.wrap_stdout("""\ Taskmaster: '.': children: - ['SConstruct', 'file.in', 'file.mid', 'file.out'] - waiting on unstarted children: - ['file.mid', 'file.out'] -Taskmaster: 'file.mid': children: - ['file.in'] - evaluating file.mid -Copy("file.mid", "file.in") -Taskmaster: 'file.out': children: - ['file.mid'] - evaluating file.out -Copy("file.out", "file.mid") + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] + waiting on unfinished children: + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] +Taskmaster: 'SConstruct': evaluating SConstruct +Taskmaster: 'Tfile.in': evaluating Tfile.in +Taskmaster: 'Tfile.mid': children: + ['Tfile.in'] + evaluating Tfile.mid +Copy("Tfile.mid", "Tfile.in") +Taskmaster: 'Tfile.out': children: + ['Tfile.mid'] + evaluating Tfile.out +Copy("Tfile.out", "Tfile.mid") Taskmaster: '.': children: - ['SConstruct', 'file.in', 'file.mid', 'file.out'] + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] evaluating . -Taskmaster: '.': already handled (executed) """) test.run(arguments='--taskmastertrace=- .', stdout=expect_stdout) @@ -68,27 +74,28 @@ test.run(arguments='-c .') expect_stdout = test.wrap_stdout("""\ -Copy("file.mid", "file.in") -Copy("file.out", "file.mid") +Copy("Tfile.mid", "Tfile.in") +Copy("Tfile.out", "Tfile.mid") """) test.run(arguments='--taskmastertrace=trace.out .', stdout=expect_stdout) expect_trace = """\ Taskmaster: '.': children: - ['SConstruct', 'file.in', 'file.mid', 'file.out'] - waiting on unstarted children: - ['file.mid', 'file.out'] -Taskmaster: 'file.mid': children: - ['file.in'] - evaluating file.mid -Taskmaster: 'file.out': children: - ['file.mid'] - evaluating file.out + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] + waiting on unfinished children: + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] +Taskmaster: 'SConstruct': evaluating SConstruct +Taskmaster: 'Tfile.in': evaluating Tfile.in +Taskmaster: 'Tfile.mid': children: + ['Tfile.in'] + evaluating Tfile.mid +Taskmaster: 'Tfile.out': children: + ['Tfile.mid'] + evaluating Tfile.out Taskmaster: '.': children: - ['SConstruct', 'file.in', 'file.mid', 'file.out'] + ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out'] evaluating . -Taskmaster: '.': already handled (executed) """ test.must_match('trace.out', expect_trace) diff --git a/test/option/tree-all.py b/test/option/tree-all.py index ec7c7d8..7940d47 100644 --- a/test/option/tree-all.py +++ b/test/option/tree-all.py @@ -37,6 +37,10 @@ import time test = TestSCons.TestSCons() +CC = test.detect('CC') +LINK = test.detect('LINK') +if LINK is None: LINK = CC + test.write('SConstruct', """ env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') env.Program('Foo', Split('Foo.c Bar.c')) @@ -82,65 +86,92 @@ tree1 = """ | +-Foo.c | +-Foo.h | +-Bar.h + | +-%(CC)s +-Bar.ooo - +-Bar.c - +-Bar.h - +-Foo.h -""" + | +-Bar.c + | +-Bar.h + | +-Foo.h + | +-%(CC)s + +-%(LINK)s +""" % locals() test.run(arguments = "--tree=all Foo.xxx") -test.fail_test(string.find(test.stdout(), tree1) == -1) +if string.find(test.stdout(), tree1) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() tree2 = """ +-. +-Bar.c + +-Bar.h +-Bar.ooo | +-Bar.c | +-Bar.h | +-Foo.h + | +-%(CC)s +-Foo.c + +-Foo.h +-Foo.ooo | +-Foo.c | +-Foo.h | +-Bar.h + | +-%(CC)s +-Foo.xxx | +-Foo.ooo | | +-Foo.c | | +-Foo.h | | +-Bar.h + | | +-%(CC)s | +-Bar.ooo - | +-Bar.c - | +-Bar.h - | +-Foo.h + | | +-Bar.c + | | +-Bar.h + | | +-Foo.h + | | +-%(CC)s + | +-%(LINK)s +-SConstruct -""" +""" % locals() test.run(arguments = "--tree=all .") -test.fail_test(string.find(test.stdout(), tree2) == -1) +if string.find(test.stdout(), tree2) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() tree3 = """ +-. +-Bar.c + +-Bar.h +-Bar.ooo | +-Bar.c | +-Bar.h | +-Foo.h + | +-%(CC)s +-Foo.c + +-Foo.h +-Foo.ooo | +-Foo.c | +-Foo.h | +-Bar.h + | +-%(CC)s +-Foo.xxx | +-[Foo.ooo] | +-[Bar.ooo] + | +-%(LINK)s +-SConstruct -""" +""" % locals() test.run(arguments = "--tree=all,prune .") -test.fail_test(string.find(test.stdout(), tree3) == -1) +if string.find(test.stdout(), tree3) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() test.run(arguments = "--tree=prune .") -test.fail_test(string.find(test.stdout(), tree3) == -1) +if string.find(test.stdout(), tree3) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() tree4 = """ E = exists @@ -156,22 +187,31 @@ tree4 = """ [ B ]+-Foo.xxx [ B ] +-Foo.ooo -[E ] | +-Foo.c -[E ] | +-Foo.h -[E ] | +-Bar.h +[E C ] | +-Foo.c +[E C ] | +-Foo.h +[E C ] | +-Bar.h +[E C ] | +-%(CC)s [ B ] +-Bar.ooo -[E ] +-Bar.c -[E ] +-Bar.h -[E ] +-Foo.h -""" +[E C ] | +-Bar.c +[E C ] | +-Bar.h +[E C ] | +-Foo.h +[E C ] | +-%(CC)s +[E C ] +-%(LINK)s +""" % locals() test.run(arguments = '-c Foo.xxx') test.run(arguments = "--no-exec --tree=all,status Foo.xxx") -test.fail_test(string.find(test.stdout(), tree4) == -1) +if string.find(test.stdout(), tree4) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() test.run(arguments = "--no-exec --tree=status Foo.xxx") -test.fail_test(string.find(test.stdout(), tree4) == -1) +if string.find(test.stdout(), tree4) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() # Make sure we print the debug stuff even if there's a build failure. test.write('Bar.h', """ @@ -185,6 +225,9 @@ THIS SHOULD CAUSE A BUILD FAILURE test.run(arguments = "--tree=all Foo.xxx", status = 2, stderr = None) -test.fail_test(string.find(test.stdout(), tree1) == -1) +if string.find(test.stdout(), tree1) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() test.pass_test() diff --git a/test/option/tree-lib.py b/test/option/tree-lib.py new file mode 100644 index 0000000..fc29d50 --- /dev/null +++ b/test/option/tree-lib.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Make sure that --tree=derived output with a library dependency shows +the dependency on the library. (On earlier versions of the Microsoft +toolchain this wouldn't show up unless the library already existed +on disk.) + +Issue 1363: http://scons.tigris.org/issues/show_bug.cgi?id=1363 +""" + +import string +import sys + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(LIBPREFIX='', + LIBSUFFIX='.lib', + OBJSUFFIX='.obj', + EXESUFFIX='.exe') +env.AppendENVPath('PATH', '.') +l = env.Library( 'util.lib', 'util.c' ) +p = env.Program( 'test.exe', 'main.c', LIBS=l ) +env.Command( 'foo.h', p, '$SOURCE > $TARGET') +""") + +test.write('main.c', """\ +#include <stdlib.h> +#include <stdio.h> +int +main(int argc, char *argv) +{ + printf("#define FOO_H \\"foo.h\\"\\n"); + return (0); +} +""") + +test.write('util.c', """\ +void +util(void) +{ + ; +} +""") + +expect = """ + +-test.exe + +-main.obj + +-util.lib + +-util.obj +""" + +test.run(arguments = '--tree=derived foo.h') +if string.find(test.stdout(), expect) == -1: + sys.stdout.write('Did not find expected tree in the following output:\n') + sys.stdout.write(test.stdout()) + test.fail_test() + +test.up_to_date(arguments = 'foo.h') + +test.pass_test() diff --git a/test/packaging/convenience-functions.py b/test/packaging/convenience-functions.py new file mode 100644 index 0000000..6eae270 --- /dev/null +++ b/test/packaging/convenience-functions.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the FindInstalledFiles() and the FindSourceFiles() functions. +""" + +import os.path +import string +import TestSCons + +python = TestSCons.python +test = TestSCons.TestSCons() + +test.write( "f1", "" ) +test.write( "f2", "" ) +test.write( "f3", "" ) + +test.write( 'SConstruct', r""" +env = Environment(tools=['default', 'packaging']) +prog = env.Install( 'bin/', ["f1", "f2"] ) +env.File( "f3" ) + +src_files = map(str, env.FindSourceFiles()) +oth_files = map(str, env.FindInstalledFiles()) +src_files.sort() +oth_files.sort() + +print src_files +print oth_files +""") + +bin_f1 = os.path.join('bin', 'f1') +bin_f2 = os.path.join('bin', 'f2') + +bin__f1 = string.replace(bin_f1, '\\', '\\\\') +bin__f2 = string.replace(bin_f2, '\\', '\\\\') + +expect_read = """\ +['SConstruct', 'f1', 'f2', 'f3'] +['%(bin__f1)s', '%(bin__f2)s'] +""" % locals() + +expect_build = """\ +Install file: "f1" as "%(bin_f1)s" +Install file: "f2" as "%(bin_f2)s" +""" % locals() + +expected = test.wrap_stdout(read_str = expect_read, build_str = expect_build) + +test.run(stdout=expected) + +test.pass_test() diff --git a/test/packaging/msi/explicit-target.py b/test/packaging/msi/explicit-target.py new file mode 100644 index 0000000..745f0c1 --- /dev/null +++ b/test/packaging/msi/explicit-target.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the ability to use a explicit target package name and the use +of FindInstalledFiles() in conjuction with .msi packages. +""" + +import os +import TestSCons + +python = TestSCons.python + +test = TestSCons.TestSCons() + +try: + from xml.dom.minidom import * +except ImportError: + test.skip_test('Canoot import xml.dom.minidom skipping test\n') + +wix = test.Environment().WhereIs('candle') + +if not wix: + test.skip_test("No 'candle' found; skipping test\n") + +# +# build with minimal tag set and test for the given package meta-data +# +test.write( 'file1.exe', "file1" ) +test.write( 'file2.exe', "file2" ) + +test.write('SConstruct', """ +import os + +env = Environment(tools=['default', 'packaging']) + +f1 = env.Install( '/usr/' , 'file1.exe' ) +f2 = env.Install( '/usr/' , 'file2.exe' ) + +env.Alias( 'install', [ f1, f2 ] ) + +env.Package( NAME = 'foo', + VERSION = '1.2', + PACKAGETYPE = 'msi', + SUMMARY = 'balalalalal', + DESCRIPTION = 'this should be reallly really long', + VENDOR = 'Nanosoft_2000', + source = env.FindInstalledFiles(), + target = "mypackage.msi", + ) +""") + +test.run(arguments='', stderr = None) + +test.must_exist( 'foo-1.2.wxs' ) +test.must_exist( 'foo-1.2.msi' ) + +dom = parse( test.workpath( 'foo-1.2.wxs' ) ) +Product = dom.getElementsByTagName( 'Product' )[0] +Package = dom.getElementsByTagName( 'Package' )[0] + +test.fail_test( not Product.attributes['Manufacturer'].value == 'Nanosoft_2000' ) +test.fail_test( not Product.attributes['Version'].value == '1.2' ) +test.fail_test( not Product.attributes['Name'].value == 'foo' ) + +test.fail_test( not Package.attributes['Description'].value == 'balalalalal' ) +test.fail_test( not Package.attributes['Comments'].value == 'this should be reallly really long' ) + +test.pass_test() diff --git a/test/packaging/multiple-packages-at-once.py b/test/packaging/multiple-packages-at-once.py new file mode 100644 index 0000000..3151c05 --- /dev/null +++ b/test/packaging/multiple-packages-at-once.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +See if the packaging tool is able to build multiple packages at once. + +TODO: test if the packages are clean versions (i.e. do not contain files + added by different packager runs) +""" + +import TestSCons + +python = TestSCons.python + +test = TestSCons.TestSCons() + +zip = test.detect('ZIP', 'zip') + +if not zip: + test.skip_test('zip not found, skipping test\n') + +test.subdir('src') + +test.write( [ 'src', 'main.c' ], r""" +int main( int argc, char* argv[] ) +{ + return 0; +} +""") + +test.write('SConstruct', """ +Program( 'src/main.c' ) +env=Environment(tools=['default', 'packaging']) +env.Package( PACKAGETYPE = ['src_zip', 'src_targz'], + target = ['src.zip', 'src.tar.gz'], + PACKAGEROOT = 'test', + source = [ 'src/main.c', 'SConstruct' ] ) +""") + +test.run(arguments='', stderr = None) + +test.must_exist( 'src.zip' ) +test.must_exist( 'src.tar.gz' ) + +test.write('SConstruct', """ +Program( 'src/main.c' ) +env=Environment(tools=['default', 'packaging']) +env.Package( PACKAGETYPE = ['src_zip', 'src_targz'], + NAME = "src", VERSION = "1.0", + PACKAGEROOT = 'test', + source = [ 'src/main.c', 'SConstruct' ] ) +""") + +test.run(arguments='', stderr = None) + +test.must_exist( 'src-1.0.zip' ) +test.must_exist( 'src-1.0.tar.gz' ) + +test.pass_test() diff --git a/test/packaging/multiple-subdirs.py b/test/packaging/multiple-subdirs.py new file mode 100644 index 0000000..80758ab --- /dev/null +++ b/test/packaging/multiple-subdirs.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we can build packages in different subdirectories. + +Test case courtesy Andrew Smith. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +tar = test.detect('TAR', 'tar') + +if not tar: + test.skip_test('No TAR executable found; skipping test\n') + +test.subdir('one', 'two', 'three') + +test.write('SConstruct', """\ +env = Environment(tools=['default', 'packaging']) +Export('env') +SConscript(dirs = ['one', 'two', 'three']) +""") + +SConscript_template = """\ +Import('*') + +files = env.Install('/usr/bin', '%s.sh') + +pkg = env.Package(NAME = '%s', + VERSION = '1.0.0', + PACKAGETYPE = 'targz', + source = [files] + ) +""" + +test.write(['one', 'SConscript'], SConscript_template % ('one', 'one')) +test.write(['two', 'SConscript'], SConscript_template % ('two', 'two')) +test.write(['three', 'SConscript'], SConscript_template % ('three', 'three')) + +test.write(['one', 'one.sh'], "one/one.sh\n") +test.write(['two', 'two.sh'], "two/two.sh\n") +test.write(['three', 'three.sh'], "three/three.sh\n") + +test.run(arguments = '.') + +test.must_match(['one', 'one-1.0.0', 'usr', 'bin', 'one.sh'], "one/one.sh\n") +test.must_match(['two', 'two-1.0.0', 'usr', 'bin', 'two.sh'], "two/two.sh\n") +test.must_match(['three', 'three-1.0.0', 'usr', 'bin', 'three.sh'], "three/three.sh\n") + +test.must_exist(['one', 'one-1.0.0.tar.gz']) +test.must_exist(['two', 'two-1.0.0.tar.gz']) +test.must_exist(['three', 'three-1.0.0.tar.gz']) + +test.pass_test() diff --git a/test/packaging/option--package-type.py b/test/packaging/option--package-type.py index 00a569e..ce16e95 100644 --- a/test/packaging/option--package-type.py +++ b/test/packaging/option--package-type.py @@ -67,14 +67,21 @@ env.Package( NAME = 'foo', ) """ % locals()) -test.run(arguments='package PACKAGETYPE=rpm', stderr = None) - src_rpm = 'foo-1.2.3-0.src.rpm' machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine +test.run(arguments='package PACKAGETYPE=rpm', stderr = None) + test.must_exist( src_rpm ) test.must_exist( machine_rpm ) +test.must_not_exist( 'bin/main.c' ) +test.must_not_exist( '/bin/main.c' ) + +test.run(arguments='-c package PACKAGETYPE=rpm', stderr = None) +test.run(arguments='package --package-type=rpm', stderr = None) +test.must_exist( src_rpm ) +test.must_exist( machine_rpm ) test.must_not_exist( 'bin/main.c' ) test.must_not_exist( '/bin/main.c' ) diff --git a/test/packaging/place-files-in-subdirectory.py b/test/packaging/place-files-in-subdirectory.py index d9758a1..66bdd53 100644 --- a/test/packaging/place-files-in-subdirectory.py +++ b/test/packaging/place-files-in-subdirectory.py @@ -38,7 +38,7 @@ test = TestSCons.TestSCons() tar = test.detect('TAR', 'tar') if not tar: - test.skipt_test('tar not found, skipping test\n') + test.skip_test('tar not found, skipping test\n') # # TEST: subdir creation and file copying diff --git a/test/packaging/rpm/cleanup.py b/test/packaging/rpm/cleanup.py index 5472fbb..11f6645 100644 --- a/test/packaging/rpm/cleanup.py +++ b/test/packaging/rpm/cleanup.py @@ -83,9 +83,11 @@ env.Alias( 'install', prog ) """ % locals()) # first run: build the package -# second run: test if the intermediate files have been cleaned -test.run( arguments='' ) -test.run( arguments='-c' ) +# second run: make sure everything is up-to-date (sanity check) +# third run: test if the intermediate files have been cleaned +test.run( arguments='.' ) +test.up_to_date( arguments='.' ) +test.run( arguments='-c .' ) src_rpm = 'foo-1.2.3-0.src.rpm' machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine diff --git a/test/packaging/rpm/explicit-target.py b/test/packaging/rpm/explicit-target.py new file mode 100644 index 0000000..12a6c6c --- /dev/null +++ b/test/packaging/rpm/explicit-target.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the ability to create a rpm package from a explicit target name. +""" + +import os +import TestSCons + +machine = TestSCons.machine +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +scons = test.program + +rpm = test.Environment().WhereIs('rpm') + +if not rpm: + test.skip_test('rpm not found, skipping test\n') + +rpm_build_root = test.workpath('rpm_build_root') + +test.subdir('src') + +test.write( [ 'src', 'main.c' ], r""" +int main( int argc, char* argv[] ) +{ + return 0; +} +""") + +test.write('SConstruct', """ +import os + +env=Environment(tools=['default', 'packaging']) + +env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ') +env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s') + +prog = env.Install( '/bin/' , Program( 'src/main.c') ) + +env.Alias( 'install', prog ) + +env.Package( NAME = 'foo', + VERSION = '1.2.3', + PACKAGEVERSION = 0, + PACKAGETYPE = 'rpm', + LICENSE = 'gpl', + SUMMARY = 'balalalalal', + X_RPM_GROUP = 'Application/fu', + X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"', + DESCRIPTION = 'this should be really really long', + source = [ prog ], + target = "my_rpm_package.rpm", + SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz' + ) +""" % locals()) + +test.run(arguments='', stderr = None) + +src_rpm = 'foo-1.2.3-0.src.rpm' +machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine + +test.must_exist( machine_rpm ) +test.must_exist( src_rpm ) +test.must_not_exist( 'bin/main' ) +test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n') +test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n') + +test.pass_test() diff --git a/test/packaging/rpm/internationalization.py b/test/packaging/rpm/internationalization.py index af0bc75..24d8ddd 100644 --- a/test/packaging/rpm/internationalization.py +++ b/test/packaging/rpm/internationalization.py @@ -104,12 +104,10 @@ test.must_not_exist( 'bin/main' ) cmd = 'rpm -qp --queryformat \'%%{GROUP}-%%{SUMMARY}-%%{DESCRIPTION}\' %s' -os.environ['LC_ALL'] = 'de_DE.utf8' os.environ['LANGUAGE'] = 'de' out = os.popen( cmd % test.workpath(machine_rpm) ).read() test.fail_test( out != 'Applikation/büro-hallo-das sollte wirklich lang sein' ) -os.environ['LC_ALL'] = 'fr_FR.utf8' os.environ['LANGUAGE'] = 'fr' out = os.popen( cmd % test.workpath(machine_rpm) ).read() test.fail_test( out != 'Application/bureau-bonjour-ceci devrait être vraiment long' ) diff --git a/test/packaging/rpm/multipackage.py b/test/packaging/rpm/multipackage.py new file mode 100644 index 0000000..5b85db3 --- /dev/null +++ b/test/packaging/rpm/multipackage.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test the ability to create more than rpm file with different package root +from one SCons environment. +""" + +import os +import TestSCons + +machine = TestSCons.machine +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +scons = test.program + +rpm = test.Environment().WhereIs('rpm') + +if not rpm: + test.skip_test('rpm not found, skipping test\n') + +rpm_build_root = test.workpath('rpm_build_root') + +test.subdir('src') + +test.write( [ 'src', 'main.c' ], r""" +int main( int argc, char* argv[] ) +{ + return 0; +} +""") + +test.write('SConstruct', """ +import os + +env=Environment(tools=['default', 'packaging']) + +env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ') +env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s') + +prog = env.Install( '/bin/' , Program( 'src/main.c') ) + +env.Package( NAME = 'foo', + VERSION = '1.2.3', + PACKAGEVERSION = 0, + PACKAGETYPE = 'rpm', + LICENSE = 'gpl', + SUMMARY = 'balalalalal', + X_RPM_GROUP = 'Application/fu', + X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"', + DESCRIPTION = 'this should be really really long', + source = [ prog ], + SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz' + ) + +env.Package( NAME = 'foo2', + VERSION = '1.2.3', + PACKAGEVERSION = 0, + PACKAGETYPE = 'rpm', + LICENSE = 'gpl', + SUMMARY = 'balalalalal', + X_RPM_GROUP = 'Application/fu', + X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"', + DESCRIPTION = 'this should be really really long', + source = [ prog ], + ) + + + +env.Alias( 'install', prog ) +""" % locals()) + +test.run(arguments='', stderr = None) + +src_rpm = 'foo-1.2.3-0.src.rpm' +machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine +src_rpm2 = 'foo2-1.2.3-0.src.rpm' +machine_rpm2 = 'foo2-1.2.3-0.%s.rpm' % machine + +test.must_exist( machine_rpm ) +test.must_exist( src_rpm ) + +test.must_exist( machine_rpm2 ) +test.must_exist( src_rpm2 ) + +test.must_not_exist( 'bin/main' ) +test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n') +test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n') + +test.pass_test() diff --git a/test/packaging/strip-install-dir.py b/test/packaging/strip-install-dir.py index 65b6a61..ec40220 100644 --- a/test/packaging/strip-install-dir.py +++ b/test/packaging/strip-install-dir.py @@ -34,6 +34,11 @@ python = TestSCons.python test = TestSCons.TestSCons() +tar = test.detect('TAR', 'tar') + +if not tar: + test.skip_test('tar not found, skipping test\n') + test.write( 'main.c', '' ) test.write('SConstruct', """ prog = Install( '/bin', 'main.c' ) diff --git a/test/option-q.py b/test/question/Configure.py index 9b67d0a..aeaba8a 100644 --- a/test/option-q.py +++ b/test/question/Configure.py @@ -24,64 +24,25 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Verify operation of the -q (--question) option in conjunction +with Configure tests. + +(This was originally mostly copied and pasted from test/option-n.py.) +""" + import os.path import re -import string -import sys import TestCmd import TestSCons -test = TestSCons.TestSCons() - -_python_ = TestSCons._python_ - -test.write('build.py', r""" -import sys -contents = open(sys.argv[2], 'rb').read() -file = open(sys.argv[1], 'wb') -file.write(contents) -file.close() -""") - -test.write('SConstruct', """ -B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES') -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'aaa.out', source = 'aaa.in') -env.B(target = 'bbb.out', source = 'bbb.in') -""" % locals()) - -test.write('aaa.in', "aaa.in\n") -test.write('bbb.in', "bbb.in\n") - -test.run(arguments = '-q aaa.out', status = 1) - -test.fail_test(os.path.exists(test.workpath('aaa.out'))) - -test.run(arguments = 'aaa.out') - -test.fail_test(test.read('aaa.out') != "aaa.in\n") - -test.run(arguments = '-q aaa.out', status = 0) +test = TestSCons.TestSCons(match = TestCmd.match_re_dotall) -test.run(arguments = '--question bbb.out', status = 1) +test.write('aaa.in', 'Hello world\n') -test.fail_test(os.path.exists(test.workpath('bbb.out'))) - -test.run(arguments = 'bbb.out') - -test.fail_test(test.read('bbb.out') != "bbb.in\n") - -test.run(arguments = '--question bbb.out', status = 0) - - -# test -q in conjunction with Configure Tests -# mostly copy&paste from test/option-n.py -test.subdir('configure') -test.match_func = TestCmd.match_re_dotall -test.write('configure/aaa.in', 'Hello world') -test.write('configure/SConstruct', -"""def userAction(target,source,env): +test.write('SConstruct', """\ +def userAction(target,source,env): import shutil shutil.copyfile( str(source[0]), str(target[0])) @@ -108,15 +69,16 @@ else: env.B(target='aaa.out', source='aaa.in') """) + # test that conf_dir isn't created and an error is raised stderr=r""" scons: \*\*\* Cannot create configure directory "config\.test" within a dry-run\. File \S+, line \S+, in \S+ """ -test.run(arguments="-q aaa.out",stderr=stderr,status=2, - chdir=test.workpath("configure")) -test.fail_test(os.path.exists(test.workpath("configure", "config.test"))) -test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) +test.run(arguments="-q aaa.out",stderr=stderr,status=2) + +test.must_not_exist(test.workpath("config.test")) +test.must_not_exist(test.workpath("config.log")) # test that targets are not built, if conf_dir exists. # verify that .cache and config.log are not created. @@ -125,27 +87,28 @@ stderr=r""" scons: \*\*\* Cannot update configure test "%s" within a dry-run\. File \S+, line \S+, in \S+ """ % re.escape(os.path.join("config.test", "conftest_0.in")) -test.subdir(['configure','config.test']) -test.run(arguments="-q aaa.out",stderr=stderr,status=2, - chdir=test.workpath("configure")) -test.fail_test(os.path.exists(test.workpath("configure", "config.test", - ".cache"))) -test.fail_test(os.path.exists(test.workpath("configure", "config.test", - "conftest_0"))) -test.fail_test(os.path.exists(test.workpath("configure", "config.test", - "conftest_0.in"))) -test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) + +test.subdir('config.test') + +test.run(arguments="-q aaa.out",stderr=stderr,status=2) + +test.must_not_exist(test.workpath("config.test", ".cache")) +test.must_not_exist(test.workpath("config.test", "conftest_0")) +test.must_not_exist(test.workpath("config.test", "conftest_0.in")) +test.must_not_exist(test.workpath("config.log")) # test that no error is raised, if all targets are up-to-date. In this # case .cache and config.log shouldn't be created stdout=test.wrap_stdout(build_str='cp aaa.in aaa.out\n', read_str="""Executing Custom Test ... yes """) -test.run(stdout=stdout,arguments="aaa.out",status=0,chdir=test.workpath("configure")) -log1_mtime = os.path.getmtime(test.workpath("configure","config.log")) -test.run(arguments="-q aaa.out",status=0, - chdir=test.workpath("configure")) -log2_mtime = os.path.getmtime(test.workpath("configure","config.log")) + +test.run(stdout=stdout,arguments="aaa.out",status=0) + +log1_mtime = os.path.getmtime(test.workpath("config.log")) + +test.run(arguments="-q aaa.out",status=0) +log2_mtime = os.path.getmtime(test.workpath("config.log")) test.fail_test( log1_mtime != log2_mtime ) test.pass_test() diff --git a/test/question/basic.py b/test/question/basic.py new file mode 100644 index 0000000..dc07e48 --- /dev/null +++ b/test/question/basic.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify basic operation of the -q (--question) option. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +_python_ = TestSCons._python_ + +test.write('build.py', r""" +import sys +contents = open(sys.argv[2], 'rb').read() +file = open(sys.argv[1], 'wb') +file.write(contents) +file.close() +""") + +test.write('SConstruct', """ +B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES') +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'aaa.out', source = 'aaa.in') +env.B(target = 'bbb.out', source = 'bbb.in') +""" % locals()) + +test.write('aaa.in', "aaa.in\n") +test.write('bbb.in', "bbb.in\n") + +test.run(arguments = '-q aaa.out', status = 1) + +test.must_not_exist(test.workpath('aaa.out')) + +test.run(arguments = 'aaa.out') + +test.must_match('aaa.out', "aaa.in\n") + +test.run(arguments = '-q aaa.out', status = 0) + +test.run(arguments = '--question bbb.out', status = 1) + +test.must_not_exist(test.workpath('bbb.out')) + +test.run(arguments = 'bbb.out') + +test.must_match('bbb.out', "bbb.in\n") + +test.run(arguments = '--question bbb.out', status = 0) + +test.pass_test() diff --git a/test/question/no-builder.py b/test/question/no-builder.py new file mode 100644 index 0000000..d038724 --- /dev/null +++ b/test/question/no-builder.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify operation of the -q (--question) option when a specified +target has no builder. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +_python_ = TestSCons._python_ + +test.write('SConstruct', """ +""") + +test.run(arguments = '-q no_such_target', status = 1) + +test.run(arguments = '--question no_such_target', status = 1) + +test.pass_test() diff --git a/test/runtest/fallback.py b/test/runtest/fallback.py index 90cd4f2..8b6ae42 100644 --- a/test/runtest/fallback.py +++ b/test/runtest/fallback.py @@ -68,12 +68,20 @@ if re.search('\s', python): else: expect_python = python +def escape(s): + return string.replace(s, '\\', '\\\\') + +expect_python = escape(expect_python) +expect_workpath_pass_py = escape(workpath_pass_py) +expect_workpath_fail_py = escape(workpath_fail_py) +expect_workpath_no_result_py = escape(workpath_no_result_py) + expect_stdout = """\ -%(expect_python)s -tt %(workpath_fail_py)s +%(expect_python)s -tt %(expect_workpath_fail_py)s FAILING TEST STDOUT -%(expect_python)s -tt %(workpath_no_result_py)s +%(expect_python)s -tt %(expect_workpath_no_result_py)s NO RESULT TEST STDOUT -%(expect_python)s -tt %(workpath_pass_py)s +%(expect_python)s -tt %(expect_workpath_pass_py)s PASSING TEST STDOUT Failed the following test: diff --git a/test/runtest/noqmtest.py b/test/runtest/noqmtest.py index c442125..f2bf6eb 100644 --- a/test/runtest/noqmtest.py +++ b/test/runtest/noqmtest.py @@ -59,12 +59,20 @@ if re.search('\s', python): else: expect_python = python +def escape(s): + return string.replace(s, '\\', '\\\\') + +expect_python = escape(expect_python) +expect_workpath_pass_py = escape(workpath_pass_py) +expect_workpath_fail_py = escape(workpath_fail_py) +expect_workpath_no_result_py = escape(workpath_no_result_py) + expect_stdout = """\ -%(expect_python)s -tt %(workpath_fail_py)s +%(expect_python)s -tt %(expect_workpath_fail_py)s FAILING TEST STDOUT -%(expect_python)s -tt %(workpath_no_result_py)s +%(expect_python)s -tt %(expect_workpath_no_result_py)s NO RESULT TEST STDOUT -%(expect_python)s -tt %(workpath_pass_py)s +%(expect_python)s -tt %(expect_workpath_pass_py)s PASSING TEST STDOUT Failed the following test: diff --git a/test/runtest/python.py b/test/runtest/python.py index 1af32dd..95b5f0f 100644 --- a/test/runtest/python.py +++ b/test/runtest/python.py @@ -46,17 +46,11 @@ head, dir = os.path.split(head) mypython = os.path.join(head, dir, os.path.pardir, dir, python) -if re.search('\s', mypython): - _mypython_ = '"' + mypython + '"' -else: - _mypython_ = mypython - test.subdir('test') test.write_passing_test(['test', 'pass.py']) -# NOTE: The "test/fail.py : FAIL" and "test/pass.py : PASS" lines both -# have spaces at the end. +# NOTE: The "test/pass.py : PASS" line has spaces at the end. expect = r"""qmtest.py run --output results.qmr --format none --result-stream="scons_tdb.AegisChangeStream" --context python="%(mypython)s" test --- TEST RESULTS ------------------------------------------------------------- @@ -75,6 +69,6 @@ expect = r"""qmtest.py run --output results.qmr --format none --result-stream="s 1 (100%%) tests PASS """ % locals() -test.run(arguments = '-P %s test' % _mypython_, stdout = expect) +test.run(arguments = ['-P', mypython, 'test'], stdout = expect) test.pass_test() diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py new file mode 100644 index 0000000..8e17e95 --- /dev/null +++ b/test/sconsign/script/Configure.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we can print .sconsign files with Configure context +info in them (which have different BuildInfo entries). +""" + +import os.path + +import TestSCons +import TestSConsign + +_obj = TestSCons._obj + +test = TestSConsign.TestSConsign(match = TestSConsign.match_re) + +CC = test.detect('CC', norm=1) +CC_dir, CC_file = os.path.split(CC) + +# Note: We don't use os.path.join() representations of the file names +# in the expected output because paths in the .sconsign files are +# canonicalized to use / as the separator. + +_sconf_temp_conftest_0_c = '.sconf_temp/conftest_0.c' + +test.write('SConstruct', """ +env = Environment() +import os +env.AppendENVPath('PATH', os.environ['PATH']) +conf = Configure(env) +r1 = conf.CheckCHeader( 'math.h' ) +env = conf.Finish() +""") + +test.run(arguments = '.') + +sig_re = r'[0-9a-fA-F]{32}' +date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' + +# Note: There's a space at the end of the '.*': line, because the +# Value node being printed actually begins with a newline. It would +# probably be good to change that to a repr() of the contents. +expect = r"""=== .: +SConstruct: None \d+ \d+ +=== .sconf_temp: +conftest_0.c: + '.*': +#include "math.h" + + + %(sig_re)s \[.*\] +conftest_0%(_obj)s: + %(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +=== %(CC_dir)s: +%(CC_file)s: %(sig_re)s \d+ \d+ +""" % locals() + +test.run_sconsign(arguments = ".sconsign", + stdout = expect) + +test.pass_test() diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py index 2f5ddf3..99845e3 100644 --- a/test/sconsign/script/SConsignFile.py +++ b/test/sconsign/script/SConsignFile.py @@ -29,12 +29,30 @@ Verify that the sconsign script works with files generated when using the signatures in an SConsignFile(). """ +import os.path + import TestSConsign test = TestSConsign.TestSConsign(match = TestSConsign.match_re) +CC = test.detect('CC', norm=1) +CC_dir, CC_file = os.path.split(CC) +LINK = test.detect('LINK', norm=1) +if LINK is None: LINK = CC + test.subdir('sub1', 'sub2') +# Note: We don't use os.path.join() representations of the file names +# in the expected output because paths in the .sconsign files are +# canonicalized to use / as the separator. + +sub1_hello_c = 'sub1/hello.c' +sub1_hello_obj = 'sub1/hello.obj' +sub2_hello_c = 'sub2/hello.c' +sub2_hello_obj = 'sub2/hello.obj' +sub2_inc1_h = 'sub2/inc1.h' +sub2_inc2_h = 'sub2/inc2.h' + test.write(['SConstruct'], """\ SConsignFile() env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') @@ -79,182 +97,328 @@ test.write(['sub2', 'inc2.h'], r"""\ test.run(arguments = '--implicit-cache .') +sig_re = r'[0-9a-fA-F]{32}' + test.run_sconsign(arguments = ".sconsign", - stdout = """\ + stdout = r"""=== .: +SConstruct: None \d+ \d+ +=== %(CC_dir)s: +%(CC_file)s: %(sig_re)s \d+ \d+ === sub1: -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ +hello.c: %(sig_re)s \d+ \d+ +hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] === sub2: -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") +hello.c: %(sig_re)s \d+ \d+ +hello.exe: %(sig_re)s \d+ \d+ + %(sub2_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +inc1.h: %(sig_re)s \d+ \d+ +inc2.h: %(sig_re)s \d+ \d+ +""" % locals()) test.run_sconsign(arguments = "--raw .sconsign", - stdout = """\ + stdout = r"""=== .: +SConstruct: {'csig': None, 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +=== %(CC_dir)s: +%(CC_file)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} === sub1: -hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.obj: \S+ -hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.c: \S+ +hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] +hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] === sub2: -hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.obj: \S+ -hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") +hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub2_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] +hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub2_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub2_inc1_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub2_inc2_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] +inc1.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +inc2.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +""" % locals()) -test.run_sconsign(arguments = "-v .sconsign", - stdout = """\ +expect = r"""=== .: +SConstruct: + csig: None + timestamp: \d+ + size: \d+ +=== %(CC_dir)s: +%(CC_file)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ === sub1: +hello.c: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ hello.exe: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.obj: \S+ + %(sub1_hello_obj)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(LINK)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] hello.obj: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.c: \S+ + %(sub1_hello_c)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(CC)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] === sub2: +hello.c: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ hello.exe: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.obj: \S+ + %(sub2_hello_obj)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(LINK)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] hello.obj: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") + %(sub2_hello_c)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(sub2_inc1_h)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(sub2_inc2_h)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(CC)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] +inc1.h: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ +inc2.h: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ +""" % locals() -test.run_sconsign(arguments = "-b -v .sconsign", - stdout = """\ -=== sub1: -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -=== sub2: -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -""") +test.run_sconsign(arguments = "-v .sconsign", stdout=expect) test.run_sconsign(arguments = "-c -v .sconsign", - stdout = """\ + stdout = r"""=== .: +SConstruct: + csig: None +=== %(CC_dir)s: +%(CC_file)s: + csig: %(sig_re)s === sub1: +hello.c: + csig: %(sig_re)s hello.exe: - csig: None + csig: %(sig_re)s hello.obj: - csig: None + csig: %(sig_re)s === sub2: +hello.c: + csig: %(sig_re)s hello.exe: - csig: None + csig: %(sig_re)s hello.obj: - csig: None -""") + csig: %(sig_re)s +inc1.h: + csig: %(sig_re)s +inc2.h: + csig: %(sig_re)s +""" % locals()) test.run_sconsign(arguments = "-s -v .sconsign", - stdout = """\ + stdout = r"""=== .: +SConstruct: + size: \d+ +=== %(CC_dir)s: +%(CC_file)s: + size: \d+ === sub1: +hello.c: + size: \d+ hello.exe: size: \d+ hello.obj: size: \d+ === sub2: +hello.c: + size: \d+ hello.exe: size: \d+ hello.obj: size: \d+ -""") +inc1.h: + size: \d+ +inc2.h: + size: \d+ +""" % locals()) test.run_sconsign(arguments = "-t -v .sconsign", - stdout = """\ + stdout = r"""=== .: +SConstruct: + timestamp: \d+ +=== %(CC_dir)s: +%(CC_file)s: + timestamp: \d+ === sub1: +hello.c: + timestamp: \d+ hello.exe: timestamp: \d+ hello.obj: timestamp: \d+ === sub2: +hello.c: + timestamp: \d+ hello.exe: timestamp: \d+ hello.obj: timestamp: \d+ -""") +inc1.h: + timestamp: \d+ +inc2.h: + timestamp: \d+ +""" % locals()) test.run_sconsign(arguments = "-e hello.obj .sconsign", - stdout = """\ + stdout = r"""=== .: +=== %(CC_dir)s: === sub1: -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] === sub2: -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") +hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals(), + stderr = r"""sconsign: no entry `hello.obj' in `\.' +sconsign: no entry `hello.obj' in `%(CC_dir)s' +""" % locals()) test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj .sconsign", - stdout = """\ + stdout = r"""=== .: +=== %(CC_dir)s: === sub1: -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] === sub2: -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") +hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.exe: %(sig_re)s \d+ \d+ + %(sub2_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals(), + stderr = r"""sconsign: no entry `hello.obj' in `\.' +sconsign: no entry `hello.exe' in `\.' +sconsign: no entry `hello.obj' in `\.' +sconsign: no entry `hello.obj' in `%(CC_dir)s' +sconsign: no entry `hello.exe' in `%(CC_dir)s' +sconsign: no entry `hello.obj' in `%(CC_dir)s' +""" % locals()) #test.run_sconsign(arguments = "-i -v .sconsign", -# stdout = """\ -#=== sub1: +# stdout = r"""=== sub1: #hello.exe: # implicit: -# hello.obj: \S+ +# hello.obj: %(sig_re)s #hello.obj: # implicit: -# hello.c: \S+ +# hello.c: %(sig_re)s #=== sub2: #hello.exe: # implicit: -# hello.obj: \S+ +# hello.obj: %(sig_re)s #hello.obj: # implicit: -# hello.c: \S+ -# inc1.h: \S+ -# inc2.h: \S+ -#""") +# hello.c: %(sig_re)s +# inc1.h: %(sig_re)s +# inc2.h: %(sig_re)s +#inc1.h: %(sig_re)s +#inc2.h: %(sig_re)s +#""" % locals()) test.pass_test() diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py index 9a3ce62..fc85133 100644 --- a/test/sconsign/script/Signatures.py +++ b/test/sconsign/script/Signatures.py @@ -35,6 +35,17 @@ import TestSConsign test = TestSConsign.TestSConsign(match = TestSConsign.match_re) +CC = test.detect('CC', norm=1) +LINK = test.detect('LINK', norm=1) +if LINK is None: LINK = CC + +# Note: We don't use os.path.join() representations of the file names +# in the expected output because paths in the .sconsign files are +# canonicalized to use / as the separator. + +sub1_hello_c = 'sub1/hello.c' +sub1_hello_obj = 'sub1/hello.obj' + def re_sep(*args): import os.path import re @@ -90,20 +101,29 @@ test.sleep() test.run(arguments = '. --max-drift=1') +sig_re = r'[0-9a-fA-F]{32}' +date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' + test.run_sconsign(arguments = "-e hello.exe -e hello.obj sub1/.sconsign", - stdout = """\ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -""") + stdout = r"""hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: None \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: None \d+ \d+ + %(CC)s: None \d+ \d+ + %(sig_re)s \[.*\] +""" % locals()) test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r sub1/.sconsign", - stdout = """\ -hello.exe: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+ - hello.obj: \S+ -hello.obj: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+ - hello.c: \S+ -""") + stdout = r"""hello.exe: %(sig_re)s '%(date_re)s' \d+ + %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+ + %(LINK)s: None '%(date_re)s' \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s '%(date_re)s' \d+ + %(sub1_hello_c)s: None '%(date_re)s' \d+ + %(CC)s: None '%(date_re)s' \d+ + %(sig_re)s \[.*\] +""" % locals()) test.pass_test() diff --git a/test/sconsign/script/dblite.py b/test/sconsign/script/dblite.py index fe49df6..1b359e2 100644 --- a/test/sconsign/script/dblite.py +++ b/test/sconsign/script/dblite.py @@ -33,8 +33,19 @@ import TestSConsign test = TestSConsign.TestSConsign(match = TestSConsign.match_re) +CC = test.detect('CC', norm=1) +LINK = test.detect('LINK', norm=1) +if LINK is None: LINK = CC + test.subdir('sub1', 'sub2') +# Note: We don't use os.path.join() representations of the file names +# in the expected output because paths in the .sconsign files are +# canonicalized to use / as the separator. + +sub1_hello_c = 'sub1/hello.c' +sub1_hello_obj = 'sub1/hello.obj' + test.write('SConstruct', """ SConsignFile('my_sconsign') SourceSignatures('timestamp') @@ -83,21 +94,30 @@ test.sleep() test.run(arguments = '. --max-drift=1') -expect = """\ -=== sub1: -hello.exe: \d+ None \d+ \d+ - hello.obj: \d+ -hello.obj: \d+ None \d+ \d+ - hello.c: \d+ -""" - -expect_r = """\ -=== sub1: -hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+ - hello.obj: \d+ -hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+ - hello.c: \d+ -""" +sig_re = r'[0-9a-fA-F]{32}' +date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' + +expect = r"""=== sub1: +hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: None \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: None \d+ \d+ + %(CC)s: None \d+ \d+ + %(sig_re)s \[.*\] +""" % locals() + +expect_r = """=== sub1: +hello.exe: %(sig_re)s '%(date_re)s' \d+ + %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+ + %(LINK)s: None '%(date_re)s' \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s '%(date_re)s' \d+ + %(sub1_hello_c)s: None '%(date_re)s' \d+ + %(CC)s: None '%(date_re)s' \d+ + %(sig_re)s \[.*\] +""" % locals() common_flags = '-e hello.exe -e hello.obj -d sub1' diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py index b860770..1fcfbfd 100644 --- a/test/sconsign/script/no-SConsignFile.py +++ b/test/sconsign/script/no-SConsignFile.py @@ -33,13 +33,23 @@ import TestSConsign test = TestSConsign.TestSConsign(match = TestSConsign.match_re) -def re_sep(*args): - import os.path - import re - return re.escape(apply(os.path.join, args)) +CC = test.detect('CC', norm=1) +LINK = test.detect('LINK', norm=1) +if LINK is None: LINK = CC test.subdir('sub1', 'sub2') +# Note: We don't use os.path.join() representations of the file names +# in the expected output because paths in the .sconsign files are +# canonicalized to use / as the separator. + +sub1_hello_c = 'sub1/hello.c' +sub1_hello_obj = 'sub1/hello.obj' +sub2_hello_c = 'sub2/hello.c' +sub2_hello_obj = 'sub2/hello.obj' +sub2_inc1_h = 'sub2/inc1.h' +sub2_inc2_h = 'sub2/inc2.h' + test.write(['SConstruct'], """ SConsignFile(None) env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj') @@ -82,124 +92,160 @@ test.write(['sub2', 'inc2.h'], r"""\ #define STRING2 "inc2.h" """) -test.run(arguments = '--implicit-cache .') +test.run(arguments = '--implicit-cache --tree=prune .') -test.run_sconsign(arguments = "sub1/.sconsign", - stdout = """\ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -""") +sig_re = r'[0-9a-fA-F]{32}' + +expect = r"""hello.c: %(sig_re)s \d+ \d+ +hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals() + +test.run_sconsign(arguments = "sub1/.sconsign", stdout=expect) +#test.run_sconsign(arguments = "sub1/.sconsign") +#print test.stdout() test.run_sconsign(arguments = "--raw sub1/.sconsign", - stdout = """\ -hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.obj: \S+ -hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+} - hello.c: \S+ -""") + stdout = r"""hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} +hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] +hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1} + %(sig_re)s \[.*\] +""" % locals()) test.run_sconsign(arguments = "-v sub1/.sconsign", - stdout = """\ + stdout = r"""hello.c: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ hello.exe: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.obj: \S+ + %(sub1_hello_obj)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(LINK)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] hello.obj: - bsig: \S+ - csig: None + csig: %(sig_re)s timestamp: \d+ size: \d+ implicit: - hello.c: \S+ -""") - -test.run_sconsign(arguments = "-b -v sub1/.sconsign", - stdout = """\ -hello.exe: - bsig: \S+ -hello.obj: - bsig: \S+ -""") + %(sub1_hello_c)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + %(CC)s: + csig: %(sig_re)s + timestamp: \d+ + size: \d+ + action: %(sig_re)s \[.*\] +""" % locals()) test.run_sconsign(arguments = "-c -v sub1/.sconsign", - stdout = """\ + stdout = r"""hello.c: + csig: %(sig_re)s hello.exe: - csig: None + csig: %(sig_re)s hello.obj: - csig: None -""") + csig: %(sig_re)s +""" % locals()) test.run_sconsign(arguments = "-s -v sub1/.sconsign", - stdout = """\ + stdout = r"""hello.c: + size: \d+ hello.exe: size: \d+ hello.obj: size: \d+ -""") +""" % locals()) test.run_sconsign(arguments = "-t -v sub1/.sconsign", - stdout = """\ + stdout = r"""hello.c: + timestamp: \d+ hello.exe: timestamp: \d+ hello.obj: timestamp: \d+ -""") +""" % locals()) test.run_sconsign(arguments = "-e hello.obj sub1/.sconsign", - stdout = """\ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -""") + stdout = r"""hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals()) test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign", - stdout = """\ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -""") - -# XXX NOT SURE IF THIS IS RIGHT! -sub2_inc1_h = re_sep('sub2', 'inc1.h') -sub2_inc2_h = re_sep('sub2', 'inc2.h') + stdout = r"""hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.exe: %(sig_re)s \d+ \d+ + %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals()) test.run_sconsign(arguments = "sub2/.sconsign", - stdout = """\ -hello.exe: \S+ None \d+ \d+ - hello.obj: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -""") + stdout = r"""hello.c: %(sig_re)s \d+ \d+ +hello.exe: %(sig_re)s \d+ \d+ + %(sub2_hello_obj)s: %(sig_re)s \d+ \d+ + %(LINK)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +inc1.h: %(sig_re)s \d+ \d+ +inc2.h: %(sig_re)s \d+ \d+ +""" % locals()) #test.run_sconsign(arguments = "-i -v sub2/.sconsign", -# stdout = """\ -#hello.exe: +# stdout = r"""hello.c: %(sig_re)s \d+ \d+ +#hello.exe: %(sig_re)s \d+ \d+ # implicit: -# hello.obj: \S+ None \d+ \d+ -#hello.obj: +# hello.obj: %(sig_re)s \d+ \d+ +#hello.obj: %(sig_re)s \d+ \d+ # implicit: -# hello.c: None \S+ \d+ \d+ -# inc1.h: None \S+ \d+ \d+ -# inc2.h: None \S+ \d+ \d+ -#""") +# hello.c: %(sig_re)s \d+ \d+ +# inc1.h: %(sig_re)s \d+ \d+ +# inc2.h: %(sig_re)s \d+ \d+ +#""" % locals()) test.run_sconsign(arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign", - stdout = """\ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ - inc1.h: \S+ - inc2.h: \S+ -hello.obj: \S+ None \d+ \d+ - hello.c: \S+ -""") + stdout = r"""hello.obj: %(sig_re)s \d+ \d+ + %(sub2_hello_c)s: %(sig_re)s \d+ \d+ + %(sub2_inc1_h)s: %(sig_re)s \d+ \d+ + %(sub2_inc2_h)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +hello.obj: %(sig_re)s \d+ \d+ + %(sub1_hello_c)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s \d+ \d+ + %(sig_re)s \[.*\] +""" % locals()) test.pass_test() diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py index 7576023..9d89d70 100644 --- a/test/timestamp-fallback.py +++ b/test/timestamp-fallback.py @@ -24,6 +24,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Verify falling back to 'timestamp' behavior if there is no native +hashlib and no underlying md5 module available. +""" + import imp import os import os.path @@ -33,6 +38,15 @@ import TestSCons test = TestSCons.TestSCons() try: + file, name, desc = imp.find_module('hashlib') +except ImportError: + pass +else: + msg = "This version of Python has a 'hashlib' module.\n" + \ + "Skipping test of falling back to timestamps.\n" + test.skip_test(msg) + +try: file, name, desc = imp.find_module('md5') except ImportError: pass diff --git a/test/up-to-date.py b/test/up-to-date.py index cec5952..366d017 100644 --- a/test/up-to-date.py +++ b/test/up-to-date.py @@ -24,9 +24,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os.path +""" +Verify appropriate printing of "is up to date" messages. +""" + import string -import sys + import TestSCons _python_ = TestSCons._python_ @@ -66,5 +69,29 @@ scons: `f3.out' is up to date. test.run(arguments = 'f1.out f2.out f3.out f4.out', stdout = expect) -test.pass_test() +# Make sure all of the "up to date" messages get printed even when -j +# is used. This broke during signature refactoring development. +expected_lines = [ + "scons: `f1.out' is up to date.", + "scons: `f2.out' is up to date.", + "scons: `f3.out' is up to date.", + "scons: `f4.out' is up to date.", +] +test.run(options = '-j4 f1.out f2.out f3.out f4.out') +stdout = test.stdout() + +missing = [] +for line in expected_lines: + if string.find(stdout, line) == -1: + missing.append(line) + +if missing: + print "Missing the following expected lines:" + for line in missing: + print line + print "STDOUT ==========" + print stdout + test.fail_test() + +test.pass_test() |