diff options
Diffstat (limited to 'test')
104 files changed, 5734 insertions, 699 deletions
diff --git a/test/Actions/function.py b/test/Actions/function.py new file mode 100644 index 0000000..00aa688 --- /dev/null +++ b/test/Actions/function.py @@ -0,0 +1,192 @@ +#!/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 TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +# +# Test that the signature of function action includes all the +# necessary pieces. +# + +test.write('SConstruct', r""" +import re + +import SCons.Action +import SCons.Builder + +options = Options() +options.AddOptions( + ('header', 'Header string (default cell argument)', 'Head:'), + ('trailer', 'Trailer string (default cell argument)', 'Tail'), + ('NbDeps', 'Number of dependencies', '2'), + ('separator', 'Separator for the dependencies (function constant)', ':'), + ('closure_cell_value', 'Value of a closure cell', '25'), + ('b', 'Value of b (value default argument', '7'), + ('regexp', 'Regexp (object as a default argument', 'a(a*)'), + ('docstring', 'Docstring', 'docstring'), + ('extracode', 'Extra code for the builder function', ''), + ('extraarg', 'Extra arg builder function', ''), + ('nestedfuncexp', 'Expression for the nested function', 'xxx - b'), +) + +optEnv = Environment(options=options, tools=[]) + +r = re.compile(optEnv['regexp']) + +toto = \ +r''' +def toto(header='%(header)s', trailer='%(trailer)s'): + xxx = %(closure_cell_value)s + def writeDeps(target, source, env, b=%(b)s, r=r %(extraarg)s , + header=header, trailer=trailer, xxx=xxx): + """+'"""%(docstring)s"""'+""" + def foo(b=b, xxx=xxx): + return %(nestedfuncexp)s + f = open(str(target[0]),'wb') + f.write(header) + for d in env['ENVDEPS']: + f.write(d+'%(separator)s') + f.write(trailer+'\\n') + f.write(str(foo())+'\\n') + f.write(r.match('aaaa').group(1)+'\\n') + %(extracode)s + try: + f.write(str(xarg)+'\\n') + except NameError: + pass + f.close() + + return writeDeps +''' + +exec( toto % optEnv ) + +genHeaderBld = SCons.Builder.Builder( + action = SCons.Action.Action( + toto(), + 'Generating $TARGET', + varlist=['ENVDEPS'] + ), + suffix = '.gen.h' + ) + +env = Environment() +env.Append(BUILDERS = {'GenHeader' : genHeaderBld}) + +envdeps = map(str, range(int(optEnv['NbDeps']))) + +env.GenHeader('Out', None, ENVDEPS=envdeps) +""") + + +rebuildstr = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +Generating Out.gen.h +scons: done building targets. +""" + +nobuildstr = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. +""" + +def runtest( arguments, expectedOutFile, expectedRebuild=True): + test.run(arguments=arguments, + stdout=expectedRebuild and rebuildstr or nobuildstr) + test.must_match('Out.gen.h', expectedOutFile) + + # Should not be rebuild when ran a second time with the same + # arguments. + + test.run(arguments = arguments, stdout=nobuildstr) + test.must_match('Out.gen.h', expectedOutFile) + + +# Original build. +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing a docstring should not cause a rebuild +runtest('docstring=ThisBuilderDoesXAndY', """Head:0:1:Tail\n18\naaa\n""", False) +runtest('docstring=SuperBuilder', """Head:0:1:Tail\n18\naaa\n""", False) +runtest('docstring=', """Head:0:1:Tail\n18\naaa\n""", False) + +# Changing a variable listed in the varlist should cause a rebuild +runtest('NbDeps=3', """Head:0:1:2:Tail\n18\naaa\n""") +runtest('NbDeps=4', """Head:0:1:2:3:Tail\n18\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing the function code should cause a rebuild +runtest('extracode=f.write("XX\\n")', """Head:0:1:Tail\n18\naaa\nXX\n""") +runtest('extracode=a=2', """Head:0:1:Tail\n18\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing a constant used in the function code should cause a rebuild +runtest('separator=,', """Head:0,1,Tail\n18\naaa\n""") +runtest('separator=;', """Head:0;1;Tail\n18\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing the code of a nested function should cause a rebuild +runtest('nestedfuncexp=b-xxx', """Head:0:1:Tail\n-18\naaa\n""") +runtest('nestedfuncexp=b+xxx', """Head:0:1:Tail\n32\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Adding an extra argument should cause a rebuild. +runtest('extraarg=,xarg=2', """Head:0:1:Tail\n18\naaa\n2\n""") +runtest('extraarg=,xarg=5', """Head:0:1:Tail\n18\naaa\n5\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing the value of a default argument should cause a rebuild +# case 1: a value +runtest('b=0', """Head:0:1:Tail\n25\naaa\n""") +runtest('b=9', """Head:0:1:Tail\n16\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# case 2: an object +runtest('regexp=(aaaa)', """Head:0:1:Tail\n18\naaaa\n""") +runtest('regexp=aa(a+)', """Head:0:1:Tail\n18\naa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# Changing the value of a closure cell value should cause a rebuild +# case 1: a value +runtest('closure_cell_value=32', """Head:0:1:Tail\n25\naaa\n""") +runtest('closure_cell_value=7', """Head:0:1:Tail\n0\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +# case 2: a default argument +runtest('header=MyHeader:', """MyHeader:0:1:Tail\n18\naaa\n""") +runtest('trailer=MyTrailer', """Head:0:1:MyTrailer\n18\naaa\n""") +runtest('', """Head:0:1:Tail\n18\naaa\n""") + +test.pass_test() diff --git a/test/CPPDEFINES/basic.py b/test/CPPDEFINES/basic.py new file mode 100644 index 0000000..5c302c3 --- /dev/null +++ b/test/CPPDEFINES/basic.py @@ -0,0 +1,64 @@ +#!/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 use of CPPPDEFINES with various data types. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +test_list = [ + 'xyz', + ['x', 'y', 'z'], + ['x', ['y', 123], 'z', ('int', '$INTEGER')], + { 'c' : 3, 'b': None, 'a' : 1 }, +] +env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0) +for i in test_list: + print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') +env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1) +for i in test_list: + print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') +""") + +expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", + read_str = """\ +-Dxyz +-Dx -Dy -Dz +-Dx -Dy=123 -Dz -Dint=0 +-Da=1 -Db -Dc=3 +|xyz| +|x| |y| |z| +|x| |y=123| |z| |int=1| +|a=1| |b| |c=3| +""") + +test.run(arguments = '.', stdout=expect) + +test.pass_test() diff --git a/test/CPPDEFINES.py b/test/CPPDEFINES/live.py index c38f857..7a169e8 100644 --- a/test/CPPDEFINES.py +++ b/test/CPPDEFINES/live.py @@ -25,56 +25,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -XXX Put a description of the test here. +Verify basic use of CPPDEFINES with live compilation. """ -import string - import TestSCons test = TestSCons.TestSCons() -# Make sure $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined. -test.write('SConstruct', """\ -env = Environment() -print env.subst('$_CPPDEFFLAGS') -""") - -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", - read_str = "\n") - -test.run(arguments = '.', stdout=expect) - -# Test CPPDEFINES as a string and a list. -test.write('SConstruct', """\ -test_list = [ - 'xyz', - ['x', 'y', 'z'], - ['x', ['y', 123], 'z', ('int', '$INTEGER')], - { 'c' : 3, 'b': None, 'a' : 1 }, -] -env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0) -for i in test_list: - print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') -env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1) -for i in test_list: - print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') -""") - -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", - read_str = """\ --Dxyz --Dx -Dy -Dz --Dx -Dy=123 -Dz -Dint=0 --Da=1 -Db -Dc=3 -|xyz| -|x| |y| |z| -|x| |y=123| |z| |int=1| -|a=1| |b| |c=3| -""") - -test.run(arguments = '.', stdout=expect) - test.write('SConstruct', """\ foo = Environment(CPPDEFINES = ['FOO', ('VAL', '$VALUE')], VALUE=7) bar = Environment(CPPDEFINES = {'BAR':None, 'VAL':8}) diff --git a/test/CPPDEFINES/scan.py b/test/CPPDEFINES/scan.py new file mode 100644 index 0000000..c9b60c3 --- /dev/null +++ b/test/CPPDEFINES/scan.py @@ -0,0 +1,181 @@ +#!/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 the Scanner that evaluates CPP lines works as expected. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +m = 'Scanner evaluation of CPP lines not yet supported; skipping test.\n' +test.skip_test(m) + +f1_exe = 'f1' + TestSCons._exe +f2_exe = 'f2' + TestSCons._exe +f3_exe = 'f3' + TestSCons._exe +f4_exe = 'f4' + TestSCons._exe + +test.write('SConstruct', """\ +env = Environment(CPPPATH = ['.']) + +f1 = env.Object('f1', 'fff.c', CPPDEFINES = ['F1']) +f2 = env.Object('f2', 'fff.c', CPPDEFINES = [('F2', 1)]) +f3 = env.Object('f3', 'fff.c', CPPDEFINES = {'F3':None}) +f4 = env.Object('f4', 'fff.c', CPPDEFINES = {'F4':1}) + +env.Program('f1', ['prog.c', f1]) +env.Program('f2', ['prog.c', f2]) +env.Program('f3', ['prog.c', f3]) +env.Program('f4', ['prog.c', f4]) +""") + +test.write('f1.h', """ +#define STRING "F1" +""") + +test.write('f2.h', """ +#define STRING "F2" +""") + +test.write('f3.h', """ +#define STRING "F3" +""") + +test.write('f4.h', """ +#define STRING "F4" +""") + +test.write('fff.c', """ +#ifdef F1 +#include <f1.h> +#endif +#if F2 +#include <f2.h> +#endif +#ifdef F3 +#include <f3.h> +#endif +#ifdef F4 +#include <f4.h> +#endif + +char * +foo(void) +{ + return (STRING); +} +""") + + +test.write('prog.c', r""" +#include <stdio.h> +#include <stdlib.h> + +extern char *foo(void); + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("prog.c: %s\n", foo()); + exit (0); +} +""") + + + +test.run(arguments = '.') + +test.run(program = test.workpath('f1'), stdout = "prog.c: F1\n") +test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n") +test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") +test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") + + + +test.write('f1.h', """ +#define STRING "F1 again" +""") + +test.up_to_date(arguments = '%(f2_exe)s %(f3_exe)s %(f4_exe)s' % locals()) + +test.not_up_to_date(arguments = '.') + +test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") +test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n") +test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") +test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") + + + +test.write('f2.h', """ +#define STRING "F2 again" +""") + +test.up_to_date(arguments = '%(f1_exe)s %(f3_exe)s %(f4_exe)s' % locals()) + +test.not_up_to_date(arguments = '.') + +test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") +test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") +test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") +test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") + + + +test.write('f3.h', """ +#define STRING "F3 again" +""") + +test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f4_exe)s' % locals()) + +test.not_up_to_date(arguments = '.') + +test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") +test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") +test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n") +test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") + + + +test.write('f4.h', """ +#define STRING "F4 again" +""") + +test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f3_exe)s' % locals()) + +test.not_up_to_date(arguments = '.') + +test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") +test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") +test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n") +test.run(program = test.workpath('f4'), stdout = "prog.c: F4 again\n") + + + +test.pass_test() diff --git a/test/CPPDEFINES/undefined.py b/test/CPPDEFINES/undefined.py new file mode 100644 index 0000000..b6b8b44 --- /dev/null +++ b/test/CPPDEFINES/undefined.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 that $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +print env.subst('$_CPPDEFFLAGS') +""") + +expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", + read_str = "\n") + +test.run(arguments = '.', stdout=expect) + +test.pass_test() diff --git a/test/CPPPATH/absolute-path.py b/test/CPPPATH/absolute-path.py new file mode 100644 index 0000000..9adb206 --- /dev/null +++ b/test/CPPPATH/absolute-path.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 ability to #include a file with an absolute path name. (Which +is not strictly a test of using $CPPPATH, but it's in the ball park...) +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('include', 'work') + +inc_h = test.workpath('include', 'inc.h') +does_not_exist_h = test.workpath('include', 'does_not_exist.h') + +test.write(['work', 'SConstruct'], """\ +Program('prog.c') +""") + +test.write(['work', 'prog.c'], """\ +#include <stdio.h> +#include "%(inc_h)s" +#if 0 +#include "%(does_not_exist_h)s" +#endif + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("%%s\\n", STRING); + return 0; +} +""" % locals()) + +test.write(['include', 'inc.h'], """\ +#define STRING "include/inc.h 1\\n" +""") + +test.run(chdir = 'work', arguments = '.') + +test.up_to_date(chdir = 'work', arguments = '.') + +test.write(['include', 'inc.h'], """\ +#define STRING "include/inc.h 2\\n" +""") + +test.not_up_to_date(chdir = 'work', arguments = '.') + +test.pass_test() diff --git a/test/CPPPATH/function-expansion.py b/test/CPPPATH/function-expansion.py new file mode 100644 index 0000000..7c80f22 --- /dev/null +++ b/test/CPPPATH/function-expansion.py @@ -0,0 +1,137 @@ +#!/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 expansion of construction variables whose values are functions +(that return lists that contain Nodes, even) works as expected within +a $CPPPATH list definition. + +This used to cause TypeErrors when the _concat expansion tried to +join the Nodes with the strings. + +Test courtesy Konstantin Bozhikov. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('list_inc1', + 'list_inc2', + 'inc1', + 'inc2', + 'inc3', + ['inc3', 'subdir']) + +test.write('SConstruct', """\ +env = Environment() +def my_cpppaths( target, source, env, for_signature ): + return [ Dir('list_inc1'), Dir('list_inc2') ] + +env = Environment( CPPPATH = [Dir('inc1'), '$INC2', '$INC3/subdir', '$MY_CPPPATHS' ], + INC2 = Dir('inc2'), + INC3 = Dir('inc3'), + MY_CPPPATHS = my_cpppaths ) + +env.Program('prog.c') +""") + +test.write('prog.c', """\ +#include <stdio.h> +#include <stdlib.h> +#include "string_list_1.h" +#include "string_list_2.h" +#include "string_1.h" +#include "string_2.h" +#include "string_3.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("prog.c\\n"); + printf("%s\\n", STRING_LIST_1); + printf("%s\\n", STRING_LIST_2); + printf("%s\\n", STRING_1); + printf("%s\\n", STRING_2); + printf("%s\\n", STRING_3); + exit (0); +} +""") + +test.write(['list_inc1', 'string_list_1.h'], """\ +#define STRING_LIST_1 "list_inc1/string_list_1.h" +""") + +test.write(['list_inc2', 'string_list_2.h'], """\ +#define STRING_LIST_2 "list_inc2/string_list_2.h" +""") + +test.write(['inc1', 'string_1.h'], """\ +#define STRING_1 "inc1/string_1.h" +""") + +test.write(['inc2', 'string_2.h'], """\ +#define STRING_2 "inc2/string_2.h" +""") + +test.write(['inc3', 'subdir', 'string_3.h'], """\ +#define STRING_3 "inc3/subdir/string_3.h" +""") + +test.run() + +test.up_to_date(arguments = '.') + +expect = """\ +prog.c +list_inc1/string_list_1.h +list_inc2/string_list_2.h +inc1/string_1.h +inc2/string_2.h +inc3/subdir/string_3.h +""" + +test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect) + +test.write(['inc3', 'subdir', 'string_3.h'], """\ +#define STRING_3 "inc3/subdir/string_3.h 2" +""") + +test.not_up_to_date(arguments = '.') + +expect = """\ +prog.c +list_inc1/string_list_1.h +list_inc2/string_list_2.h +inc1/string_1.h +inc2/string_2.h +inc3/subdir/string_3.h 2 +""" + +test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect) + +test.pass_test() diff --git a/test/CPPPATH/list-expansion.py b/test/CPPPATH/list-expansion.py new file mode 100644 index 0000000..7e5326f --- /dev/null +++ b/test/CPPPATH/list-expansion.py @@ -0,0 +1,132 @@ +#!/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 expansion of construction variables whose values are +lists works as expected within a $CPPPATH list definition. + +Previously, the stringification of the expansion of the individual +variables would turn a list like ['sub1', 'sub2'] below into "-Isub1 sub2" +on the command line. + +Test case courtesy Daniel Svensson. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('sub1', 'sub2', 'sub3', 'sub4') + +test.write('SConstruct', """\ +class _inc_test: + def __init__(self, name): + self.name = name + + def __call__(self, target, source, env, for_signature): + return env.something[self.name] + +env = Environment() + +env.something = {} +env.something['test'] = ['sub1', 'sub2'] + +env['INC_PATHS1'] = _inc_test + +env['INC_PATHS2'] = ['sub3', 'sub4'] + +env.Append(CPPPATH = ['${INC_PATHS1("test")}', '$INC_PATHS2']) +env.Program('test', 'test.c') +""") + +test.write('test.c', """\ +#include <stdio.h> +#include <stdlib.h> +#include "string1.h" +#include "string2.h" +#include "string3.h" +#include "string4.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("test.c\\n"); + printf("%s\\n", STRING1); + printf("%s\\n", STRING2); + printf("%s\\n", STRING3); + printf("%s\\n", STRING4); + exit (0); +} +""") + +test.write(['sub1', 'string1.h'], """\ +#define STRING1 "sub1/string1.h" +""") + +test.write(['sub2', 'string2.h'], """\ +#define STRING2 "sub2/string2.h" +""") + +test.write(['sub3', 'string3.h'], """\ +#define STRING3 "sub3/string3.h" +""") + +test.write(['sub4', 'string4.h'], """\ +#define STRING4 "sub4/string4.h" +""") + +test.run() + +test.up_to_date(arguments = '.') + +expect = """\ +test.c +sub1/string1.h +sub2/string2.h +sub3/string3.h +sub4/string4.h +""" + +test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect) + +test.write(['sub2', 'string2.h'], """\ +#define STRING2 "sub2/string2.h 2" +""") + +test.not_up_to_date(arguments = '.') + +expect = """\ +test.c +sub1/string1.h +sub2/string2.h 2 +sub3/string3.h +sub4/string4.h +""" + +test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect) + +test.pass_test() diff --git a/test/Configure/Builder-call.py b/test/Configure/Builder-call.py index a6f2fa5..1ce114c 100644 --- a/test/Configure/Builder-call.py +++ b/test/Configure/Builder-call.py @@ -35,7 +35,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.write('cmd.py', r""" +test.write('mycommand.py', r""" import sys sys.stderr.write( 'Hello World on stderr\n' ) sys.stdout.write( 'Hello World on stdout\n' ) @@ -48,7 +48,7 @@ def CustomTest(*args): return 0 conf = env.Configure(custom_tests = {'MyTest' : CustomTest}) if not conf.MyTest(): - env.Command("hello", [], '%(_python_)s cmd.py $TARGET') + env.Command("hello", [], '%(_python_)s mycommand.py $TARGET') env = conf.Finish() """ % locals()) diff --git a/test/DMD.py b/test/D/DMD.py index 8b443f8..8b443f8 100644 --- a/test/DMD.py +++ b/test/D/DMD.py diff --git a/test/D/Scanner.py b/test/D/Scanner.py new file mode 100644 index 0000000..5c69820 --- /dev/null +++ b/test/D/Scanner.py @@ -0,0 +1,144 @@ +#!/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 D scanner can return multiple modules imported by +a single statement. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +_obj = TestSCons._obj + +dmd = test.where_is('dmd') +if not dmd: + test.skip_test("Could not find 'dmd'; skipping test.\n") + +test.subdir(['p']) + +test.write('SConstruct', """ +env = Environment() +env.Program('test1.d') +env.Program('test2.d') +""") + +test.write(['test1.d'], """\ +import module1; +import module2; +import module3; +import p.submodule1; +import p.submodule2; + +int main() { + return 0; +} +""") + +test.write(['test2.d'], """\ +import + module1, + module2, + module3; +import + p.submodule1, + p.submodule2; + +int main() { + return 0; +} +""") + +test.write(['ignored.d'], """\ +module ignored; + +int something; +""") + +test.write(['module1.d'], """\ +module module1; + +int something; +""") + +test.write(['module2.d'], """\ +module module2; + +int something; +""") + +test.write(['module3.di'], """\ +module module3; + +int something; +""") + +test.write(['p', 'ignored.d'], """\ +module p.ignored; + +int something; +""") + +test.write(['p', 'submodule1.d'], """\ +module p.submodule1; + +int something; +""") + +test.write(['p', 'submodule2.d'], """\ +module p.submodule2; + +int something; +""") + +arguments = 'test1%(_obj)s test2%(_obj)s' % locals() + +test.run(arguments = arguments) + +test.up_to_date(arguments = arguments) + +test.write(['module2.d'], """\ +module module2; + +int something_else; +""") + +test.not_up_to_date(arguments = arguments) + +test.up_to_date(arguments = arguments) + +test.write(['p', 'submodule2.d'], """\ +module p.submodule2; + +int something_else; +""") + +test.not_up_to_date(arguments = arguments) + +test.up_to_date(arguments = arguments) + +test.pass_test() diff --git a/test/Errors/SyntaxError.py b/test/Errors/SyntaxError.py index b9ff1ff..956caa7 100644 --- a/test/Errors/SyntaxError.py +++ b/test/Errors/SyntaxError.py @@ -37,8 +37,10 @@ test.write('SConstruct', """ a ! x """) +# It looks like vanilla Python 2.2 is the only version that +# puts "<string>" here in place of the file name. test.run(stdout = "scons: Reading SConscript files ...\n", - stderr = """ File ".+SConstruct", line 2 + stderr = """ File "(.+SConstruct|<string>)", line 2 a ! x diff --git a/test/Errors/execute-a-directory.py b/test/Errors/execute-a-directory.py new file mode 100644 index 0000000..bcdcb7c --- /dev/null +++ b/test/Errors/execute-a-directory.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__" + +import os +import string + +import TestSCons + +test = TestSCons.TestSCons() + +not_executable = test.workpath("not_executable") + +test.write(not_executable, "\n") + +test.write("f3.in", "\n") + +test.write('SConstruct', r""" +bld = Builder(action = '%s $SOURCES $TARGET') +env = Environment(BUILDERS = { 'bld' : bld }) +env.bld(target = 'f3', source = 'f3.in') +""" % string.replace(test.workdir, '\\', '\\\\')) + +test.run(arguments='.', + stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1), + stderr = None, + status = 2) + +bad_command = """\ +Bad command or file name +""" + +unrecognized = """\ +'%s' is not recognized as an internal or external command, +operable program or batch file. +scons: *** [%s] Error 1 +""" + +unspecified = """\ +The name specified is not recognized as an +internal or external command, operable program or batch file. +scons: *** [%s] Error 1 +""" + +cannot_execute = """\ +%s: cannot execute +scons *** [%s] Error 126 +""" + +Permission_denied = """\ +%s: Permission denied +scons: *** [%s] Error 126 +""" + +permission_denied = """\ +%s: permission denied +scons: *** [%s] Error 126 +""" + +is_a_directory = """\ +%s: is a directory +scons: *** [%s] Error 126 +""" + +test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) +if os.name == 'nt': + errs = [ + bad_command, + unrecognized % (test.workdir, 'f3'), + unspecified % 'f3' + ] + test.fail_test(not test.stderr() in errs) +else: + errs = [ + cannot_execute % (not_executable, 'f3'), + is_a_directory % (test.workdir, 'f3'), + Permission_denied % (test.workdir, 'f3'), + Permission_denied % (test.workdir, 'f3'), + ] + error_message_not_found = 1 + for err in errs: + if string.find(test.stderr(), err) != -1: + error_message_not_found = None + break + test.fail_test(error_message_not_found) + +test.pass_test() diff --git a/test/Errors/non-executable-file.py b/test/Errors/non-executable-file.py new file mode 100644 index 0000000..d6e018b --- /dev/null +++ b/test/Errors/non-executable-file.py @@ -0,0 +1,103 @@ +#!/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 string + +import TestSCons + +test = TestSCons.TestSCons() + +not_executable = test.workpath("not_executable") + +test.write(not_executable, "\n") + +test.write("f1.in", "\n") + +bad_command = """\ +Bad command or file name +""" + +unrecognized = """\ +'%s' is not recognized as an internal or external command, +operable program or batch file. +scons: *** [%s] Error 1 +""" + +unspecified = """\ +The name specified is not recognized as an +internal or external command, operable program or batch file. +scons: *** [%s] Error 1 +""" + +cannot_execute = """\ +%s: cannot execute +scons *** [%s] Error 126 +""" + +Permission_denied = """\ +%s: Permission denied +scons: *** [%s] Error 126 +""" + +permission_denied = """\ +%s: permission denied +scons: *** [%s] Error 126 +""" + +test.write('SConstruct', r""" +bld = Builder(action = '%s $SOURCES $TARGET') +env = Environment(BUILDERS = { 'bld': bld }) +env.bld(target = 'f1', source = 'f1.in') +""" % string.replace(not_executable, '\\', '\\\\')) + +test.run(arguments='.', + stdout = test.wrap_stdout("%s f1.in f1\n" % not_executable, error=1), + stderr = None, + status = 2) + +test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) +if os.name == 'nt': + errs = [ + bad_command, + unrecognized % (not_executable, 'f1'), + unspecified % 'f1' + ] + test.fail_test(not test.stderr() in errs) +else: + errs = [ + cannot_execute % (not_executable, 'f1'), + Permission_denied % (not_executable, 'f1'), + permission_denied % (not_executable, 'f1'), + ] + error_message_not_found = 1 + for err in errs: + if string.find(test.stderr(), err) != -1: + error_message_not_found = None + break + test.fail_test(error_message_not_found) + +test.pass_test() diff --git a/test/Errors/nonexistent-executable.py b/test/Errors/nonexistent-executable.py new file mode 100644 index 0000000..b2a9557 --- /dev/null +++ b/test/Errors/nonexistent-executable.py @@ -0,0 +1,107 @@ +#!/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 string + +import TestSCons + +test = TestSCons.TestSCons() + +no_such_file = test.workpath("no_such_file") + +test.write("f1.in", "\n") + +test.write('SConstruct', r""" +bld = Builder(action = '%s $SOURCES $TARGET') +env = Environment(BUILDERS = { 'bld' : bld }) +env.bld(target = 'f1', source = 'f1.in') +""" % string.replace(no_such_file, '\\', '\\\\')) + +test.run(arguments='.', + stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1), + stderr = None, + status = 2) + +bad_command = """\ +Bad command or file name +""" + +unrecognized = """\ +'%s' is not recognized as an internal or external command, +operable program or batch file. +scons: *** [%s] Error 1 +""" + +unspecified = """\ +The name specified is not recognized as an +internal or external command, operable program or batch file. +scons: *** [%s] Error 1 +""" + +not_found_1 = """ +sh: %s: not found +scons: *** [%s] Error 1 +""" + +not_found_2 = """ +sh: %s: not found +scons: *** [%s] Error 1 +""" + +not_found_127 = """\ +sh: %s: not found +scons: *** [%s] Error 127 +""" + +No_such = """\ +%s: No such file or directory +scons: *** [%s] Error 127 +""" + +test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) +if os.name == 'nt': + errs = [ + bad_command, + unrecognized % (no_such_file, 'f1'), + unspecified % 'f1' + ] + test.fail_test(not test.stderr() in errs) +else: + errs = [ + not_found_1 % (no_such_file, 'f1'), + not_found_2 % (no_such_file, 'f1'), + not_found_127 % (no_such_file, 'f1'), + No_such % (no_such_file, 'f1'), + ] + error_message_not_found = 1 + for err in errs: + if string.find(test.stderr(), err) != -1: + error_message_not_found = None + break + test.fail_test(error_message_not_found) + +test.pass_test() diff --git a/test/Errors/permission-denied.py b/test/Errors/permission-denied.py new file mode 100644 index 0000000..05d1e9d --- /dev/null +++ b/test/Errors/permission-denied.py @@ -0,0 +1,64 @@ +#!/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 TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', r""" +env = Environment() +env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE')) +env.InstallAs('test2.out', 'test.out') +# Mark test2.out as precious so we'll handle the exception in +# FunctionAction() rather than when the target is cleaned before building. +env.Precious('test2.out') +env.Default('test2.out') +""") + +test.write('test.in', "test.in 1\n") + +test.run(arguments = '.') + +test.write('test.in', "test.in 2\n") + +test.writable('test2.out', 0) +f = open(test.workpath('test2.out')) + +test.run(arguments = '.', + stderr = None, + status = 2) + +f.close() +test.writable('test2.out', 1) + +test.description_set("Incorrect STDERR:\n%s" % test.stderr()) +errs = [ + "scons: *** [test2.out] test2.out: Permission denied\n", + "scons: *** [test2.out] test2.out: permission denied\n", +] +test.fail_test(test.stderr() not in errs) + +test.pass_test() diff --git a/test/Install/option--install-sandbox.py b/test/Install/option--install-sandbox.py index 4cf9310..38a7915 100644 --- a/test/Install/option--install-sandbox.py +++ b/test/Install/option--install-sandbox.py @@ -48,9 +48,10 @@ file1_out = target+os.path.join( target, destdir, 'file1.out' ) # test.write('SConstruct', r""" env = Environment(SUBDIR='subdir') -env.Install(r'%(destdir)s', 'file1.out') -env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'], - ['file2.in', r'%(_SUBDIR_file3_in)s']) +f1 = env.Install(r'%(destdir)s', 'file1.out') +f2 = env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'], + ['file2.in', r'%(_SUBDIR_file3_in)s']) +env.Depends(f2, f1) """ % locals()) test.write('file1.out', "file1.out\n") @@ -58,9 +59,9 @@ test.write('file2.in', "file2.in\n") test.write(['subdir', 'file3.in'], "subdir/file3.in\n") expect = test.wrap_stdout("""\ +Install file: "file1.out" as "%(file1_out)s" Install file: "file2.in" as "%(target_file2_out)s" Install file: "%(subdir_file3_in)s" as "%(target_subdir_file3_out)s" -Install file: "file1.out" as "%(file1_out)s" """ % locals()) test.run(arguments = '--install-sandbox=%s' % destdir, stdout=expect) diff --git a/test/Interactive/Alias.py b/test/Interactive/Alias.py new file mode 100644 index 0000000..fc05b9a --- /dev/null +++ b/test/Interactive/Alias.py @@ -0,0 +1,85 @@ +#!/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 ability to build an Alias in --interactive mode. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +foo = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Alias('foo-alias', foo) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo-alias\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +# Verify that "scons" can be used as a synonmyn for the "build" command. +scons.send("scons foo-alias\n") + +scons.send("scons 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build foo-alias\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("2") +scons>>> scons: `foo-alias' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/Default-None.py b/test/Interactive/Default-None.py new file mode 100644 index 0000000..36ebf2f --- /dev/null +++ b/test/Interactive/Default-None.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 get the expected error message when we use a "build" +command without arguments and there are no default targets (because they +explicitly called Default(None) in the SConstruct file). +""" + +import TestSCons + +test = TestSCons.TestSCons(combine=1) + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Default(None) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build\n") + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +# Verify that "scons" can be used as a synonmyn for the "build" command. +scons.send("scons\n") + +scons.send("scons foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build\n") + +scons.send("build foo.out\n") + +expect_stdout = """\ +scons>>> scons: *** No targets specified and no Default() targets found. Stop. +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> scons: *** No targets specified and no Default() targets found. Stop. +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("2") +scons>>> scons: *** No targets specified and no Default() targets found. Stop. +scons>>> scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/Default.py b/test/Interactive/Default.py new file mode 100644 index 0000000..d6205e2 --- /dev/null +++ b/test/Interactive/Default.py @@ -0,0 +1,86 @@ +#!/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 use a "build" command without arguments to (re-)build +the Default() targets, without exiting the command loop. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +foo_out = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Default(foo_out) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +# Verify that "scons" can be used as a synonmy for the "build" command. +scons.send("scons\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("2") +scons>>> scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/added-include.py b/test/Interactive/added-include.py new file mode 100644 index 0000000..8c30314 --- /dev/null +++ b/test/Interactive/added-include.py @@ -0,0 +1,118 @@ +#!/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__" + +""" +This verifies the --interactive command line option's ability to +rebuild a target when an implicit dependency (include line) is +added to the source file. +""" + +import string + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('foo.h.in', """ +#define FOO_STRING "foo.h.in" +""") + +test.write('foo.c', """ +#include <stdio.h> + +int main() +{ + printf("foo.c\\n"); + return 0; +} +""") + +test.write('SConstruct', """ +env = Environment(CPPPATH=['.']) +env.Command('foo.h', ['foo.h.in'], Copy('$TARGET', '$SOURCE')) +env.Program('foo', ['foo.c']) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +""") + +foo_exe = test.workpath('foo' + TestSCons._exe) +_foo_exe_ = '"%s"' % string.replace(foo_exe, '\\', '\\\\') + + + +# Start scons, to build "foo" +scons = test.start(arguments = '--interactive') + +scons.send("build %(_foo_exe_)s 1\n" % locals()) + +test.wait_for(test.workpath('1'), popen=scons) + +test.run(program = foo_exe, stdout = 'foo.c\n') + + + + +# Update foo.c +# We add a new #include line, to make sure that scons notices +# the new implicit dependency and builds foo.h first. +test.write('foo.c', """ +#include <foo.h> + +#include <stdio.h> + +int main() +{ + printf("%s\\n", FOO_STRING); + return 0; +} +""") + +scons.send("build %(_foo_exe_)s 2\n" % locals()) + +test.wait_for(test.workpath('2')) + +# Run foo, and make sure it prints correctly +test.run(program = foo_exe, stdout = 'foo.h.in\n') + + + +test.write('foo.h.in', """ +#define FOO_STRING "foo.h.in 3" +""") + + + +scons.send("build %(_foo_exe_)s 3\n" % locals()) + +test.wait_for(test.workpath('3')) + +# Run foo, and make sure it prints correctly +test.run(program = foo_exe, stdout = 'foo.h.in 3\n') + + + +test.pass_test() diff --git a/test/Interactive/basic.py b/test/Interactive/basic.py new file mode 100644 index 0000000..4c78f69 --- /dev/null +++ b/test/Interactive/basic.py @@ -0,0 +1,84 @@ +#!/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 --interactive command line option to build +a target, rebuild it when the input changes, and not rebuild it when +the input doesn't change. + +Also tests that "scons" can be used as a synonym for "build". +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +# Verify that "scons" can be used as a synonmy for the "build" command. +scons.send("scons foo.out 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build foo.out\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> Copy("foo.out", "foo.in") +Touch("2") +scons>>> scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/cache-debug.py b/test/Interactive/cache-debug.py new file mode 100644 index 0000000..dab5159 --- /dev/null +++ b/test/Interactive/cache-debug.py @@ -0,0 +1,117 @@ +#!/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 --interactive command line option to build a target when the +--cache-debug option is used. +""" + +import TestCmd +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +CacheDir('cache') +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +Command('4', [], Touch('$TARGET')) +Command('5', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build foo.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 4\n") + +test.wait_for(test.workpath('4'), popen=scons) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build --cache-debug=- foo.out\n") + +scons.send("build 5\n") + +test.wait_for(test.workpath('5'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + + + +expect_stdout = \ +r"""scons>>> Copy\("foo.out", "foo.in"\) +scons>>> Touch\("1"\) +scons>>> Removed foo.out +scons>>> Touch\("2"\) +scons>>> Retrieved `foo.out' from cache +scons>>> Touch\("3"\) +scons>>> Removed foo.out +scons>>> Touch\("4"\) +scons>>> Retrieved `foo.out' from cache +CacheRetrieve\(foo.out\): retrieving from [0-9A-za-z]+ +scons>>> Touch\("5"\) +scons>>> +""" + +test.finish(scons, stdout = expect_stdout, match=TestCmd.match_re) + + + +test.pass_test() diff --git a/test/Interactive/cache-disable.py b/test/Interactive/cache-disable.py new file mode 100644 index 0000000..0fb8435 --- /dev/null +++ b/test/Interactive/cache-disable.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 the --interactive command line option to build +a target when the --cache-disable option is used. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +CacheDir('cache') +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +Command('4', [], Touch('$TARGET')) +Command('5', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build foo.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 4\n") + +test.wait_for(test.workpath('4')) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build --cache-disable foo.out\n") + +scons.send("build 5\n") + +test.wait_for(test.workpath('5')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + + + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Removed foo.out +scons>>> Touch("2") +scons>>> Retrieved `foo.out' from cache +scons>>> Touch("3") +scons>>> Removed foo.out +scons>>> Touch("4") +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("5") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/cache-force.py b/test/Interactive/cache-force.py new file mode 100644 index 0000000..8fd3f92 --- /dev/null +++ b/test/Interactive/cache-force.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 the --interactive command line option to build a target when the +--cache-force option is used. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +CacheDir('cache') +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +Command('4', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build foo.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +import shutil +shutil.rmtree(test.workpath('cache')) + + + +scons.send("build --cache-force foo.out\n") + +scons.send("clean foo.out\n") + +scons.send("build foo.out\n") + +scons.send("build 4\n") + +test.wait_for(test.workpath('4')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + + + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Removed foo.out +scons>>> Touch("2") +scons>>> Retrieved `foo.out' from cache +scons>>> Touch("3") +scons>>> scons: `foo.out' is up to date. +scons>>> Removed foo.out +scons>>> Retrieved `foo.out' from cache +scons>>> Touch("4") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/cache-show.py b/test/Interactive/cache-show.py new file mode 100644 index 0000000..c1fe487 --- /dev/null +++ b/test/Interactive/cache-show.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 the --interactive command line option to build a target when the +--cache-show option is used. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +CacheDir('cache') +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +Command('4', [], Touch('$TARGET')) +Command('5', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build foo.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + +scons.send("clean foo.out\n") + +scons.send("build 4\n") + +test.wait_for(test.workpath('4')) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build --cache-show foo.out\n") + +scons.send("build 5\n") + +test.wait_for(test.workpath('5')) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + + + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Removed foo.out +scons>>> Touch("2") +scons>>> Retrieved `foo.out' from cache +scons>>> Touch("3") +scons>>> Removed foo.out +scons>>> Touch("4") +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("5") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/clean.py b/test/Interactive/clean.py new file mode 100644 index 0000000..4f4f80d --- /dev/null +++ b/test/Interactive/clean.py @@ -0,0 +1,105 @@ +#!/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__" + +""" +Verifies operation of the --interactive command line option +"clean" subcommand. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE')) +Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE')) +Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +""") + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build f1.out f2.out f3.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('f1.out'), "f1.in\n") +test.must_match(test.workpath('f2.out'), "f2.in\n") +test.must_match(test.workpath('f3.out'), "f3.in\n") + + + +scons.send("clean f1.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_not_exist('f1.out') +test.must_exist('f2.out') +test.must_exist('f3.out') + + + +scons.send("build -c\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_not_exist('f1.out') +test.must_not_exist('f2.out') +test.must_not_exist('f3.out') + +expect_stdout = """\ +scons>>> Copy("f1.out", "f1.in") +Copy("f2.out", "f2.in") +Copy("f3.out", "f3.in") +scons>>> Touch("1") +scons>>> Removed f1.out +scons>>> Touch("2") +scons>>> Removed 1 +Removed 2 +Removed f2.out +Removed f3.out +scons>>> Touch("3") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/exit.py b/test/Interactive/exit.py new file mode 100644 index 0000000..df06d5d --- /dev/null +++ b/test/Interactive/exit.py @@ -0,0 +1,64 @@ +#!/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 "exit" subcommand. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +scons.send('exit\n') + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> """ + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/help.py b/test/Interactive/help.py new file mode 100644 index 0000000..ef4c578 --- /dev/null +++ b/test/Interactive/help.py @@ -0,0 +1,85 @@ +#!/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 the "help" subcommand (and its "h" and "?" aliases). +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +scons.send('help\n') + +scons.send('h\n') + +scons.send('?\n') + +help_text = """\ +build [TARGETS] Build the specified TARGETS and their dependencies. + 'b' is a synonym. +clean [TARGETS] Clean (remove) the specified TARGETS and their + dependencies. 'c' is a synonym. +exit Exit SCons interactive mode. +help [COMMAND] Prints help for the specified COMMAND. 'h' and + '?' are synonyms. +shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!' + are synonyms. +version Prints SCons version information. +""" + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> %(help_text)s +scons>>> %(help_text)s +scons>>> %(help_text)s +scons>>> +""" % locals() + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/implicit-BuildDir.py b/test/Interactive/implicit-BuildDir.py new file mode 100644 index 0000000..7b7aa4b --- /dev/null +++ b/test/Interactive/implicit-BuildDir.py @@ -0,0 +1,142 @@ +#!/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__" + +""" +This is a regression test for a bug in earlier versions of the +--interactive command line option (specifically the original prototype +submitted by Adam Simpkins, who created this test case). + +It tests to make sure that cached state is cleared between files for +nodes in both the build tree and the source tree when BuildDirs are used. +This is needed especially with BuildDirs created with duplicate=0, since +the scanners scan the files in the source tree. Any cached implicit +deps must be cleared on the source files. +""" + +import os.path +import string + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('src', + ['src', 'inc']) + +# Create the top-level SConstruct file +test.write('SConstruct', """ +BUILD_ENV = Environment() +Export('BUILD_ENV') + +hdr_dir = '#build/include' +BUILD_ENV['HDR_DIR'] = hdr_dir +BUILD_ENV.Append(CPPPATH = hdr_dir) + +BUILD_ENV.BuildDir('build', 'src', duplicate = 0) +SConscript('build/SConscript') + +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +# Create the src/SConscript file +test.write(['src', 'SConscript'], """ +Import('BUILD_ENV') +BUILD_ENV.Install(BUILD_ENV['HDR_DIR'], ['inc/foo.h']) +BUILD_ENV.Program('foo', ['foo.c']) +""") + +# Create src/foo.c +test.write(['src', 'foo.c'], """ +#include <stdio.h> + +#define FOO_PRINT_STRING "Hello from foo.c" + +int main() +{ + printf(FOO_PRINT_STRING "\\n"); + return 0; +} +""") + +# Create src/inc/foo.h +test.write(['src', 'inc', 'foo.h'], """ +#ifndef INCLUDED_foo_h +#define INCLUDED_foo_h + +#define FOO_PRINT_STRING "Hello from foo.h" + +#endif /* INCLUDED_foo_h */ +""") + +# Start scons, to build only "build/foo" +build_foo_exe = os.path.join('build', 'foo' + TestSCons._exe) +_build_foo_exe_ = '"%s"' % string.replace(build_foo_exe, '\\', '\\\\') +abs_foo_exe = test.workpath(build_foo_exe) + +scons = test.start(arguments = '--interactive', combine=1) + + + +# Build build/foo +scons.send('build %(_build_foo_exe_)s 1\n' % locals()) + +test.wait_for(test.workpath('1')) + +# Run foo, and make sure it prints correctly +test.run(program = abs_foo_exe, stdout = 'Hello from foo.c\n') + + + +# Update foo.c to include foo.h +test.write(['src', 'foo.c'], """ +#include "foo.h" +#include <stdio.h> + +int main() +{ + printf(FOO_PRINT_STRING "\\n"); + return 0; +} +""") + +# Build build/foo +scons.send('build %(_build_foo_exe_)s 2\n' % locals()) + +test.wait_for(test.workpath('2')) + +# Run foo, and make sure it prints correctly +test.run(program = abs_foo_exe, stdout = 'Hello from foo.h\n') + + + +scons.send('exit\n') + +test.finish(scons) + + + +test.pass_test() diff --git a/test/Interactive/option--Q.py b/test/Interactive/option--Q.py new file mode 100644 index 0000000..4c02fa7 --- /dev/null +++ b/test/Interactive/option--Q.py @@ -0,0 +1,83 @@ +#!/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 the -Q option on an individual "build" command +will suppress the progress messages. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '--interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +scons.send("build -Q foo.out 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +expect_stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons>>> scons: Building targets ... +Copy("foo.out", "foo.in") +Touch("1") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> Copy("foo.out", "foo.in") +Touch("2") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/option-i.py b/test/Interactive/option-i.py new file mode 100644 index 0000000..a2935a7 --- /dev/null +++ b/test/Interactive/option-i.py @@ -0,0 +1,106 @@ +#!/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 -i option, specified on the build command, causes +build errors to be ignored, just for that command. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +def error(target, source, env): + return 1 +e1 = Command('e1.out', 'e1.in', Action(error)) +e2 = Command('e2.out', 'e2.in', Action(error)) +f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE')) +f2 = Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE')) +Depends(f1, e1) +Depends(f2, e2) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +""") + +test.write('e1.in', "e1.in\n") +test.write('e2.in', "e2.in\n") +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") + + + +scons = test.start(arguments = '-Q --interactive', combine=1) + +scons.send("build f1.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_not_exist(test.workpath('f1.out')) + + + +scons.send("build -i e1.out f1.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_match(test.workpath('f1.out'), "f1.in\n") + + + +scons.send("build f2.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3'), popen=scons) + +test.must_not_exist(test.workpath('f2.out')) + + + +expect_stdout = """\ +scons>>> error(["e1.out"], ["e1.in"]) +scons: *** [e1.out] Error 1 +scons>>> Touch("1") +scons>>> error(["e1.out"], ["e1.in"]) +scons: *** [e1.out] Error 1 +Copy("f1.out", "f1.in") +scons>>> Touch("2") +scons>>> error(["e2.out"], ["e2.in"]) +scons: *** [e2.out] Error 1 +scons>>> Touch("3") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/option-j.py b/test/Interactive/option-j.py new file mode 100644 index 0000000..29bba88 --- /dev/null +++ b/test/Interactive/option-j.py @@ -0,0 +1,164 @@ +#!/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 "build" command of --interactive mode can take a -j +option to build things in parallel. +""" + +import TestSCons + +test = TestSCons.TestSCons(combine=1) + +test.write('SConstruct', """\ +import os +import time +from SCons.Script import * +def cat(target, source, env): + t = str(target[0]) + os.mkdir(t + '.started') + fp = open(t, 'wb') + for s in source: + fp.write(open(str(s), 'rb').read()) + fp.close() + os.mkdir(t + '.finished') + +def must_be_finished(target, source, env, dir): + if not os.path.exists(dir): + msg = 'build failed, %s does not exist\\n' % dir + sys.stderr.write(msg) + return 1 + return cat(target, source, env) + +def f1_a_out_must_be_finished(target, source, env): + return must_be_finished(target, source, env, 'f1-a.out.finished') +def f3_a_out_must_be_finished(target, source, env): + return must_be_finished(target, source, env, 'f3-a.out.finished') + +def must_wait_for_f2_b_out(target, source, env): + t = str(target[0]) + os.mkdir(t + '.started') + f2_b_started = 'f2-b.out.started' + while not os.path.exists(f2_b_started): + time.sleep(1) + fp = open(t, 'wb') + for s in source: + fp.write(open(str(s), 'rb').read()) + fp.close() + os.mkdir(t + '.finished') + +def _f2_a_out_must_not_be_finished(target, source, env): + f2_a_started = 'f2-a.out.started' + f2_a_finished = 'f2-a.out.finished' + while not os.path.exists(f2_a_started): + time.sleep(1) + msg = 'f2_a_out_must_not_be_finished(["%s"], ["%s"])\\n' % (target[0], source[0]) + sys.stdout.write(msg) + if os.path.exists(f2_a_finished): + msg = 'build failed, %s exists\\n' % f2_a_finished + sys.stderr.write(msg) + return 1 + return cat(target, source, env) + +f2_a_out_must_not_be_finished = Action(_f2_a_out_must_not_be_finished, + strfunction = None) + +Cat = Action(cat) +f1_a = Command('f1-a.out', 'f1-a.in', cat) +f1_b = Command('f1-b.out', 'f1-b.in', f1_a_out_must_be_finished) +f2_a = Command('f2-a.out', 'f2-a.in', must_wait_for_f2_b_out) +f2_b = Command('f2-b.out', 'f2-b.in', f2_a_out_must_not_be_finished) +f3_a = Command('f3-a.out', 'f3-a.in', cat) +f3_b = Command('f3-b.out', 'f3-b.in', f3_a_out_must_be_finished) +Command('f1.out', f1_a + f1_b, cat) +Command('f2.out', f2_a + f2_b, cat) +Command('f3.out', f3_a + f3_b, cat) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +""") + +test.write('f1-a.in', "f1-a.in\n") +test.write('f1-b.in', "f1-b.in\n") +test.write('f2-a.in', "f2-a.in\n") +test.write('f2-b.in', "f2-b.in\n") +test.write('f3-a.in', "f3-a.in\n") +test.write('f3-b.in', "f3-b.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build f1.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_match(test.workpath('f1.out'), "f1-a.in\nf1-b.in\n") + + + +scons.send("build -j2 f2.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_match(test.workpath('f2.out'), "f2-a.in\nf2-b.in\n") + + + +scons.send("build f3.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_match(test.workpath('f3.out'), "f3-a.in\nf3-b.in\n") + + + +expect_stdout = """\ +scons>>> cat(["f1-a.out"], ["f1-a.in"]) +f1_a_out_must_be_finished(["f1-b.out"], ["f1-b.in"]) +cat(["f1.out"], ["f1-a.out", "f1-b.out"]) +scons>>> Touch("1") +scons>>> must_wait_for_f2_b_out(["f2-a.out"], ["f2-a.in"]) +f2_a_out_must_not_be_finished(["f2-b.out"], ["f2-b.in"]) +cat(["f2.out"], ["f2-a.out", "f2-b.out"]) +scons>>> Touch("2") +scons>>> cat(["f3-a.out"], ["f3-a.in"]) +f3_a_out_must_be_finished(["f3-b.out"], ["f3-b.in"]) +cat(["f3.out"], ["f3-a.out", "f3-b.out"]) +scons>>> Touch("3") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/option-k.py b/test/Interactive/option-k.py new file mode 100644 index 0000000..f15605e --- /dev/null +++ b/test/Interactive/option-k.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 the -k option, specified on the build command, causes +us to keep going and build additional targets. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +def error(target, source, env): + return 1 +e1 = Command('e1.out', 'e1.in', Action(error)) +f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE')) +Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE')) +Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE')) +Depends(f1, e1) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +""") + +test.write('e1.in', "e1.in\n") +test.write('e2.in', "e2.in\n") +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") + + + +scons = test.start(arguments = '-Q --interactive', combine=1) + +scons.send("build f1.out f2.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_not_exist(test.workpath('f1.out')) +test.must_not_exist(test.workpath('f2.out')) + + + +scons.send("build -k f1.out f2.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_not_exist(test.workpath('f1.out')) +test.must_match(test.workpath('f2.out'), "f2.in\n") + + + +scons.send("build f1.out f3.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3'), popen=scons) + +test.must_not_exist(test.workpath('f1.out')) +test.must_not_exist(test.workpath('f3.out')) + + + +expect_stdout = """\ +scons>>> error(["e1.out"], ["e1.in"]) +scons: *** [e1.out] Error 1 +scons>>> Touch("1") +scons>>> error(["e1.out"], ["e1.in"]) +scons: *** [e1.out] Error 1 +Copy("f2.out", "f2.in") +scons>>> Touch("2") +scons>>> error(["e1.out"], ["e1.in"]) +scons: *** [e1.out] Error 1 +scons>>> Touch("3") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/option-n.py b/test/Interactive/option-n.py new file mode 100644 index 0000000..f5ee1e3 --- /dev/null +++ b/test/Interactive/option-n.py @@ -0,0 +1,79 @@ +#!/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 -n option, specified on the build command, reports +what would be built but doesn't actually build anything. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build -n foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1'), popen=scons) + +test.must_not_exist(test.workpath('foo.out')) + + + +scons.send("build foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2'), popen=scons) + +test.must_match(test.workpath('foo.out'), "foo.in\n") + + + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("2") +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/option-s.py b/test/Interactive/option-s.py new file mode 100644 index 0000000..167d581 --- /dev/null +++ b/test/Interactive/option-s.py @@ -0,0 +1,79 @@ +#!/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 --interactive command line option +to build a target, rebuild it when the input changes, and not rebuild +it when the input doesn't change. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +scons.send("build -s foo.out 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build foo.out\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> scons>>> scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/repeat-line.py b/test/Interactive/repeat-line.py new file mode 100644 index 0000000..e85b9ea --- /dev/null +++ b/test/Interactive/repeat-line.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 a blank line repeats the last (build) command. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +scons.send("\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build foo.out\n") + +scons.send("\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> build foo.out 1 +Copy("foo.out", "foo.in") +scons: `1' is up to date. +scons>>> Touch("2") +scons>>> scons: `foo.out' is up to date. +scons>>> build foo.out +scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/shell.py b/test/Interactive/shell.py new file mode 100644 index 0000000..9d5e8a2 --- /dev/null +++ b/test/Interactive/shell.py @@ -0,0 +1,116 @@ +#!/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 ability of the "shell" command (and its "sh" and "!" aliases) +to shell out of interactive mode. +""" + +import string +import sys + +import TestSCons + +test = TestSCons.TestSCons(combine=1) + +_python_ = TestSCons._python_ + +shell_command_py = test.workpath('shell_command.py') +_shell_command_py_ = '"%s"' % string.replace(shell_command_py, '\\', '\\\\') + +test.write(shell_command_py, """\ +print 'hello from shell_command.py' +""") + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +scons.send('!%(_python_)s %(_shell_command_py_)s\n' % locals()) + +scons.send("\n") + +scons.send('shell %(_python_)s %(_shell_command_py_)s\n' % locals()) + +scons.send("\n") + +scons.send('sh %(_python_)s %(_shell_command_py_)s\n' % locals()) + +scons.send("\n") + +scons.send('!no_such_command arg1 arg2\n') + +scons.send("\n") + +scons.send("build foo.out\n") + +scons.send("\n") + +if sys.platform == 'win32': + no_such_error = 'The system cannot find the file specified' +else: + no_such_error = 'No such file or directory' + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> hello from shell_command.py +scons>>> !%(_python_)s %(_shell_command_py_)s +hello from shell_command.py +scons>>> hello from shell_command.py +scons>>> shell %(_python_)s %(_shell_command_py_)s +hello from shell_command.py +scons>>> hello from shell_command.py +scons>>> sh %(_python_)s %(_shell_command_py_)s +hello from shell_command.py +scons>>> scons: no_such_command: %(no_such_error)s +scons>>> !no_such_command arg1 arg2 +scons: no_such_command: %(no_such_error)s +scons>>> scons: `foo.out' is up to date. +scons>>> build foo.out +scons: `foo.out' is up to date. +scons>>> +""" % locals() + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/taskmastertrace.py b/test/Interactive/taskmastertrace.py new file mode 100644 index 0000000..23b9ad9 --- /dev/null +++ b/test/Interactive/taskmastertrace.py @@ -0,0 +1,90 @@ +#!/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 --taskmastertrace= option to the "build" command +of --interactive mode. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +scons.send("build --taskmastertrace=- foo.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build foo.out\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> Taskmaster: 'foo.out': children: + ['foo.in'] + waiting on unfinished children: + ['foo.in'] +Taskmaster: 'foo.in': evaluating foo.in +Taskmaster: 'foo.out': children: + ['foo.in'] + evaluating foo.out +Copy("foo.out", "foo.in") +scons>>> Touch("2") +scons>>> scons: `foo.out' is up to date. +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/tree.py b/test/Interactive/tree.py new file mode 100644 index 0000000..96e7d4a --- /dev/null +++ b/test/Interactive/tree.py @@ -0,0 +1,91 @@ +#!/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 --interactive command line option to build +a target, rebuild it when the input changes, and not rebuild it when +the input doesn't change. + +Also tests that "scons" can be used as a synonym for "build". +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +test.write('foo.in', "foo.in 2\n") + +scons.send("build --tree=all foo.out\n") + +scons.send("scons 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('foo.out'), "foo.in 2\n") + + + +scons.send("build --debug=tree foo.out\n") + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +scons>>> Touch("1") +scons>>> Copy("foo.out", "foo.in") ++-foo.out + +-foo.in +scons>>> Touch("2") +scons>>> scons: `foo.out' is up to date. ++-foo.out + +-foo.in +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/unknown-command.py b/test/Interactive/unknown-command.py new file mode 100644 index 0000000..2b77378 --- /dev/null +++ b/test/Interactive/unknown-command.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 the error message when an unknown command is typed in. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +""") + +test.write('foo.in', "foo.in 1\n") + + + +scons = test.start(arguments = '-Q --interactive') + +scons.send("build foo.out 1\n") + +test.wait_for(test.workpath('1')) + +test.must_match(test.workpath('foo.out'), "foo.in 1\n") + + + +scons.send('this-is-an-unknown-command hello\n') + +expect_stdout = """\ +scons>>> Copy("foo.out", "foo.in") +Touch("1") +scons>>> *** Unknown command: this-is-an-unknown-command +scons>>> +""" + +test.finish(scons, stdout = expect_stdout) + + + +test.pass_test() diff --git a/test/Interactive/version.py b/test/Interactive/version.py new file mode 100644 index 0000000..84f70e8 --- /dev/null +++ b/test/Interactive/version.py @@ -0,0 +1,84 @@ +#!/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 the "version" subcommand. +""" + +import TestCmd +import TestSCons + +test = TestSCons.TestSCons(match = TestCmd.match_re) + +test.write('SConstruct', "") + + + +# Construct the standard copyright marker so it doesn't get replaced +# by the packaging build. +copyright_marker = '__' + 'COPYRIGHT' + '__' + +copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007' + +fmt = '(%s|Copyright \\(c\\) %s The SCons Foundation)\n' + +copyright_line = fmt % (copyright_marker, copyright_years) + + + +expect1 = """\ +scons>>> +scons>>> +""" + +expect2 = """\ +scons>>> +scons>>> +""" + +test.run(arguments = '-Q --interactive', + stdin = "version\nexit\n") + +# Windows may or may not print a line for the script version +# depending on whether it's invoked through scons.py or scons.bat. +expect1 = r"""scons>>> SCons by Steven Knight et al\.: +\tengine: v\S+, [^,]*, by \S+ on \S+ +%(copyright_line)sscons>>> +""" % locals() + +expect2 = r"""scons>>> SCons by Steven Knight et al\.: +\tscript: v\S+, [^,]*, by \S+ on \S+ +\tengine: v\S+, [^,]*, by \S+ on \S+ +%(copyright_line)sscons>>> +""" % locals() + +stdout = test.stdout() + '\n' +if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2): + print repr(stdout) + test.fail_test() + + + +test.pass_test() diff --git a/test/Java/JAR.py b/test/Java/JAR.py index f0951c6..ee552f4 100644 --- a/test/Java/JAR.py +++ b/test/Java/JAR.py @@ -120,21 +120,11 @@ test.run(arguments='classes.jar') test.must_match('classes.jar', 'cvfm classes.jar foo.mf -C testdir bar.class\n') -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('jar', ENV=ENV): - where_jar = test.detect('JAR', 'jar', ENV=ENV) -else: - where_jar = test.where_is('jar') -if not where_jar: - test.skip_test("Could not find Java jar, skipping test(s).\n") + + +where_javac, java_version = test.java_where_javac() +where_jar = test.java_where_jar() + test.write("wrapper.py", """\ diff --git a/test/Java/JARCHDIR.py b/test/Java/JARCHDIR.py index f7d9fca..a3f2ec4 100644 --- a/test/Java/JARCHDIR.py +++ b/test/Java/JARCHDIR.py @@ -40,21 +40,8 @@ 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: - 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('jar', ENV=ENV): - where_jar = test.detect('JAR', 'jar', ENV=ENV) -else: - where_jar = test.where_is('jar') -if not where_jar: - test.skip_test("Could not find Java jar, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() +where_jar = test.java_where_jar() diff --git a/test/Java/JARFLAGS.py b/test/Java/JARFLAGS.py index 3939d98..03a222b 100644 --- a/test/Java/JARFLAGS.py +++ b/test/Java/JARFLAGS.py @@ -33,21 +33,10 @@ test = TestSCons.TestSCons() test.subdir('src') -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('jar', ENV=ENV): - where_jar = test.detect('JAR', 'jar', ENV=ENV) -else: - where_jar = test.where_is('jar') -if not where_jar: - test.skip_test("Could not find Java jar, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() +where_jar = test.java_where_jar() + + test.write('SConstruct', """ env = Environment(tools = ['javac', 'jar'], @@ -75,9 +64,9 @@ public class Example1 expect = test.wrap_stdout("""\ %(where_javac)s -d classes -sourcepath src src/Example1\.java -%(where_jar)s cvf test.jar classes/src/Example1\.class +%(where_jar)s cvf test.jar -C classes src/Example1\.class .* -adding: classes/src/Example1\.class.* +adding: src/Example1\.class.* """ % locals()) expect = string.replace(expect, '/', os.sep) diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py index 7723224..5962b94 100644 --- a/test/Java/JAVABOOTCLASSPATH.py +++ b/test/Java/JAVABOOTCLASSPATH.py @@ -38,21 +38,8 @@ _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") +where_javac, java_version = test.java_where_javac() +where_javah = test.java_where_javah() test.write('SConstruct', """ env = Environment(tools = ['javac', 'javah'], diff --git a/test/Java/JAVACFLAGS.py b/test/Java/JAVACFLAGS.py index 045fb7b..e287054 100644 --- a/test/Java/JAVACFLAGS.py +++ b/test/Java/JAVACFLAGS.py @@ -31,14 +31,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: - where_javac = test.where_is('javac') -if not where_javac: - test.skip_test("Could not find Java javac, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() test.subdir('src') diff --git a/test/Java/JAVACLASSPATH.py b/test/Java/JAVACLASSPATH.py index 0ae7dea..11f7c2c 100644 --- a/test/Java/JAVACLASSPATH.py +++ b/test/Java/JAVACLASSPATH.py @@ -36,21 +36,8 @@ _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") +where_javac, java_version = test.java_where_javac() +where_javah = test.java_where_javah() test.write('SConstruct', """ env = Environment(tools = ['javac', 'javah'], diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py index ecd3737..95abd33 100644 --- a/test/Java/JAVAH.py +++ b/test/Java/JAVAH.py @@ -24,9 +24,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os +import os.path import string -import sys + import TestSCons _python_ = TestSCons._python_ @@ -95,21 +95,11 @@ line 3 -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") +where_javac, java_version = test.java_where_javac() +where_javah = test.java_where_javah() -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 java_version: + java_version = repr(java_version) @@ -125,6 +115,9 @@ test.write('SConstruct', """ foo = Environment(tools = ['javac', 'javah', 'install'], JAVAC = r'%(where_javac)s', JAVAH = r'%(where_javah)s') +jv = %(java_version)s +if jv: + foo['JAVAVERSION'] = jv javah = foo.Dictionary('JAVAH') bar = foo.Clone(JAVAH = r'%(_python_)s wrapper.py ' + javah) foo.Java(target = 'class1', source = 'com/sub/foo') diff --git a/test/Java/JAVASOURCEPATH.py b/test/Java/JAVASOURCEPATH.py index 069e228..87e90ad 100644 --- a/test/Java/JAVASOURCEPATH.py +++ b/test/Java/JAVASOURCEPATH.py @@ -36,14 +36,7 @@ _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") +where_javac, java_version = test.java_where_javac() test.write('SConstruct', """ env = Environment(tools = ['javac', 'javah'], diff --git a/test/Java/Java-1.4.py b/test/Java/Java-1.4.py index 3d3d47a..3c0e1ed 100644 --- a/test/Java/Java-1.4.py +++ b/test/Java/Java-1.4.py @@ -38,14 +38,7 @@ _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") +where_javac, java_version = test.java_where_javac('1.4') @@ -234,10 +227,10 @@ public class NestedExample { public NestedExample() { - Thread t = new Thread() { + new Thread() { public void start() { - Thread t = new Thread() { + new Thread() { public void start() { try {Thread.sleep(200);} @@ -256,7 +249,7 @@ public class NestedExample public static void main(String argv[]) { - NestedExample e = new NestedExample(); + new NestedExample(); } } """) @@ -268,7 +261,7 @@ public class NestedExample test.write(['src5', 'TestSCons.java'], """\ class TestSCons { public static void main(String[] args) { - Foo[] fooArray = new Foo[] { new Foo() }; + new Foo(); } } @@ -355,12 +348,16 @@ def classes_must_match(dir, expect): global failed got = get_class_files(test.workpath(dir)) if expect != got: - sys.stderr.write("Expected the following class files in '%s':\n" % dir) - for c in expect: - sys.stderr.write(' %s\n' % c) - sys.stderr.write("Got the following class files in '%s':\n" % dir) - for c in got: - sys.stderr.write(' %s\n' % c) + missing = set(expect) - set(got) + if missing: + sys.stderr.write("Missing the following class files from '%s':\n" % dir) + for c in missing: + sys.stderr.write(' %s\n' % c) + unexpected = set(got) - set(expect) + if unexpected: + sys.stderr.write("Found the following unexpected class files in '%s':\n" % dir) + for c in unexpected: + sys.stderr.write(' %s\n' % c) failed = 1 def classes_must_not_exist(dir, expect): diff --git a/test/Java/Java-1.5.py b/test/Java/Java-1.5.py index 4ac3d96..f6d93c7 100644 --- a/test/Java/Java-1.5.py +++ b/test/Java/Java-1.5.py @@ -38,15 +38,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -ENV = test.java_ENV() -ENV['PATH'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11/bin' + os.pathsep + os.environ['PATH'] - -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") +where_javac, java_version = test.java_where_javac('1.5') @@ -235,10 +227,10 @@ public class NestedExample { public NestedExample() { - Thread t = new Thread() { + new Thread() { public void start() { - Thread t = new Thread() { + new Thread() { public void start() { try {Thread.sleep(200);} @@ -257,7 +249,7 @@ public class NestedExample public static void main(String argv[]) { - NestedExample e = new NestedExample(); + new NestedExample(); } } """) diff --git a/test/Java/Java-1.6.py b/test/Java/Java-1.6.py index f2b629a..5bd8e2f 100644 --- a/test/Java/Java-1.6.py +++ b/test/Java/Java-1.6.py @@ -38,15 +38,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -ENV = test.java_ENV() -ENV['PATH'] = '/usr/lib/jvm/java-6-sun-1.6.0.00/bin' + os.pathsep + os.environ['PATH'] - -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") +where_javac, java_version = test.java_where_javac('1.6') @@ -235,10 +227,10 @@ public class NestedExample { public NestedExample() { - Thread t = new Thread() { + new Thread() { public void start() { - Thread t = new Thread() { + new Thread() { public void start() { try {Thread.sleep(200);} @@ -257,7 +249,7 @@ public class NestedExample public static void main(String argv[]) { - NestedExample e = new NestedExample(); + new NestedExample(); } } """) diff --git a/test/Java/RMIC.py b/test/Java/RMIC.py index 2ab1804..f9721c2 100644 --- a/test/Java/RMIC.py +++ b/test/Java/RMIC.py @@ -92,21 +92,8 @@ line 3 test.fail_test(test.read(['outdir', 'test2.class']) != "test2.JAVA\nline 3\n") -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 non-simulated test(s).\n") - -if test.detect_tool('rmic', ENV=ENV): - where_rmic = test.detect('RMIC', 'rmic', ENV=ENV) -else: - where_rmic = test.where_is('rmic') -if not where_rmic: - test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n") +where_javac, java_version = test.java_where_javac() +where_rmic = test.java_where_rmic() test.write("wrapper.py", """\ import os @@ -319,15 +306,20 @@ test.run(arguments = '.') test.fail_test(test.read('wrapper.out') != "wrapper.py %s -d outdir2 -classpath class2 com.sub.bar.Example3 com.sub.bar.Example4\n" % where_rmic) -test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class'))) - -test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class'))) +test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class')) +test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class')) +test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class')) +test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class')) + +# We used to check for _Skel.class files as well, but they're not +# generated by default starting with Java 1.5, and they apparently +# haven't been needed for a while. Don't bother looking, even if we're +# running Java 1.4. If we think they're needed but they don't exist +# the test.up_to_date() call below will detect it. +#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class')) +#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class')) +#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class')) +#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class')) test.up_to_date(arguments = '.') diff --git a/test/Java/RMICCOM.py b/test/Java/RMICCOM.py index ed5e0d6..e8a5655 100644 --- a/test/Java/RMICCOM.py +++ b/test/Java/RMICCOM.py @@ -40,9 +40,9 @@ test.subdir('src') -out_file1 = os.path.join('out', 'file1', 'class_Skel.class') -out_file2 = os.path.join('out', 'file2', 'class_Skel.class') -out_file3 = os.path.join('out', 'file3', 'class_Skel.class') +out_file1 = os.path.join('out', 'file1', 'class_Stub.class') +out_file2 = os.path.join('out', 'file2', 'class_Stub.class') +out_file3 = os.path.join('out', 'file3', 'class_Stub.class') diff --git a/test/Java/RMICCOMSTR.py b/test/Java/RMICCOMSTR.py index 5a451eb..a92bac5 100644 --- a/test/Java/RMICCOMSTR.py +++ b/test/Java/RMICCOMSTR.py @@ -41,9 +41,9 @@ test.subdir('src') -out_file1 = os.path.join('out', 'file1', 'class_Skel.class') -out_file2 = os.path.join('out', 'file2', 'class_Skel.class') -out_file3 = os.path.join('out', 'file3', 'class_Skel.class') +out_file1 = os.path.join('out', 'file1', 'class_Stub.class') +out_file2 = os.path.join('out', 'file2', 'class_Stub.class') +out_file3 = os.path.join('out', 'file3', 'class_Stub.class') diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index d185b4d..9cac759 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -33,22 +33,8 @@ import TestSCons test = TestSCons.TestSCons() -# This test requires javac and swig -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") +where_javac, java_version = test.java_where_javac() +where_javah = test.java_where_javah() swig = test.where_is('swig') if not swig: diff --git a/test/Java/no-JARCHDIR.py b/test/Java/no-JARCHDIR.py new file mode 100644 index 0000000..795689c --- /dev/null +++ b/test/Java/no-JARCHDIR.py @@ -0,0 +1,122 @@ +#!/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 Jar() behavior when we have no JARCHDIR set (it should +automatically use the classdir that was deduced from the Java() call) +and when we explicity set it to None (it should not use the Java() +classdir attribute at all). +""" + +import string + +import TestSCons + +test = TestSCons.TestSCons() + +where_javac, java_version = test.java_where_javac() +where_jar = test.java_where_jar() + +test.subdir('src') + + + +test.write(['src', 'a.java'], """\ +package foo.bar; +public class a {} +""") + +test.write(['src', 'b.java'], """\ +package foo.bar; +public class b {} +""") + + + +test.write('SConstruct', """\ +env = Environment(tools = ['javac', 'jar'], + JAVAC = r'%(where_javac)s', + JAR = r'%(where_jar)s') + +jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src')) +""" % locals()) + +test.run(arguments = '.') + + + +test.run(program = where_jar, arguments = 'tf x.jar') + +expect = """\ +foo/bar/a.class +foo/bar/b.class +""" + +if string.find(test.stdout(), expect) == -1: + print "Did not find expected string in standard output." + print "Expected ==========================================================" + print expect + print "Output ============================================================" + print test.stdout() + test.fail_test() + + + +test.run(arguments = '-c') + + + +test.write('SConstruct', """\ +env = Environment(tools = ['javac', 'jar'], + JAVAC = r'%(where_javac)s', + JAR = r'%(where_jar)s', + JARCHDIR = None) + +jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src')) +""" % locals()) + +test.run(arguments = '.') + + + +test.run(program = where_jar, arguments = 'tf x.jar') + +expect = """\ +classes/foo/bar/a.class +classes/foo/bar/b.class +""" + +if string.find(test.stdout(), expect) == -1: + print "Did not find expected string in standard output." + print "Expected ==========================================================" + print expect + print "Output ============================================================" + print test.stdout() + test.fail_test() + + + +test.pass_test() diff --git a/test/Java/source-files.py b/test/Java/source-files.py index 8d2506f..63d1d92 100644 --- a/test/Java/source-files.py +++ b/test/Java/source-files.py @@ -35,14 +35,7 @@ _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") +where_javac, java_version = test.java_where_javac() test.write('SConstruct', """ diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py index 8df5e09..5477a2d 100644 --- a/test/Java/swig-dependencies.py +++ b/test/Java/swig-dependencies.py @@ -34,29 +34,14 @@ 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: - 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") - -if test.detect_tool('jar', ENV=ENV): - where_jar = test.detect('JAR', 'jar', ENV=ENV) -else: - where_jar = test.where_is('jar') -if not where_jar: - test.skip_test("Could not find Java jar, skipping test(s).\n") +swig = test.where_is('swig') +if not swig: + test.skip_test('Can not find installed "swig", skipping test.\n') + +where_javac, java_version = test.java_where_javac() +where_javah = test.java_where_javah() +where_jar = test.java_where_jar() test.subdir(['foo'], ['java'], diff --git a/test/LIBPATH.py b/test/Libs/LIBPATH.py index 7fd4f9b..7fd4f9b 100644 --- a/test/LIBPATH.py +++ b/test/Libs/LIBPATH.py diff --git a/test/LIBPREFIX.py b/test/Libs/LIBPREFIX.py index a71e967..a71e967 100644 --- a/test/LIBPREFIX.py +++ b/test/Libs/LIBPREFIX.py diff --git a/test/LIBPREFIXES.py b/test/Libs/LIBPREFIXES.py index 1e5d6c2..1e5d6c2 100644 --- a/test/LIBPREFIXES.py +++ b/test/Libs/LIBPREFIXES.py diff --git a/test/LIBS.py b/test/Libs/LIBS.py index e9f6545..e9f6545 100644 --- a/test/LIBS.py +++ b/test/Libs/LIBS.py diff --git a/test/LIBSUFFIX.py b/test/Libs/LIBSUFFIX.py index a71e967..a71e967 100644 --- a/test/LIBSUFFIX.py +++ b/test/Libs/LIBSUFFIX.py diff --git a/test/LIBSUFFIXES.py b/test/Libs/LIBSUFFIXES.py index 29cbb18..29cbb18 100644 --- a/test/LIBSUFFIXES.py +++ b/test/Libs/LIBSUFFIXES.py diff --git a/test/Library.py b/test/Libs/Library.py index 4bcb2c7..4bcb2c7 100644 --- a/test/Library.py +++ b/test/Libs/Library.py diff --git a/test/SHLIBPREFIX.py b/test/Libs/SHLIBPREFIX.py index 87b92fa..87b92fa 100644 --- a/test/SHLIBPREFIX.py +++ b/test/Libs/SHLIBPREFIX.py diff --git a/test/SHLIBSUFFIX.py b/test/Libs/SHLIBSUFFIX.py index dc88e3b..dc88e3b 100644 --- a/test/SHLIBSUFFIX.py +++ b/test/Libs/SHLIBSUFFIX.py diff --git a/test/SharedLibrary.py b/test/Libs/SharedLibrary.py index f8447ca..f8447ca 100644 --- a/test/SharedLibrary.py +++ b/test/Libs/SharedLibrary.py diff --git a/test/Libs/SharedLibraryIxes.py b/test/Libs/SharedLibraryIxes.py new file mode 100644 index 0000000..f9d1471 --- /dev/null +++ b/test/Libs/SharedLibraryIxes.py @@ -0,0 +1,261 @@ +#!/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 we can build shared libraries and link against shared +libraries that have non-standard library prefixes and suffixes. +""" + +import re +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import sys +isWindows = sys.platform == 'win32' + +env = Environment() + +# Make sure that the shared library can be located at runtime. +env.Append(RPATH=['.']) +env.Append(LIBPATH=['.']) + +# We first bake the LIBSUFFIXES, so that it will not change as a +# side-effect of changing SHLIBSUFFIX. +env['LIBSUFFIXES'] = map( env.subst, env.get('LIBSUFFIXES', [])) + +weird_prefixes = ['libXX', 'libYY'] + +if isWindows: + weird_suffixes = ['.xxx', '.yyy', '.xxx.dll', '.yyy.dll'] + env.Append(CCFLAGS = '/MD') +elif env['PLATFORM'] == 'darwin': + weird_suffixes = ['.xxx.dylib', '.yyy.dylib'] +else: + weird_suffixes = ['.xxx.so', '.yyy.so'] + +shlibprefix = env.subst('$SHLIBPREFIX') +shlibsuffix = env.subst('$SHLIBSUFFIX') + +progprefix = env.subst('$PROGPREFIX') +progsuffix = env.subst('$PROGSUFFIX') + +goo_obj = env.SharedObject(source='goo.c') +foo_obj = env.SharedObject(source='foo.c') +prog_obj = env.SharedObject(source='prog.c') + +# +# The following functions define all the different way that one can +# use link againt a shared library. +# +def nodeInSrc(source, lib, libname): + return (source+lib, '') + +def pathInSrc(source, lib, libname): + return (source+map(str,lib), '') + +def nodeInLib(source, lib, libname): + return (source, lib) + +def pathInLib(source, lib, libname): + return (source, map(str,lib)) + +def nameInLib(source, lib, libname): + # NOTE: libname must contain both the proper prefix and suffix. + # + # When using non-standard prefixes and suffixes, one has to + # provide the full name of the library since scons can not know + # which of the non-standard extension to use. + # + # Note that this is not necessarally SHLIBPREFIX and + # SHLIBSUFFIX. These are the ixes of the target library, not the + # ixes of the library that we are linking againt. + return (source, libname) + +libmethods = [ + nodeInSrc, pathInSrc, nodeInLib, pathInLib, + nameInLib ] + +def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw): + '''Build a target using a given builder while linking againt a given + library using a specified method for linking against the library.''' + + # On Windows, we have to link against the .lib file. + if isWindows: + for l in lib: + if str(l)[-4:] == '.lib': + lib = [l] + break + (source, LIBS) = method(source, lib, libname) + #build = builder(target=target, source=source, LIBS=LIBS, **kw) + kw = kw.copy() + kw['target'] = target + kw['source'] = source + kw['LIBS'] = LIBS + build = apply(builder, (), kw) + + # Check that the build target depends on at least one of the + # library target. + found_dep = False + children = build[0].children() + for l in lib: + if l in children: + found_dep = True + break; + assert found_dep, \ + "One of %s not found in %s, method=%s, libname=%s, shlibsuffix=%s" % \ + (map(str,lib), map(str, build[0].children()), method.__name__, libname, shlibsuffix) + return build + +def prog(i, + goomethod, goolibprefix, goolibsuffix, + foomethod, foolibprefix, foolibsuffix): + '''Build a program + + The program links against a shared library foo which itself links + against a shared library goo. The libraries foo and goo can use + arbitrary library prefixes and suffixes.''' + + goo_name = goolibprefix+'goo'+str(i)+goolibsuffix + foo_name = foolibprefix+'foo'+str(i)+foolibsuffix + prog_name = progprefix+'prog'+str(i)+progsuffix + + print 'Prog: %d, %s, %s, %s' % (i, goo_name, foo_name, prog_name) + + # On Windows, we have to link against the .lib file. + if isWindows: + goo_libname = goolibprefix+'goo'+str(i)+'.lib' + foo_libname = foolibprefix+'foo'+str(i)+'.lib' + else: + goo_libname = goo_name + foo_libname = foo_name + + goo_lib = env.SharedLibrary( + goo_name, goo_obj, SHLIBSUFFIX=goolibsuffix) + foo_lib = buildAndlinkAgainst( + env.SharedLibrary, foo_name, foo_obj, + goomethod, goo_lib, goo_libname, SHLIBSUFFIX=foolibsuffix) + prog = buildAndlinkAgainst(env.Program, prog_name, prog_obj, + foomethod, foo_lib, foo_libname) + + +# +# Create the list of all possible permutations to test. +# +i = 0 +tests = [] +prefixes = [shlibprefix] + weird_prefixes +suffixes = [shlibsuffix] + weird_suffixes +for foolibprefix in prefixes: + for foolibsuffix in suffixes: + for foomethod in libmethods: + for goolibprefix in prefixes: + for goolibsuffix in suffixes: + for goomethod in libmethods: + tests.append( + (i, + goomethod, goolibprefix, goolibsuffix, + foomethod, foolibprefix, foolibsuffix)) + i = i + 1 + +# +# Pseudo-randomly choose 200 tests to run out of the possible +# tests. (Testing every possible permutation would take too long.) +# +import random +random.seed(123456) +try: + random.shuffle(tests) +except AttributeError: + pass + +for i in range(200): + apply(prog, tests[i]) + +""") + +test.write('goo.c', r""" +#include <stdio.h> + +#ifdef _WIN32 +#define EXPORT __declspec( dllexport ) +#else +#define EXPORT +#endif + +EXPORT void +goo(void) +{ + printf("goo.c\n"); +} +""") + +test.write('foo.c', r""" +#include <stdio.h> + +#ifdef _WIN32 +#define EXPORT __declspec( dllexport ) +#else +#define EXPORT +#endif + +EXPORT void +foo(void) +{ + goo(); + printf("foo.c\n"); +} +""") + +test.write('prog.c', r""" +#include <stdio.h> + +void foo(void); +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + foo(); + printf("prog.c\n"); + return 0; +} +""") + +test.run(arguments = '.', + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) + +tests = re.findall(r'Prog: (\d+), (\S+), (\S+), (\S+)', test.stdout()) +expected = "goo.c\nfoo.c\nprog.c\n" + +for t in tests: + test.must_exist(t[1]) + test.must_exist(t[2]) + test.must_exist(t[3]) + test.run(program = test.workpath(t[3]), stdout=expected) + +test.pass_test() diff --git a/test/LoadableModule.py b/test/LoadableModule.py index 5243fbf..4a8e1ed 100644 --- a/test/LoadableModule.py +++ b/test/LoadableModule.py @@ -105,7 +105,8 @@ test.run(arguments = '.', if string.find(sys.platform, 'darwin') != -1: test.run(program='/usr/bin/file', arguments = "foo1", - stdout="foo1: Mach-O bundle ppc\n") + match = TestCmd.match_re, + stdout="foo1: Mach-O bundle (ppc|i386)\n") if sys.platform in platforms_with_dlopen: os.environ['LD_LIBRARY_PATH'] = test.workpath() diff --git a/test/MSVC/pdb-manifest.py b/test/MSVC/pdb-manifest.py new file mode 100644 index 0000000..00f3ee2 --- /dev/null +++ b/test/MSVC/pdb-manifest.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 .pdb files work correctly in conjunction with manifest files. +""" + +import sys + +import TestSCons + +_exe = TestSCons._exe +_dll = TestSCons._dll +_lib = TestSCons._lib + +test = TestSCons.TestSCons() + +if sys.platform != 'win32': + msg = "Skipping Visual C/C++ test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) + +test.write('SConstruct', """\ +env = Environment() + +env['WINDOWS_INSERT_DEF'] = True +env['WINDOWS_INSERT_MANIFEST'] = True +env['PDB'] = '${TARGET.base}.pdb' +env.Program('test', 'test.cpp') +env.SharedLibrary('sharedlib', 'test.cpp') +env.StaticLibrary('staticlib', 'test.cpp') +""") + +test.write('test.cpp', """\ +#include <stdio.h> +#include <stdlib.h> +int +main(int argc, char *argv) +{ + printf("test.cpp\\n"); + exit (0); +} +""") + +test.write('sharedlib.def', """\ +""") + +test.run(arguments = '.') + +test.must_exist('test%s' % _exe) +test.must_exist('test.pdb') + +test.must_exist('sharedlib%s' % _dll) +test.must_exist('sharedlib.pdb') + +test.must_exist('staticlib%s' % _lib) +test.must_not_exist('staticlib.pdb') + +test.pass_test() diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py index 2878136..9936490 100644 --- a/test/QT/moc-from-header.py +++ b/test/QT/moc-from-header.py @@ -55,6 +55,8 @@ test.Qt_create_SConstruct('SConstruct') test.write('SConscript', """\ Import("env") env.Program(target = 'aaa', source = 'aaa.cpp') +if env['PLATFORM'] == 'darwin': + env.Install('.', 'qt/lib/libmyqt.dylib') """) test.write('aaa.cpp', r""" @@ -67,7 +69,7 @@ test.write('aaa.h', r""" void aaa(void) Q_OBJECT; """) -test.run(arguments = aaa_exe) +test.run() test.up_to_date(options = '-n', arguments=aaa_exe) diff --git a/test/QT/warnings.py b/test/QT/warnings.py index baa1e6f..ef94dd6 100644 --- a/test/QT/warnings.py +++ b/test/QT/warnings.py @@ -59,9 +59,10 @@ match12 = r""" scons: warning: Generated moc file 'aaa.moc' is not included by 'aaa.cpp' """ + TestSCons.file_expr -# In case 'ar' gives a warning about creating a library. -test.fail_test(not test.match_re(test.stderr(), match12) and \ - not test.match_re(test.stderr(), match12 + ".+\n")) +if not re.search(match12, test.stderr()): + print "Did not find expected regular expression in stderr:" + print test.stderr() + test.fail_test() os.environ['QTDIR'] = test.QT diff --git a/test/Repository/Java.py b/test/Repository/Java.py index 6e8bbd6..67ef605 100644 --- a/test/Repository/Java.py +++ b/test/Repository/Java.py @@ -37,18 +37,8 @@ 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") - -where_java = test.where_is('java') -if not where_java: - test.skip_test("Could not find Java java, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() +where_java = test.java_where_java() java = where_java @@ -115,6 +105,8 @@ test.writable('repository', 0) # test.run(chdir = 'work1', options = opts, arguments = ".") +os.environ['JAVA_HOME'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11' + test.run(program = java, arguments = "-cp %s Foo1" % work1_classes, stdout = "rep1/src/Foo1.java\n") diff --git a/test/Repository/JavaH.py b/test/Repository/JavaH.py index fc87904..258d9bd 100644 --- a/test/Repository/JavaH.py +++ b/test/Repository/JavaH.py @@ -37,25 +37,9 @@ 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") - -where_java = test.where_is('java') -if not where_java: - test.skip_test("Could not find Java java, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() +where_java = test.java_where_java() +where_javah = test.java_where_javah() java = where_java javac = where_javac diff --git a/test/Repository/LIBPATH.py b/test/Repository/LIBPATH.py index 9216a8b..0f80ace 100644 --- a/test/Repository/LIBPATH.py +++ b/test/Repository/LIBPATH.py @@ -59,6 +59,13 @@ def write_LIBDIRFLAGS(env, target, source): return 0 env_zzz.Command('zzz.out', aaa_exe, write_LIBDIRFLAGS) env_yyy.Command('yyy.out', bbb_exe, write_LIBDIRFLAGS) + +if env_yyy['PLATFORM'] == 'darwin': + # The Mac OS X linker complains about nonexistent directories + # specified as -L arguments. Suppress its warnings so we don't + # treat the warnings on stderr as a failure. + env_yyy.Append(LINKFLAGS=['-w']) + env_zzz.Append(LINKFLAGS=['-w']) """) test.write(['work', 'aaa.c'], r""" diff --git a/test/Repository/RMIC.py b/test/Repository/RMIC.py index ebe6a83..bf8edff 100644 --- a/test/Repository/RMIC.py +++ b/test/Repository/RMIC.py @@ -28,34 +28,17 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Test building Java applications when using Repositories. """ -import os import string -import sys + 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('rmic', ENV=ENV): - where_rmic = test.detect('RMIC', 'rmic', ENV=ENV) -else: - where_rmic = test.where_is('rmic') -if not where_rmic: - test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n") - -where_java = test.where_is('java') -if not where_java: - test.skip_test("Could not find Java java, skipping test(s).\n") +where_javac, java_version = test.java_where_javac() +where_java = test.java_where_java() +where_rmic = test.java_where_rmic() java = where_java javac = where_javac @@ -185,15 +168,20 @@ test.run(chdir = 'work1', options = opts, arguments = ".") # see that they were built from the proper rep1 sources, but I don't # know how to do that with RMI, so punt for now. -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) + +# We used to check for _Skel.class files as well, but they're not +# generated by default starting with Java 1.5, and they apparently +# haven't been needed for a while. Don't bother looking, even if we're +# running Java 1.4. If we think they're needed but they don't exist +# the variou test.up_to_date() calls below will detect it. +#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) +#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')) +#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) test.up_to_date(chdir = 'work1', options = opts, arguments = ".") @@ -294,15 +282,15 @@ test.fail_test(string.find(test.stdout(), ' com.sub.foo.Foo1 com.sub.foo.Foo2') # see that they were built from the proper work1 sources, but I don't # know how to do that with RMI, so punt for now. -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) +test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')) +#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) +#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')) +#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) test.up_to_date(chdir = 'work1', options = opts, arguments = ".") @@ -315,10 +303,11 @@ test.run(chdir = 'rep1', options = opts, arguments = ".") # see that they were built from the proper work1 sources, but I don't # know how to do that with RMI, so punt for now. -test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) + +#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')) +#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) test.up_to_date(chdir = 'rep1', options = opts, arguments = ".") @@ -343,13 +332,16 @@ Local(rmi_classes) test.run(chdir = 'work3', options = opts, arguments = ".") -test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class'))) -test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class'))) -test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class'))) +test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class')) +test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class')) +test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class')) + +test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')) +test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')) + +#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')) +#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')) -test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))) -test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))) -test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))) +test.up_to_date(chdir = 'work3', options = opts, arguments = ".") test.pass_test() diff --git a/test/SWIG/module-parens.py b/test/SWIG/module-parens.py new file mode 100644 index 0000000..0d89ebe --- /dev/null +++ b/test/SWIG/module-parens.py @@ -0,0 +1,102 @@ +#!/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 handle %module(directors="1") statements, both with and +without white space before the opening parenthesis. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +swig = test.where_is('swig') + +if not swig: + test.skip_test('Can not find installed "swig", skipping test.\n') + +python_include_dir = test.get_python_inc() + +test.write(['SConstruct'], """\ +env = Environment(SWIGFLAGS = '-python', + CPPPATH=r"%(python_include_dir)s") + +import sys +if sys.version[0] == '1': + # SWIG requires the -classic flag on pre-2.0 Python versions. + env.Append(SWIGFLAGS = ' -classic') + +env.SharedLibrary('test1.so', 'test1.i') +env.SharedLibrary('test2.so', 'test2.i') +""" % locals()) + +test.write(['test1.cc'], """\ +int test1func() +{ + return 0; +} +""") + +test.write(['test1.h'], """\ +int test1func(); +""") + +test.write(['test1.i'], """\ +%module(directors="1") test1 + +%{ +#include "test1.h" +%} + +%include "test1.h" +""") + +test.write(['test2.cc'], """\ +int test2func() +{ + return 0; +} +""") + +test.write(['test2.h'], """\ +int test2func(); +""") + +test.write(['test2.i'], """\ +%module (directors="1") test2 + +%{ +#include "test2.h" +%} + +%include "test2.h" +""") + +test.run(arguments = '.') + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py index dd2c938..ef91189 100644 --- a/test/Scanner/generated.py +++ b/test/Scanner/generated.py @@ -318,10 +318,10 @@ def write_out(file, dict): f.write(file + ": " + str(dict[k]) + "\\n") f.close() -orig_function = CScan.scan +orig_function = CScan.__call__ -def MyCScan(node, paths, orig_function=orig_function): - deps = orig_function(node, paths) +def MyCScan(node, paths, cwd, orig_function=orig_function): + deps = orig_function(node, paths, cwd) global Scanned n = str(node) @@ -333,7 +333,7 @@ def MyCScan(node, paths, orig_function=orig_function): return deps -CScan.scan = MyCScan +CScan.__call__ = MyCScan env = Environment(CPPPATH = ".") l = env.StaticLibrary("g", Split("libg_1.c libg_2.c libg_3.c")) diff --git a/test/TEX/build_dir_dup0.py b/test/TEX/build_dir_dup0.py new file mode 100644 index 0000000..8035957 --- /dev/null +++ b/test/TEX/build_dir_dup0.py @@ -0,0 +1,257 @@ +#!/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 creation of a fully-featured TeX document (with bibliography +and index) in a build_dir. + +Test courtesy Rob Managan. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +latex = test.where_is('latex') +dvipdf = test.where_is('dvipdf') +makeindex = test.where_is('makeindex') +bibtex = test.where_is('bibtex') +if not latex or not makeindex or not bibtex or not dvipdf: + test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or dvipdf; skipping test.\n") + +test.subdir(['docs']) + + +test.write(['SConstruct'], """\ +import os + +env = Environment(ENV = { 'PATH' : os.environ['PATH'] }, + TOOLS = ['tex', 'latex', 'dvipdf']) +Export(['env']) + +SConscript(os.path.join('docs', 'SConscript'), + build_dir=os.path.join('mybuild','docs'), + duplicate=0) +""") + + +test.write(['docs', 'SConscript'], """\ +Import('env') + +test_dvi = env.DVI(source='test.tex') +testpdf = env.PDF(source=test_dvi) +""") + + +test.write(['docs', 'Fig1.ps'], """\ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: Fig1.fig +%%Creator: fig2dev Version 3.2 Patchlevel 4 +%%CreationDate: Tue Apr 25 09:56:11 2006 +%%BoundingBox: 0 0 98 98 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def + +end +save +newpath 0 98 moveto 0 0 lineto 98 0 lineto 98 98 lineto closepath clip newpath +-24.9 108.2 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/sc {scale} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/tr {translate} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06299 0.06299 sc +% +% Fig objects follow +% +7.500 slw +% Ellipse +n 1170 945 766 766 0 360 DrawEllipse gs col0 s gr + +$F2psEnd +rs +""") + + +test.write(['docs', 'Fig1.tex'], +r"""\begin{picture}(0,0)% +\includegraphics{Fig1.ps}% +\end{picture}% +\setlength{\unitlength}{4144sp}% +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +\begin{picture}(1548,1546)(397,-879) +\put(856,-196){\makebox(0,0)[lb]{\smash{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}center $r_0$}% +}}} +\end{picture} +""") + + +test.write(['docs', 'test.bib'], """\ +%% This BibTeX bibliography file was created using BibDesk. +%% http://bibdesk.sourceforge.net/ + +%% Saved with string encoding Western (ASCII) + +@techreport{AnAuthor:2006fk, + Author = {A. N. Author}, + Date-Added = {2006-11-15 12:51:30 -0800}, + Date-Modified = {2006-11-15 12:52:35 -0800}, + Institution = {none}, + Month = {November}, + Title = {A Test Paper}, + Year = {2006}} +""") + + +test.write(['docs', 'test.tex'], +r"""\documentclass{report} + +\usepackage{graphicx} +\usepackage{epsfig,color} % for .tex version of figures if we go that way + +\usepackage{makeidx} +\makeindex + +\begin{document} + +\title{Report Title} + +\author{A. N. Author} + +\maketitle + +\begin{abstract} +there is no abstract +\end{abstract} + +\tableofcontents +\listoffigures + +\chapter{Introduction} + +The introduction is short. + +\index{Acknowledgements} + +\section{Acknowledgements} + +The Acknowledgements are show as well \cite{AnAuthor:2006fk}. + +\index{Getting the Report} + +To get a hard copy of this report call me. + +\begin{figure}[htbp] +\begin{center} +\input{Fig1.tex} % testing figure variant that uses TeX labeling +\caption{Zone and Node indexing} +\label{fig1} +\end{center} +\end{figure} + +All done now. + +\bibliographystyle{unsrt} +\bibliography{test} +\newpage + +\printindex + +\end{document} +""") + + +# makeindex will write status messages to stderr (grrr...), so ignore it. +test.run(arguments = '.', stderr=None) + + +# All (?) the files we expect will get created in the build_dir +# (mybuild/docs) and not in the srcdir (docs). +files = [ + 'test.aux', + 'test.bbl', + 'test.blg', + 'test.dvi', + 'test.idx', + 'test.ilg', + 'test.ind', + 'test.lof', + 'test.log', + 'test.pdf', + 'test.toc', +] + +for f in files: + test.must_exist(['mybuild', 'docs', f]) + test.must_not_exist(['docs', f]) + + +test.pass_test() diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py index d4e2d79..686263d 100644 --- a/test/TEX/multi-run.py +++ b/test/TEX/multi-run.py @@ -28,6 +28,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Validate that both .tex and .ltx files can handle a LaTeX-style bibliography (by calling $BIBTEX to generate a .bbl file) and correctly re-run to resolve undefined references. + +Also verifies that package warnings are caught and re-run as needed. """ import string @@ -42,7 +44,7 @@ latex = test.where_is('latex') if not tex and not latex: test.skip_test("Could not find tex or latex; skipping test(s).\n") -test.subdir('work1', 'work2', 'work4') +test.subdir('work1', 'work2', 'work3', 'work4') input_file = r""" @@ -64,6 +66,62 @@ Hello world. \end{document} """ +input_file3 = r""" +\documentclass{article} +\usepackage{longtable} + +\begin{document} +As stated in the last paper, this is a bug-a-boo. +here is some more junk and another table +here is some more junk and another table + +\begin{longtable}[l]{rlll} + Isotope &\multicolumn{1}{c}{Abar} &Name\\ +\\ + 1001 &1.0078 &Proton &$p$\\ + 1002 &2.0141 &Deuterium &$d$\\ + 1003 &3.0170 &Tritium &$t$\\ + 2003 &3.0160 &Helium 3 &He$^3$\\ + 2004 &4.0026 &Helium 4 &He$^{4}$\\ +\end{longtable} + +and a closing comment + + These parameters and arrays are filled in when the parameter \textbf{iftnrates} + is set to 1: + +\begin{longtable}[l]{ll} +\\ +\textbf{nxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{pxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\ +\textbf{nxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{pxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{nxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{pxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\ +\textbf{nxxxx} &Total number of particles made by xxxx reaction\\ +\textbf{pxxxx} &Total number of particles made by xxxx reaction\\ +\\ +\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\ +\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\ +\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\ +\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\ +\\ +\textbf{reactot}(r) &Total number of reactions for reaction r\\ +\textbf{reacreg}(r,ir) &Total number of reactions for reaction r in region ir\\ +\end{longtable} + + +\end{document} +""" + bibfile = r""" @Article{X, author = "Mr. X", @@ -95,6 +153,20 @@ PDF( "foo.tex" ) print foo_log test.fail_test(1) + test.write(['work3', 'SConstruct'], """\ +DVI( "foo3.tex" ) +""") + + test.write(['work3', 'foo3.tex'], input_file3) + + test.run(chdir = 'work3', arguments = '.') + + foo_log = test.read(['work3', 'foo3.log']) + if string.find(foo_log, 'Rerun LaTeX') != -1: + print 'foo.log contains "Rerun LaTeX":' + print foo_log + test.fail_test(1) + if latex: @@ -117,6 +189,20 @@ PDF( "foo.ltx" ) print foo_log test.fail_test(1) + test.write(['work3', 'SConstruct'], """\ +DVI( "foo3.tex" ) +PDF( "foo3.tex" ) +""") + + test.write(['work3', 'foo3.tex'], input_file3) + + test.run(chdir = 'work3', arguments = '.') + + foo_log = test.read(['work3', 'foo3.log']) + if string.find(foo_log, 'Rerun LaTeX') != -1: + print 'foo.log contains "Rerun LaTeX":' + print foo_log + test.fail_test(1) test.write(['work4', 'SConstruct'], """\ diff --git a/test/YACC/live.py b/test/YACC/live.py index 4934570..0e5f156 100644 --- a/test/YACC/live.py +++ b/test/YACC/live.py @@ -103,13 +103,19 @@ graph: GRAPH_T %% """) +import sys +if sys.platform == 'darwin': + file_hpp = 'file.cpp.h' +else: + file_hpp = 'file.hpp' + test.write("hello.cpp", """\ -#include "file.hpp" +#include "%(file_hpp)s" int main() { } -""") +""" % locals()) test.write('foo.y', yacc % 'foo.y') diff --git a/test/build-errors.py b/test/build-errors.py deleted file mode 100644 index e25fbd5..0000000 --- a/test/build-errors.py +++ /dev/null @@ -1,223 +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 os -import string -import sys -import TestCmd -import TestSCons - -test = TestSCons.TestSCons() - -no_such_file = test.workpath("no_such_file") -not_executable = test.workpath("not_executable") - -test.write(not_executable, "\n") - -test.write("f1.in", "\n") -test.write("f2.in", "\n") -test.write("f3.in", "\n") - -test.write('SConstruct1', r""" -bld = Builder(action = '%s $SOURCES $TARGET') -env = Environment(BUILDERS = { 'bld' : bld }) -env.bld(target = 'f1', source = 'f1.in') -""" % string.replace(no_such_file, '\\', '\\\\')) - -test.run(arguments='-f SConstruct1 .', - stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1), - stderr = None, - status = 2) - -bad_command = """\ -Bad command or file name -""" - -unrecognized = """\ -'%s' is not recognized as an internal or external command, -operable program or batch file. -scons: *** [%s] Error 1 -""" - -unspecified = """\ -The name specified is not recognized as an -internal or external command, operable program or batch file. -scons: *** [%s] Error 1 -""" - -not_found_1 = """ -sh: %s: not found -scons: *** [%s] Error 1 -""" - -not_found_2 = """ -sh: %s: not found -scons: *** [%s] Error 1 -""" - -No_such = """\ -%s: No such file or directory -scons: *** [%s] Error 127 -""" - -cannot_execute = """\ -%s: cannot execute -scons *** [%s] Error 126 -""" - -Permission_denied = """\ -%s: Permission denied -scons: *** [%s] Error 126 -""" - -permission_denied = """\ -%s: permission denied -scons: *** [%s] Error 126 -""" - -is_a_directory = """\ -%s: is a directory -scons: *** [%s] Error 126 -""" - -test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) -if os.name == 'nt': - errs = [ - bad_command, - unrecognized % (no_such_file, 'f1'), - unspecified % 'f1' - ] - test.fail_test(not test.stderr() in errs) -else: - errs = [ - not_found_1 % (no_such_file, 'f1'), - not_found_2 % (no_such_file, 'f1'), - No_such % (no_such_file, 'f1'), - ] - error_message_not_found = 1 - for err in errs: - if string.find(test.stderr(), err) != -1: - error_message_not_found = None - break - test.fail_test(error_message_not_found) - -test.write('SConstruct2', r""" -bld = Builder(action = '%s $SOURCES $TARGET') -env = Environment(BUILDERS = { 'bld': bld }) -env.bld(target = 'f2', source = 'f2.in') -""" % string.replace(not_executable, '\\', '\\\\')) - -test.run(arguments='-f SConstruct2 .', - stdout = test.wrap_stdout("%s f2.in f2\n" % not_executable, error=1), - stderr = None, - status = 2) - -test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) -if os.name == 'nt': - errs = [ - bad_command, - unrecognized % (not_executable, 'f2'), - unspecified % 'f2' - ] - test.fail_test(not test.stderr() in errs) -else: - errs = [ - cannot_execute % (not_executable, 'f2'), - Permission_denied % (not_executable, 'f2'), - permission_denied % (not_executable, 'f2'), - ] - error_message_not_found = 1 - for err in errs: - if string.find(test.stderr(), err) != -1: - error_message_not_found = None - break - test.fail_test(error_message_not_found) - -test.write('SConstruct3', r""" -bld = Builder(action = '%s $SOURCES $TARGET') -env = Environment(BUILDERS = { 'bld' : bld }) -env.bld(target = 'f3', source = 'f3.in') -""" % string.replace(test.workdir, '\\', '\\\\')) - -test.run(arguments='-f SConstruct3 .', - stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1), - stderr = None, - status = 2) - -test.description_set("Incorrect STDERR:\n%s\n" % test.stderr()) -if os.name == 'nt': - errs = [ - bad_command, - unrecognized % (test.workdir, 'f3'), - unspecified % 'f3' - ] - test.fail_test(not test.stderr() in errs) -else: - errs = [ - cannot_execute % (not_executable, 'f3'), - is_a_directory % (test.workdir, 'f3'), - ] - error_message_not_found = 1 - for err in errs: - if string.find(test.stderr(), err) != -1: - error_message_not_found = None - break - test.fail_test(error_message_not_found) - -test.write('SConstruct4', r""" -env = Environment() -env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE')) -env.InstallAs('test2.out', 'test.out') -# Mark test2.out as precious so we'll handle the exception in -# FunctionAction() rather than when the target is cleaned before building. -env.Precious('test2.out') -env.Default('test2.out') -""") - -test.write('test.in', "test.in 1\n") - -test.run(arguments = '-f SConstruct4 .') - -test.write('test.in', "test.in 2\n") - -test.writable('test2.out', 0) -f = open(test.workpath('test2.out')) - -test.run(arguments = '-f SConstruct4 .', - stderr = None, - status = 2) - -f.close() -test.writable('test2.out', 1) - -test.description_set("Incorrect STDERR:\n%s" % test.stderr()) -errs = [ - "scons: *** [test2.out] test2.out: Permission denied\n", - "scons: *** [test2.out] test2.out: permission denied\n", -] -test.fail_test(test.stderr() not in errs) - -test.pass_test() diff --git a/test/builderrors.py b/test/builderrors.py index 8c7c4ab..28c9a0a 100644 --- a/test/builderrors.py +++ b/test/builderrors.py @@ -145,10 +145,10 @@ test.fail_test(string.find(err, 'Exception') != -1 or \ # Test bad shell ('./one' is a dir, so it can't be used as a shell). # This will also give an exit status not in exitvalmap, -# with error "Permission denied". +# with error "Permission denied" or "No such file or directory". test.write('SConstruct', """ env=Environment() -if env['PLATFORM'] == 'posix': +if env['PLATFORM'] in ('posix', 'darwin'): from SCons.Platform.posix import fork_spawn env['SPAWN'] = fork_spawn env['SHELL'] = 'one' @@ -157,10 +157,14 @@ env.Command(target='badshell.out', source=[], action='foo') test.run(status=2, stderr=None) err = test.stderr() -test.fail_test(string.find(err, 'Exception') != -1 or \ - string.find(err, 'Traceback') != -1) -test.fail_test(string.find(err, "ermission") == -1 and \ - string.find(err, "such file") == -1) +if string.find(err, 'Exception') != -1 or string.find(err, 'Traceback') != -1: + print "Exception or Traceback found in the following error output:" + print err + test.fail_test() +if string.find(err, 'ermission') == -1 and string.find(err, 'such file') == -1: + print "Missing '[Pp]ermission' or 'such file' string in the following error output:" + print err + test.fail_test() # Test command with exit status -1. diff --git a/test/import.py b/test/import.py index 9c5d3af..85948f9 100644 --- a/test/import.py +++ b/test/import.py @@ -96,6 +96,7 @@ tools = [ 'g77', 'gas', 'gcc', + 'gfortran', 'gnulink', 'gs', 'hpc++', diff --git a/test/option-k.py b/test/option-k.py index 0a46606..4a460a2 100644 --- a/test/option-k.py +++ b/test/option-k.py @@ -32,7 +32,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.subdir('work1', 'work2') +test.subdir('work1', 'work2', 'work3') @@ -49,6 +49,11 @@ import sys sys.exit(1) """) + +# +# Test: work1 +# + test.write(['work1', 'SConstruct'], """\ Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS') @@ -90,7 +95,27 @@ test.must_not_exist(test.workpath('work1', 'aaa.1')) test.must_not_exist(test.workpath('work1', 'aaa.out')) test.must_match(['work1', 'bbb.out'], "succeed.py: bbb.out\n") +expect = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Cleaning targets ... +Removed bbb.out +scons: done cleaning targets. +""" + +test.run(chdir = 'work1', + arguments = '--clean --keep-going aaa.out bbb.out', + stdout = expect) + +test.must_not_exist(test.workpath('work1', 'aaa.1')) +test.must_not_exist(test.workpath('work1', 'aaa.out')) +test.must_not_exist(test.workpath('work1', 'bbb.out')) + + +# +# Test: work2 +# test.write(['work2', 'SConstruct'], """\ Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') @@ -126,4 +151,145 @@ test.must_match(['work2', 'ddd.out'], "succeed.py: ddd.out\n") +# +# Test: work3 +# +# Check that the -k (keep-going) switch works correctly when the Nodes +# forms a DAG. The test case is the following +# +# all +# | +# +-----+-----+-------------+ +# | | | +# a1 a2 a3 +# | | | +# + +---+---+ +---+---+ +# \ | / | | +# \ bbb.out / a4 ccc.out +# \ / / +# \ / / +# \ / / +# aaa.out (fails) +# + +test.write(['work3', 'SConstruct'], """\ +Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') +Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS') +env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail }) +a = env.Fail('aaa.out', 'aaa.in') +b = env.Succeed('bbb.out', 'bbb.in') +c = env.Succeed('ccc.out', 'ccc.in') + +a1 = Alias( 'a1', a ) +a2 = Alias( 'a2', a+b) +a4 = Alias( 'a4', c) +a3 = Alias( 'a3', a4+c) + +Alias('all', a1+a2+a3) +""" % locals()) + +test.write(['work3', 'aaa.in'], "aaa.in\n") +test.write(['work3', 'bbb.in'], "bbb.in\n") +test.write(['work3', 'ccc.in'], "ccc.in\n") + + +# Test tegular build (i.e. without -k) +test.run(chdir = 'work3', + arguments = '.', + status = 2, + stderr = None, + stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +%(_python_)s ../fail.py aaa.out +scons: building terminated because of errors. +""" % locals()) + +test.must_not_exist(['work3', 'aaa.out']) +test.must_not_exist(['work3', 'bbb.out']) +test.must_not_exist(['work3', 'ccc.out']) + + +test.run(chdir = 'work3', + arguments = '-c .') +test.must_not_exist(['work3', 'aaa.out']) +test.must_not_exist(['work3', 'bbb.out']) +test.must_not_exist(['work3', 'ccc.out']) + + +# Current directory +test.run(chdir = 'work3', + arguments = '-k .', + status = 2, + stderr = None, + stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +%(_python_)s ../fail.py aaa.out +%(_python_)s ../succeed.py bbb.out +%(_python_)s ../succeed.py ccc.out +scons: done building targets (errors occurred during build). +""" % locals()) + +test.must_not_exist(['work3', 'aaa.out']) +test.must_exist(['work3', 'bbb.out']) +test.must_exist(['work3', 'ccc.out']) + + +test.run(chdir = 'work3', + arguments = '-c .') +test.must_not_exist(['work3', 'aaa.out']) +test.must_not_exist(['work3', 'bbb.out']) +test.must_not_exist(['work3', 'ccc.out']) + + +# Single target +test.run(chdir = 'work3', + arguments = '--keep-going all', + status = 2, + stderr = None, + stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +%(_python_)s ../fail.py aaa.out +%(_python_)s ../succeed.py bbb.out +%(_python_)s ../succeed.py ccc.out +scons: done building targets (errors occurred during build). +""" % locals()) + +test.must_not_exist(['work3', 'aaa.out']) +test.must_exist(['work3', 'bbb.out']) +test.must_exist(['work3', 'ccc.out']) + + +test.run(chdir = 'work3', + arguments = '-c .') +test.must_not_exist(['work3', 'aaa.out']) +test.must_not_exist(['work3', 'bbb.out']) +test.must_not_exist(['work3', 'ccc.out']) + + +# Separate top-level targets +test.run(chdir = 'work3', + arguments = '-k a1 a2 a3', + status = 2, + stderr = None, + stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons: Building targets ... +%(_python_)s ../fail.py aaa.out +%(_python_)s ../succeed.py bbb.out +%(_python_)s ../succeed.py ccc.out +scons: done building targets (errors occurred during build). +""" % locals()) + +test.must_not_exist(['work3', 'aaa.out']) +test.must_exist(['work3', 'bbb.out']) +test.must_exist(['work3', 'ccc.out']) + + test.pass_test() diff --git a/test/option/debug-includes.py b/test/option/debug-includes.py index 172cbb0..70857e6 100644 --- a/test/option/debug-includes.py +++ b/test/option/debug-includes.py @@ -79,7 +79,14 @@ includes = """ +-bar.h """ test.run(arguments = "--debug=includes foo.ooo") -test.fail_test(string.find(test.stdout(), includes) == -1) + +if string.find(test.stdout(), includes) == -1: + print "Did not find expected string in standard output." + print "Expected ==========================================================" + print includes + print "Actual ============================================================" + print test.stdout() + test.fail_test() # In an ideal world, --debug=includes would also work when there's a build # failure, but this would require even more complicated logic to scan diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py index 8c8b2cf..ad35b5d 100644 --- a/test/option/debug-memoizer.py +++ b/test/option/debug-memoizer.py @@ -29,6 +29,7 @@ Test calling the --debug=memoizer option. """ import os +import new import string import TestSCons @@ -39,15 +40,22 @@ test = TestSCons.TestSCons(match = TestSCons.match_re) class M: def __init__(cls, name, bases, cls_dict): - cls.has_metaclass = 1 - -class A: - __metaclass__ = M + cls.use_metaclass = 1 + def fake_method(self): + pass + new.instancemethod(fake_method, None, cls) try: - has_metaclass = A.has_metaclass + class A: + __metaclass__ = M + + use_metaclass = A.use_metaclass except AttributeError: - has_metaclass = None + use_metaclass = None + reason = 'no metaclasses' +except TypeError: + use_metaclass = None + reason = 'new.instancemethod\\(\\) bug' @@ -72,12 +80,8 @@ expect = [ "Node._children_get()", ] -expect_no_metaclasses = """ -scons: warning: memoization is not supported in this version of Python \\(no metaclasses\\) -""" + TestSCons.file_expr - -if has_metaclass: +if use_metaclass: def run_and_check(test, args, desc): test.run(arguments = args) @@ -92,6 +96,12 @@ if has_metaclass: else: + expect_no_metaclasses = """ +scons: warning: memoization is not supported in this version of Python \\(%s\\) +""" % reason + + expect_no_metaclasses = expect_no_metaclasses + TestSCons.file_expr + def run_and_check(test, args, desc): test.run(arguments = args, stderr = expect_no_metaclasses) stdout = test.stdout() diff --git a/test/option/stack-size.py b/test/option/stack-size.py new file mode 100644 index 0000000..495f86d --- /dev/null +++ b/test/option/stack-size.py @@ -0,0 +1,357 @@ +#!/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 string + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +isStackSizeAvailable = False +try: + import threading + isStackSizeAvailable = hasattr(threading,'stack_size') +except ImportError: + pass + +test.subdir('work1', 'work2') + +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(['work1', 'SConstruct'], """ +B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES') +env = Environment(BUILDERS = { 'B' : B }) +f1 = env.B(target = 'f1.out', source = 'f1.in') +f2 = env.B(target = 'f2.out', source = 'f2.in') +Requires(f2, f1) +""" % locals()) + +test.write(['work1', 'f1.in'], "f1.in\n") +test.write(['work1', 'f2.in'], "f2.in\n") + + +test.write(['work2', 'SConstruct'], """ +SetOption('stack_size', 128) +B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES') +env = Environment(BUILDERS = { 'B' : B }) +f1 = env.B(target = 'f1.out', source = 'f1.in') +f2 = env.B(target = 'f2.out', source = 'f2.in') +Requires(f2, f1) +""" % locals()) + +test.write(['work2', 'f1.in'], "f1.in\n") +test.write(['work2', 'f2.in'], "f2.in\n") + + + +expected_stdout = test.wrap_stdout("""\ +%(_python_)s ../build.py f1.out f1.in +%(_python_)s ../build.py f2.out f2.in +""" % locals()) + +re_expected_stdout = string.replace(expected_stdout, '\\', '\\\\') + +expect_unsupported = """ +scons: warning: Setting stack size is unsupported by this version of Python: + (('module' object|'threading' module) has no attribute 'stack_size'|stack_size) +File .* +""" + + +# +# Test without any options +# +test.run(chdir='work1', + arguments = '.', + stdout=expected_stdout, + stderr='') +test.must_exist(['work1', 'f1.out']) +test.must_exist(['work1', 'f2.out']) + +test.run(chdir='work1', + arguments = '-c .') +test.must_not_exist(['work1', 'f1.out']) +test.must_not_exist(['work1', 'f2.out']) + +# +# Test with -j2 +# +test.run(chdir='work1', + arguments = '-j2 .', + stdout=expected_stdout, + stderr='') +test.must_exist(['work1', 'f1.out']) +test.must_exist(['work1', 'f2.out']) + +test.run(chdir='work1', + arguments = '-j2 -c .') +test.must_not_exist(['work1', 'f1.out']) +test.must_not_exist(['work1', 'f2.out']) + + +# +# Test with --stack-size +# +test.run(chdir='work1', + arguments = '--stack-size=128 .', + stdout=expected_stdout, + stderr='') +test.must_exist(['work1', 'f1.out']) +test.must_exist(['work1', 'f2.out']) + +test.run(chdir='work1', + arguments = '--stack-size=128 -c .') +test.must_not_exist(['work1', 'f1.out']) +test.must_not_exist(['work1', 'f2.out']) + +# +# Test with SetOption('stack_size', 128) +# +test.run(chdir='work2', + arguments = '.', + stdout=expected_stdout, + stderr='') +test.must_exist(['work2', 'f1.out']) +test.must_exist(['work2', 'f2.out']) + +test.run(chdir='work2', + arguments = '--stack-size=128 -c .') +test.must_not_exist(['work2', 'f1.out']) +test.must_not_exist(['work2', 'f2.out']) + +if isStackSizeAvailable: + # + # Test with -j2 --stack-size=128 + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 -c .') + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --stack-size=16 + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 .', + match=TestSCons.match_re, + stdout=re_expected_stdout, + stderr=""" +scons: warning: Setting stack size failed: + size not valid: 16384 bytes +File .* +""") + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 -c .', + match=TestSCons.match_re, + stderr=""" +scons: warning: Setting stack size failed: + size not valid: 16384 bytes +File .* +""") + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 SetOption('stack_size', 128) + # + test.run(chdir='work2', + arguments = '-j2 .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work2', 'f1.out']) + test.must_exist(['work2', 'f2.out']) + + test.run(chdir='work2', + arguments = '-j2 -c .') + test.must_not_exist(['work2', 'f1.out']) + test.must_not_exist(['work2', 'f2.out']) + + # + # Test with -j2 --stack-size=128 --warn=no-stack-size + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .') + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --stack-size=16 --warn=no-stack-size + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .') + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128) + # + test.run(chdir='work2', + arguments = '-j2 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work2', 'f1.out']) + test.must_exist(['work2', 'f2.out']) + + test.run(chdir='work2', + arguments = '-j2 --warn=no-stack-size -c .') + test.must_not_exist(['work2', 'f1.out']) + test.must_not_exist(['work2', 'f2.out']) + +else: + + # + # Test with -j2 --stack-size=128 + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 .', + match=TestSCons.match_re, + stdout=re_expected_stdout, + stderr=expect_unsupported) + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 -c .', + match=TestSCons.match_re, + stderr=expect_unsupported) + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --stack-size=16 + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 .', + match=TestSCons.match_re, + stdout=re_expected_stdout, + stderr=expect_unsupported) + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 -c .', + match=TestSCons.match_re, + stderr=expect_unsupported) + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 SetOption('stack_size', 128) + # + test.run(chdir='work2', + arguments = '-j2 .', + match=TestSCons.match_re, + stdout=re_expected_stdout, + stderr=expect_unsupported) + test.must_exist(['work2', 'f1.out']) + test.must_exist(['work2', 'f2.out']) + + test.run(chdir='work2', + arguments = '-j2 -c .', + match=TestSCons.match_re, + stderr=expect_unsupported) + test.must_not_exist(['work2', 'f1.out']) + test.must_not_exist(['work2', 'f2.out']) + + # + # Test with -j2 --stack-size=128 --warn=no-stack-size + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .') + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --stack-size=16 --warn=no-stack-size + # + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work1', 'f1.out']) + test.must_exist(['work1', 'f2.out']) + + test.run(chdir='work1', + arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .') + test.must_not_exist(['work1', 'f1.out']) + test.must_not_exist(['work1', 'f2.out']) + + # + # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128) + # + test.run(chdir='work2', + arguments = '-j2 --warn=no-stack-size .', + stdout=expected_stdout, + stderr='') + test.must_exist(['work2', 'f1.out']) + test.must_exist(['work2', 'f2.out']) + + test.run(chdir='work2', + arguments = '-j2 --warn=no-stack-size -c .') + test.must_not_exist(['work2', 'f1.out']) + test.must_not_exist(['work2', 'f2.out']) + +test.pass_test() diff --git a/test/scons-time/func/file.py b/test/scons-time/func/file.py index c9486c4..079c125 100644 --- a/test/scons-time/func/file.py +++ b/test/scons-time/func/file.py @@ -31,7 +31,7 @@ affect how the func subcommand processes things. import TestSCons_time -test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re) +test = TestSCons_time.TestSCons_time() try: import pstats @@ -56,22 +56,43 @@ prefix = 'foo-001' expect1 = r'\d.\d\d\d prof1\.py:1\(_main\)' + '\n' -test.run(arguments = 'func -f st1.conf', stdout = expect1) +test.run(arguments = 'func -f st1.conf', + match = TestSCons_time.match_re, + stdout = expect1) test.write('st2.conf', """\ prefix = 'foo' title = 'ST2.CONF TITLE' +vertical_bars = ( + ( 1.4, 7, None ), + ( 1.5, 7, "label 1.5" ), + ( 1.6, 7, "label 1.6" ), +) """) expect2 = \ r"""set title "ST2.CONF TITLE" set key bottom left -plot '-' title "Startup" with lines lt 1 +set label 3 "label 1.5" at 0.5,1.5 right +set label 4 "label 1.6" at 0.6,1.5 right +plot '-' title "Startup" with lines lt 1, \ + '-' notitle with lines lt 7, \ + '-' title "label 1.5" with lines lt 7, \ + '-' title "label 1.6" with lines lt 7 # Startup 1 0.000 2 0.000 e +1.4 0 +1.4 1 +e +1.5 0 +1.5 1 +e +1.6 0 +1.6 1 +e """ test.run(arguments = 'func --file st2.conf --fmt gnuplot', stdout = expect2) diff --git a/test/scons-time/mem/file.py b/test/scons-time/mem/file.py index a236df7..a1e7181 100644 --- a/test/scons-time/mem/file.py +++ b/test/scons-time/mem/file.py @@ -53,16 +53,23 @@ test.run(arguments = 'mem -f st1.conf', stdout = expect1) test.write('st2.conf', """\ prefix = 'foo' title = 'ST2.CONF TITLE' +vertical_bars = ( + ( 1.5, 7, None ), +) """) expect2 = \ r"""set title "ST2.CONF TITLE" set key bottom left -plot '-' title "Startup" with lines lt 1 +plot '-' title "Startup" with lines lt 1, \ + '-' notitle with lines lt 7 # Startup 1 4000.000 2 4000.000 e +1.5 0 +1.5 4800 +e """ test.run(arguments = 'mem --file st2.conf --fmt gnuplot', stdout = expect2) diff --git a/test/scons-time/obj/file.py b/test/scons-time/obj/file.py index c881397..3cf8e74 100644 --- a/test/scons-time/obj/file.py +++ b/test/scons-time/obj/file.py @@ -53,16 +53,23 @@ test.run(arguments = 'obj -f st1.conf Node.FS.Base', stdout = expect1) test.write('st2.conf', """\ prefix = 'foo' title = 'ST2.CONF TITLE' +vertical_bars = ( + ( 1.5, 7, None ), +) """) expect2 = \ r"""set title "ST2.CONF TITLE" set key bottom left -plot '-' title "Startup" with lines lt 1 +plot '-' title "Startup" with lines lt 1, \ + '-' notitle with lines lt 7 # Startup 1 16040.000 2 16040.000 e +1.5 0 +1.5 18000 +e """ test.run(arguments = 'obj --file st2.conf --fmt gnuplot Node.FS.Base', stdout = expect2) diff --git a/test/scons-time/run/aegis.py b/test/scons-time/run/aegis.py index 8f378cb..641f129 100644 --- a/test/scons-time/run/aegis.py +++ b/test/scons-time/run/aegis.py @@ -59,22 +59,9 @@ test.must_exist('foo-329-0.log', 'foo-329-2.log', 'foo-329-2.prof') -def tempdir_re(*args): - import os - import os.path - import string - import tempfile - - sep = re.escape(os.sep) - args = (tempfile.gettempdir(), 'scons-time-aegis-',) + args - x = apply(os.path.join, args) - x = re.escape(x) - x = string.replace(x, 'aegis\\-', 'aegis\\-[^%s]*' % sep) - return x - expect = [ - tempdir_re('src', 'script', 'scons.py'), - 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'), + test.tempdir_re('src', 'script', 'scons.py'), + 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'), ] content = test.read(test.workpath('foo-321-2.log')) diff --git a/test/scons-time/run/config/archive_list.py b/test/scons-time/run/config/archive_list.py index 8d48d26..8ddde3d 100644 --- a/test/scons-time/run/config/archive_list.py +++ b/test/scons-time/run/config/archive_list.py @@ -38,9 +38,11 @@ test.write_fake_scons_py() test.write_sample_project('foo.tar.gz') test.write('config', """\ -archive_list = ['foo.tar.gz'] +archive_list = ['foo.tar.gz', 'foo-file'] """) +test.write('foo-file', "foo-file\n") + test.run(arguments = 'run -f config') test.must_exist('foo-000-0.log', @@ -50,6 +52,8 @@ test.must_exist('foo-000-0.log', 'foo-000-2.log', 'foo-000-2.prof') +test.must_exist('foo-file') + test.write_sample_project('bar.tar.gz') diff --git a/test/scons-time/run/option/quiet.py b/test/scons-time/run/option/quiet.py index f5a3d8c..453829c 100644 --- a/test/scons-time/run/option/quiet.py +++ b/test/scons-time/run/option/quiet.py @@ -37,28 +37,11 @@ python = TestSCons_time.python test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re) test.diff_function = TestSCons_time.diff_re - -def tempdir_re(*args): - import os,sys - import os.path - import string - import tempfile - - sep = re.escape(os.sep) - args = (tempfile.gettempdir(), 'scons-time-',) + args - x = apply(os.path.join, args) - x = re.escape(x) - x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep) - if sys.platform=='darwin': - # OSX has /tmp in /private/tmp. - x = '(/private)?' + x - return x - scons_py = re.escape(test.workpath('src', 'script', 'scons.py')) src_engine = re.escape(test.workpath('src', 'engine')) -tmp_scons_time = tempdir_re() -tmp_scons_time_foo = tempdir_re('foo') +tmp_scons_time = test.tempdir_re() +tmp_scons_time_foo = test.tempdir_re('foo') test.write_fake_scons_py() diff --git a/test/scons-time/run/option/verbose.py b/test/scons-time/run/option/verbose.py index fb95dab..935e2a9 100644 --- a/test/scons-time/run/option/verbose.py +++ b/test/scons-time/run/option/verbose.py @@ -38,28 +38,11 @@ _python_ = re.escape(TestSCons_time._python_) test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re) test.diff_function = TestSCons_time.diff_re - -def tempdir_re(*args): - import os,sys - import os.path - import string - import tempfile - - sep = re.escape(os.sep) - args = (tempfile.gettempdir(), 'scons-time-',) + args - x = apply(os.path.join, args) - x = re.escape(x) - x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep) - if sys.platform=='darwin': - # OSX has /tmp in /private/tmp. - x = '(/private)?' + x - return x - scons_py = re.escape(test.workpath('src', 'script', 'scons.py')) src_engine = re.escape(test.workpath('src', 'engine')) -tmp_scons_time = tempdir_re() -tmp_scons_time_foo = tempdir_re('foo') +tmp_scons_time = test.tempdir_re() +tmp_scons_time_foo = test.tempdir_re('foo') test.write_fake_scons_py() diff --git a/test/scons-time/run/subversion.py b/test/scons-time/run/subversion.py index 3839999..757f6df 100644 --- a/test/scons-time/run/subversion.py +++ b/test/scons-time/run/subversion.py @@ -60,22 +60,9 @@ test.must_exist('foo-716-0.log', 'foo-716-2.log', 'foo-716-2.prof') -def tempdir_re(*args): - import os - import os.path - import string - import tempfile - - sep = re.escape(os.sep) - args = (tempfile.gettempdir(), 'scons-time-svn-',) + args - x = apply(os.path.join, args) - x = re.escape(x) - x = string.replace(x, 'svn\\-', 'svn\\-[^%s]*' % sep) - return x - expect = [ - tempdir_re('src', 'script', 'scons.py'), - 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'), + test.tempdir_re('src', 'script', 'scons.py'), + 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'), ] content = test.read(test.workpath('foo-617-2.log'), mode='r') diff --git a/test/scons-time/time/empty.py b/test/scons-time/time/empty.py new file mode 100644 index 0000000..7542bfc --- /dev/null +++ b/test/scons-time/time/empty.py @@ -0,0 +1,91 @@ +#!/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 time subcommand doesn't fail and prints an appropriate +error message if a log file is empty. +""" + +import TestSCons_time + +test = TestSCons_time.TestSCons_time() + + +header = ' Total SConscripts SCons commands\n' + +lines = [] + +line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n' +empty_fmt = ' %s\n' + +for i in xrange(9): + logfile_name = 'foo-%s-0.log' % i + if i == 5: + test.write(test.workpath(logfile_name), "") + lines.append(empty_fmt % logfile_name) + else: + test.fake_logfile(logfile_name) + lines.append(line_fmt % logfile_name) + +expect = [header] + lines + +test.run(arguments = 'time foo-*.log', + stdout = ''.join(expect), + stderr = "file 'foo-5-0.log' has no contents!\n") + +expect = """\ +set key bottom left +plot '-' title "Startup" with lines lt 1 +# Startup +0 11.123456 +1 11.123456 +2 11.123456 +3 11.123456 +4 11.123456 +6 11.123456 +7 11.123456 +8 11.123456 +e +""" + +stderr = "file 'foo-5-0.log' has no contents!\n" + +test.run(arguments = 'time --fmt gnuplot --which total foo-*.log', + stdout = expect, + stderr = stderr) + +expect = """\ +set key bottom left +plot '-' title "Startup" with lines lt 1 +# Startup +e +""" + +test.run(arguments = 'time --fmt gnuplot foo-5-0.log', + stdout = expect, + stderr = stderr) + +test.pass_test() diff --git a/test/scons-time/time/file.py b/test/scons-time/time/file.py index f4046c9..96bd035 100644 --- a/test/scons-time/time/file.py +++ b/test/scons-time/time/file.py @@ -53,16 +53,23 @@ test.run(arguments = 'time -f st1.conf', stdout = expect1) test.write('st2.conf', """\ prefix = 'foo' title = 'ST2.CONF TITLE' +vertical_bars = ( + ( 1.5, 7, None ), +) """) expect2 = \ r"""set title "ST2.CONF TITLE" set key bottom left -plot '-' title "Startup" with lines lt 1 +plot '-' title "Startup" with lines lt 1, \ + '-' notitle with lines lt 7 # Startup 1 11.123456 2 11.123456 e +1.5 0 +1.5 12 +e """ test.run(arguments = 'time --file st2.conf --fmt gnuplot', stdout = expect2) diff --git a/test/scons-time/time/no-result.py b/test/scons-time/time/no-result.py new file mode 100644 index 0000000..ca345b2 --- /dev/null +++ b/test/scons-time/time/no-result.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 the time subcommand's --which option doesn't fail, and prints +an appropriate error message, if a log file doesn't have its specific +requested results. +""" + +import TestSCons_time + +test = TestSCons_time.TestSCons_time() + + +header = """\ +set key bottom left +plot '-' title "Startup" with lines lt 1 +# Startup +""" + +footer = """\ +e +""" + +line_fmt = "%s 11.123456\n" + +lines = [] + +for i in xrange(9): + logfile_name = 'foo-%s-0.log' % i + if i == 5: + test.write(test.workpath(logfile_name), "NO RESULTS HERE!\n") + else: + test.fake_logfile(logfile_name) + lines.append(line_fmt % i) + +expect = [header] + lines + [footer] + +stderr = "file 'foo-5-0.log' has no results!\n" + + +test.run(arguments = 'time --fmt gnuplot --which total foo*.log', + stdout = ''.join(expect), + stderr = stderr) + +expect = [header] + [footer] + +test.run(arguments = 'time --fmt gnuplot foo-5-0.log', + stdout = ''.join(expect), + stderr = stderr) + +test.pass_test() diff --git a/test/subclassing.py b/test/subclassing.py index 18be1bc..31632a9 100644 --- a/test/subclassing.py +++ b/test/subclassing.py @@ -25,7 +25,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Verify that we can trivially subclass our "public" classes. +Verify that we can trivially subclass our "public" classes. Also +verify that we can use a trivial subclass of new-style str classes +as well as UserString as Builder input. """ import TestSCons @@ -33,6 +35,8 @@ import TestSCons test = TestSCons.TestSCons() test.write('SConstruct', """ +copy_action = Copy('$TARGET', '$SOURCE') + # Some day, we'd probably like people to be able to subclass Action and # Builder, but that's going to take some serious class-hackery to turn # our factory function into the class itself. @@ -45,18 +49,31 @@ class my_Scanner(Scanner): class my_Environment(Environment): pass env = my_Environment() -env.Program('hello', 'hello.c') -""") +env.Command('f0.out', 'f0.in', copy_action) + +from UserString import UserString +try: + class mystr(str): + pass +except TypeError: + class mystr(UserString): + pass -test.write('hello.c', """\ -#include <stdio.h> -#include <stdlib.h> -int -main(int argc, char *argv[]) { - printf("hello.c\\n"); -} +Command(mystr('f1.out'), mystr('f1.in'), copy_action) +Command(UserString('f2.out'), UserString('f2.in'), copy_action) + +Install(mystr('install'), mystr('f1.out')) +Install(mystr('install'), UserString('f2.out')) """) +test.write('f0.in', "f0.in\n") +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") + test.run(arguments = '.') +test.must_match('f0.out', "f0.in\n") +test.must_match(['install', 'f1.out'], "f1.in\n") +test.must_match(['install', 'f2.out'], "f2.in\n") + test.pass_test() diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py index 9d89d70..0774995 100644 --- a/test/timestamp-fallback.py +++ b/test/timestamp-fallback.py @@ -79,7 +79,8 @@ 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 f3.out', + stderr = None) test.run(arguments = 'f1.out f2.out f3.out f4.out', stdout = test.wrap_stdout("""\ @@ -87,7 +88,8 @@ scons: `f1.out' is up to date. build(["f2.out"], ["f2.in"]) scons: `f3.out' is up to date. build(["f4.out"], ["f4.in"]) -""")) +"""), + stderr = None) os.utime(test.workpath('f1.in'), (os.path.getatime(test.workpath('f1.in')), @@ -102,7 +104,8 @@ build(["f1.out"], ["f1.in"]) scons: `f2.out' is up to date. build(["f3.out"], ["f3.in"]) scons: `f4.out' is up to date. -""")) +"""), + stderr = None) test.pass_test() |