diff options
Diffstat (limited to 'test')
30 files changed, 1507 insertions, 416 deletions
diff --git a/test/CPPDEFINES.py b/test/CPPDEFINES.py index 61aaecd..c38f857 100644 --- a/test/CPPDEFINES.py +++ b/test/CPPDEFINES.py @@ -50,13 +50,13 @@ test.write('SConstruct', """\ test_list = [ 'xyz', ['x', 'y', 'z'], - ['x', ['y', 123], 'z'], + ['x', ['y', 123], 'z', ('int', '$INTEGER')], { 'c' : 3, 'b': None, 'a' : 1 }, ] -env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='') +env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0) for i in test_list: print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') -env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|') +env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1) for i in test_list: print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') """) @@ -65,18 +65,18 @@ expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", read_str = """\ -Dxyz -Dx -Dy -Dz --Dx -Dy=123 -Dz +-Dx -Dy=123 -Dz -Dint=0 -Da=1 -Db -Dc=3 |xyz| |x| |y| |z| -|x| |y=123| |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', 7)]) +foo = Environment(CPPDEFINES = ['FOO', ('VAL', '$VALUE')], VALUE=7) bar = Environment(CPPDEFINES = {'BAR':None, 'VAL':8}) baz = Environment(CPPDEFINES = ['BAZ', ('VAL', 9)]) f = foo.Object(target = 'foo', source = 'prog.c') diff --git a/test/CPPPATH.py b/test/CPPPATH/CPPPATH.py index c9400f7..80b4aa7 100644 --- a/test/CPPPATH.py +++ b/test/CPPPATH/CPPPATH.py @@ -24,8 +24,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os -import sys +import os.path + import TestSCons _exe = TestSCons._exe @@ -154,7 +154,7 @@ foobar/ttt.h # Make sure we didn't duplicate the source file in the variant subdirectory. -test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) +test.must_not_exist(test.workpath('variant', 'prog.c')) test.up_to_date(arguments = args) @@ -196,7 +196,7 @@ foobar/ttt.h # Make sure we didn't duplicate the source file in the variant subdirectory. -test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) +test.must_not_exist(test.workpath('variant', 'prog.c')) test.up_to_date(arguments = args) @@ -238,7 +238,7 @@ foobar/ttt.h """) # Make sure we didn't duplicate the source file in the variant subdirectory. -test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) +test.must_not_exist(test.workpath('variant', 'prog.c')) test.up_to_date(arguments = args) @@ -301,25 +301,4 @@ test.up_to_date(arguments = args) -# Check that neither a null-string CPPPATH nor a -# a CPPPATH containing null values blows up. -test.write('SConstruct', """ -env = Environment(CPPPATH = '') -env.Library('one', source = 'empty1.c') -env = Environment(CPPPATH = [None]) -env.Library('two', source = 'empty2.c') -env = Environment(CPPPATH = ['']) -env.Library('three', source = 'empty3.c') -""") - -test.write('empty1.c', "int a=0;\n") -test.write('empty2.c', "int b=0;\n") -test.write('empty3.c', "int c=0;\n") - -test.run(arguments = '.', - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) - - - test.pass_test() diff --git a/test/CPPPATH/Dir.py b/test/CPPPATH/Dir.py new file mode 100644 index 0000000..1059467 --- /dev/null +++ b/test/CPPPATH/Dir.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 CPPPATH values with Dir nodes work correctly. +""" + +import TestSCons + +_exe = TestSCons._exe + +test = TestSCons.TestSCons() + +test.subdir('inc1', 'inc2', 'inc3', ['inc3', 'subdir']) + +test.write('SConstruct', """ +env = Environment(CPPPATH = [Dir('inc1'), '$INC2', '$INC3/subdir'], + INC2 = Dir('inc2'), + INC3 = Dir('inc3')) +env.Program('prog.c') +""") + +test.write('prog.c', """\ +#include <stdio.h> +#include <stdlib.h> + +#include "one.h" +#include "two.h" +#include "three.h" +int +main(int argc, char *argv[]) +{ + printf("%s\\n", ONE); + printf("%s\\n", TWO); + printf("%s\\n", THREE); + return (0); +} +""") + +test.write(['inc1', 'one.h'], """\ +#define ONE "1" +""") + +test.write(['inc2', 'two.h'], """\ +#define TWO "2" +""") + +test.write(['inc3', 'subdir', 'three.h'], """\ +#define THREE "3" +""") + +test.run(arguments = '.') + +test.run(program = test.workpath('prog' + _exe), stdout = "1\n2\n3\n") + +test.pass_test() diff --git a/test/CPPPATH/expand-object.py b/test/CPPPATH/expand-object.py new file mode 100644 index 0000000..5e1b06f --- /dev/null +++ b/test/CPPPATH/expand-object.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Make sure that $CPPPATH expands correctly if one of the subsidiary +expansions contains a stringable non-Node object. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +class XXX: + def __init__(self, value): + self.value = value + def __str__(self): + return 'XXX-' + self.value + '-XXX' +env = Environment(CPPPATH = ['#', + '$BUILDDIR', + '/tmp/xyzzy'], + BUILDDIR = '#scons_build/$EXPANSION', + EXPANSION = XXX('win32')) +env.Object('foo.c') +""") + +test.write('foo.c', """\ +#include <stdio.h> +void +foo(void) +{ + printf("foo.c\\n"); +} +""") + +test.run(arguments = '.') + +test.must_exist(test.workpath('foo' + TestSCons._obj)) + +test.pass_test() diff --git a/test/CPPPATH/nested-lists.py b/test/CPPPATH/nested-lists.py new file mode 100644 index 0000000..8ec97bc --- /dev/null +++ b/test/CPPPATH/nested-lists.py @@ -0,0 +1,77 @@ +#!/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 CPPPATH values consisting of nested lists work correctly. +""" + +import TestSCons + +_exe = TestSCons._exe + +test = TestSCons.TestSCons() + +test.subdir('inc1', 'inc2', 'inc3') + +test.write('SConstruct', """ +env = Environment(CPPPATH = ['inc1', ['inc2', ['inc3']]]) +env.Program('prog.c') +""") + +test.write('prog.c', """\ +#include <stdio.h> +#include <stdlib.h> + +#include "one.h" +#include "two.h" +#include "three.h" +int +main(int argc, char *argv[]) +{ + printf("%s\\n", ONE); + printf("%s\\n", TWO); + printf("%s\\n", THREE); + return (0); +} +""") + +test.write(['inc1', 'one.h'], """\ +#define ONE "1" +""") + +test.write(['inc2', 'two.h'], """\ +#define TWO "2" +""") + +test.write(['inc3', 'three.h'], """\ +#define THREE "3" +""") + +test.run(arguments = '.') + +test.run(program = test.workpath('prog' + _exe), stdout = "1\n2\n3\n") + +test.pass_test() diff --git a/test/CPPPATH/null.py b/test/CPPPATH/null.py new file mode 100644 index 0000000..19895db --- /dev/null +++ b/test/CPPPATH/null.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that neither a null-string CPPPATH nor a +a CPPPATH containing null values blows up. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(CPPPATH = '') +env.Library('one', source = 'empty1.c') +env = Environment(CPPPATH = [None]) +env.Library('two', source = 'empty2.c') +env = Environment(CPPPATH = ['']) +env.Library('three', source = 'empty3.c') +""") + +test.write('empty1.c', "int a=0;\n") +test.write('empty2.c', "int b=0;\n") +test.write('empty3.c', "int c=0;\n") + +test.run(arguments = '.', + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) + + + +test.pass_test() diff --git a/test/CXX/CC-variables.py b/test/CXX/CC-variables.py index 93aa315..fea3dde 100644 --- a/test/CXX/CC-variables.py +++ b/test/CXX/CC-variables.py @@ -34,7 +34,7 @@ import TestSCons test = TestSCons.TestSCons() test.write('SConstruct', """ -env = Environment(tools = ['g++']) +env = Environment(tools = ['g++'], CXX = 'g++') env.Object(target = 'test.obj', source = 'test.cxx') env.MergeFlags('+for_CCFLAGS -Wp,-for_CPPFLAGS') """) diff --git a/test/CacheDir/up-to-date-q.py b/test/CacheDir/up-to-date-q.py index 07123c9..0a49164 100644 --- a/test/CacheDir/up-to-date-q.py +++ b/test/CacheDir/up-to-date-q.py @@ -60,7 +60,7 @@ int main(){ return 0; } sconstruct = """ import os -CacheDir('%s') +CacheDir(r'%s') Program('foo', 'foo.c') """ % test.workpath('cache') diff --git a/test/Errors/preparation.py b/test/Errors/preparation.py new file mode 100644 index 0000000..3f98894 --- /dev/null +++ b/test/Errors/preparation.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that we print a useful message (and exit non-zero) if an external +error occurs while deciding if a Node is current or not. +""" + +import sys + +import TestSCons + +test = TestSCons.TestSCons() + +install = test.workpath('install') +install_file = test.workpath('install', 'file') +work_file = test.workpath('work', 'file') + +test.subdir('install', 'work') + +test.write(['work', 'SConstruct'], """\ +Alias("install", Install(r"%(install)s", File('file'))) + +# Make a directory where we expect the File() to be. This causes an +# IOError or OSError when we try to open it to read its signature. +import os +os.mkdir(r'%(work_file)s') +""" % locals()) + +if sys.platform == 'win32': + error_message = "Permission denied" +else: + error_message = "Is a directory" + +expect = """\ +scons: *** [%(install_file)s] %(work_file)s: %(error_message)s +""" % locals() + +test.run(chdir = 'work', + arguments = 'install', + status = 2, + stderr = expect) + +test.pass_test() diff --git a/test/Intel/icpc-link.py b/test/Intel/icpc-link.py new file mode 100644 index 0000000..068e0f3 --- /dev/null +++ b/test/Intel/icpc-link.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Simple "Hello, world" test of linking with the Intel C++ compiler, icpc. + +This tests for a bug (1415) where our initialization of the linker to +$CC prevented automatic linking of C++ source. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +icpc = test.detect_tool('intelc', prog='icpc') +if not icpc: + test.skip_test("Could not find 'icpc' from 'intelc' Tool; skipping test(s).\n") + +test.write('SConstruct', """\ +env = Environment(tools=['default', 'intelc']) +env.Program('hw', 'hw.cpp') +""") + +test.write('hw.cpp', """\ +#include <iostream> +int +main() +{ + std::cout<<"hw\\n"; + return 0; +} +""") + +test.run(arguments = '.') + +test.pass_test() diff --git a/test/Java/JAVAC.py b/test/Java/JAVAC.py index 7c06324..09639ea 100644 --- a/test/Java/JAVAC.py +++ b/test/Java/JAVAC.py @@ -24,6 +24,10 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Test setting the JAVAC variable. +""" + import os import os.path import string @@ -93,223 +97,4 @@ 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") - - - -test.write("wrapper.py", """\ -import os -import string -import sys -open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:])) -os.system(string.join(sys.argv[1:], " ")) -""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\')) - -test.write('SConstruct', """ -foo = Environment(tools = ['javac'], - JAVAC = r'%(where_javac)s') -javac = foo.Dictionary('JAVAC') -bar = foo.Clone(JAVAC = r'%(_python_)s wrapper.py ' + javac) -foo.Java(target = 'class1', source = 'com/sub/foo') -bar.Java(target = 'class2', source = 'com/sub/bar') -foo.Java(target = 'class3', source = ['src1', 'src2']) -""" % locals()) - -test.subdir('com', - ['com', 'sub'], - ['com', 'sub', 'foo'], - ['com', 'sub', 'bar'], - 'src1', - 'src2') - -test.write(['com', 'sub', 'foo', 'Example1.java'], """\ -package com.sub.foo; - -public class Example1 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['com', 'sub', 'foo', 'Example2.java'], """\ -package com.other; - -public class Example2 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['com', 'sub', 'foo', 'Example3.java'], """\ -package com.sub.foo; - -public class Example3 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['com', 'sub', 'bar', 'Example4.java'], """\ -package com.sub.bar; - -public class Example4 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['com', 'sub', 'bar', 'Example5.java'], """\ -package com.other; - -public class Example5 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['com', 'sub', 'bar', 'Example6.java'], """\ -package com.sub.bar; - -public class Example6 -{ - - public static void main(String[] args) - { - - } - -} -""") - -test.write(['src1', 'Example7.java'], """\ -public class Example7 -{ - - public static void main(String[] args) - { - - } - -} -""") - -# Acid-test file for parsing inner Java classes, courtesy Chad Austin. -test.write(['src2', 'Test.java'], """\ -class Empty { -} - -interface Listener { - public void execute(); -} - -public -class -Test { - class Inner { - void go() { - use(new Listener() { - public void execute() { - System.out.println("In Inner"); - } - }); - } - String s1 = "class A"; - String s2 = "new Listener() { }"; - /* class B */ - /* new Listener() { } */ - } - - public static void main(String[] args) { - new Test().run(); - } - - void run() { - use(new Listener() { - public void execute() { - use(new Listener( ) { - public void execute() { - System.out.println("Inside execute()"); - } - }); - } - }); - - new Inner().go(); - } - - void use(Listener l) { - l.execute(); - } -} - -class Private { - void run() { - new Listener() { - public void execute() { - } - }; - } -} -""") - -test.run(arguments = '.') - -expected_wrapper_out = "wrapper.py %s -d class2 -sourcepath com/sub/bar com/sub/bar/Example4.java com/sub/bar/Example5.java com/sub/bar/Example6.java\n" -expected_wrapper_out = string.replace(expected_wrapper_out, '/', os.sep) -test.must_match('wrapper.out', expected_wrapper_out % where_javac) - -test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example1.class')) -test.must_exist(test.workpath('class1', 'com', 'other', 'Example2.class')) -test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example3.class')) - -test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example4.class')) -test.must_exist(test.workpath('class2', 'com', 'other', 'Example5.class')) -test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example6.class')) - -test.must_exist(test.workpath('class3', 'Example7.class')) - -test.must_exist(test.workpath('class3', 'Empty.class')) -test.must_exist(test.workpath('class3', 'Listener.class')) -test.must_exist(test.workpath('class3', 'Private.class')) -test.must_exist(test.workpath('class3', 'Private$1.class')) -test.must_exist(test.workpath('class3', 'Test.class')) -test.must_exist(test.workpath('class3', 'Test$1.class')) -test.must_exist(test.workpath('class3', 'Test$2.class')) -test.must_exist(test.workpath('class3', 'Test$3.class')) -test.must_exist(test.workpath('class3', 'Test$Inner.class')) - -test.up_to_date(arguments = '.') - test.pass_test() diff --git a/test/Java/live.py b/test/Java/live.py new file mode 100644 index 0000000..5ad2194 --- /dev/null +++ b/test/Java/live.py @@ -0,0 +1,346 @@ +#!/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 Java compilation with a live "javac" compiler. +""" + +import os +import os.path +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") + + + +test.write('SConstruct', """ +env = Environment(tools = ['javac'], + JAVAC = r'%(where_javac)s') +env.Java(target = 'class1', source = 'com/sub/foo') +env.Java(target = 'class2', source = 'com/sub/bar') +env.Java(target = 'class3', source = ['src1', 'src2']) +env.Java(target = 'class4', source = ['src4']) +env.Java(target = 'class5', source = ['src5']) +""" % locals()) + +test.subdir('com', + ['com', 'sub'], + ['com', 'sub', 'foo'], + ['com', 'sub', 'bar'], + 'src1', + 'src2', + 'src4', + 'src5') + +test.write(['com', 'sub', 'foo', 'Example1.java'], """\ +package com.sub.foo; + +public class Example1 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'sub', 'foo', 'Example2.java'], """\ +package com.other; + +public class Example2 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'sub', 'foo', 'Example3.java'], """\ +package com.sub.foo; + +public class Example3 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'sub', 'bar', 'Example4.java'], """\ +package com.sub.bar; + +public class Example4 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'sub', 'bar', 'Example5.java'], """\ +package com.other; + +public class Example5 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'sub', 'bar', 'Example6.java'], """\ +package com.sub.bar; + +public class Example6 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['src1', 'Example7.java'], """\ +public class Example7 +{ + + public static void main(String[] args) + { + + } + +} +""") + +# Acid-test file for parsing inner Java classes, courtesy Chad Austin. +test.write(['src2', 'Test.java'], """\ +class Empty { +} + +interface Listener { + public void execute(); +} + +public +class +Test { + class Inner { + void go() { + use(new Listener() { + public void execute() { + System.out.println("In Inner"); + } + }); + } + String s1 = "class A"; + String s2 = "new Listener() { }"; + /* class B */ + /* new Listener() { } */ + } + + public static void main(String[] args) { + new Test().run(); + } + + void run() { + use(new Listener() { + public void execute() { + use(new Listener( ) { + public void execute() { + System.out.println("Inside execute()"); + } + }); + } + }); + + new Inner().go(); + } + + void use(Listener l) { + l.execute(); + } +} + +class Private { + void run() { + new Listener() { + public void execute() { + } + }; + } +} +""") + +# Testing nested anonymous inner classes, courtesy Brandon Mansfield. +test.write(['src4', 'NestedExample.java'], """\ +// import java.util.*; + +public class NestedExample +{ + public NestedExample() + { + Thread t = new Thread() { + public void start() + { + Thread t = new Thread() { + public void start() + { + try {Thread.sleep(200);} + catch (Exception e) {} + } + }; + while (true) + { + try {Thread.sleep(200);} + catch (Exception e) {} + } + } + }; + } + + + public static void main(String argv[]) + { + NestedExample e = new NestedExample(); + } +} +""") + +# Test not finding an anonymous class when the second token after a +# "new" is a closing brace. This duplicates a test from the unit tests, +# but lets us make sure that we correctly determine that everything is +# up-to-date after the build. +test.write(['src5', 'TestSCons.java'], """\ +class TestSCons { + public static void main(String[] args) { + Foo[] fooArray = new Foo[] { new Foo() }; + } +} + +class Foo { } +""") + +test.run(arguments = '.') + +def get_class_files(dir): + def find_class_files(arg, dirname, fnames): + for fname in fnames: + if fname[-6:] == '.class': + arg.append(os.path.join(dirname, fname)) + result = [] + os.path.walk(dir, find_class_files, result) + result.sort() + return result + +classes_1 = get_class_files(test.workpath('class1')) +classes_2 = get_class_files(test.workpath('class2')) +classes_3 = get_class_files(test.workpath('class3')) +classes_4 = get_class_files(test.workpath('class4')) +classes_5 = get_class_files(test.workpath('class5')) + +expect_1 = [ + test.workpath('class1', 'com', 'other', 'Example2.class'), + test.workpath('class1', 'com', 'sub', 'foo', 'Example1.class'), + test.workpath('class1', 'com', 'sub', 'foo', 'Example3.class'), +] + +expect_2 = [ + test.workpath('class2', 'com', 'other', 'Example5.class'), + test.workpath('class2', 'com', 'sub', 'bar', 'Example4.class'), + test.workpath('class2', 'com', 'sub', 'bar', 'Example6.class'), +] + +expect_3 = [ + test.workpath('class3', 'Empty.class'), + test.workpath('class3', 'Example7.class'), + test.workpath('class3', 'Listener.class'), + test.workpath('class3', 'Private$1.class'), + test.workpath('class3', 'Private.class'), + test.workpath('class3', 'Test$1.class'), + test.workpath('class3', 'Test$2.class'), + test.workpath('class3', 'Test$3.class'), + test.workpath('class3', 'Test$Inner.class'), + test.workpath('class3', 'Test.class'), +] + +expect_4 = [ + test.workpath('class4', 'NestedExample$1.class'), + test.workpath('class4', 'NestedExample$2.class'), + test.workpath('class4', 'NestedExample.class'), +] + +expect_5 = [ + test.workpath('class5', 'Foo.class'), + test.workpath('class5', 'TestSCons.class'), +] + +def classes_must_match(dir, expect, got): + 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) + test.fail_test() + +classes_must_match('class1', expect_1, classes_1) +classes_must_match('class2', expect_2, classes_2) +classes_must_match('class3', expect_3, classes_3) +classes_must_match('class4', expect_4, classes_4) + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/MSVS/common-prefix.py b/test/MSVS/common-prefix.py index d40060c..4034a4a 100644 --- a/test/MSVS/common-prefix.py +++ b/test/MSVS/common-prefix.py @@ -69,9 +69,9 @@ vcproj_template = """\ \t\t\t> \t\t\t<Tool \t\t\t\tName="VCNMakeTool" -\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c Test.exe" +\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" \t\t\t\tOutput="Test.exe" \t\t\t\tPreprocessorDefinitions="" \t\t\t\tIncludeSearchPath="" diff --git a/test/MSVS/runfile.py b/test/MSVS/runfile.py index 5638916..23fd84b 100644 --- a/test/MSVS/runfile.py +++ b/test/MSVS/runfile.py @@ -69,9 +69,9 @@ expected_vcprojfile = """\ \t\t\t> \t\t\t<Tool \t\t\t\tName="VCNMakeTool" -\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c Test.exe" +\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" \t\t\t\tOutput="runfile.exe" \t\t\t\tPreprocessorDefinitions="" \t\t\t\tIncludeSearchPath="" diff --git a/test/MSVS/vs-6.0-files.py b/test/MSVS/vs-6.0-files.py index ce7ef46..04e7c93 100644 --- a/test/MSVS/vs-6.0-files.py +++ b/test/MSVS/vs-6.0-files.py @@ -77,8 +77,8 @@ CFG=Test - Win32 Release # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "" # PROP BASE Intermediate_Dir "" -# PROP BASE Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct Test.exe" -# PROP BASE Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct Test.exe" +# PROP BASE Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +# PROP BASE Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct "Test.exe"" # PROP BASE Target_File "Test.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" @@ -86,8 +86,8 @@ CFG=Test - Win32 Release # PROP Use_Debug_Libraries 0 # PROP Output_Dir "" # PROP Intermediate_Dir "" -# PROP Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct Test.exe" -# PROP Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct Test.exe" +# PROP Cmd_Line "echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +# PROP Rebuild_Opt "-c && echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN>" -C "<WORKPATH>" -f SConstruct "Test.exe"" # PROP Target_File "Test.exe" # PROP Bsc_Name "" # PROP Target_Dir "" diff --git a/test/MSVS/vs-7.0-files.py b/test/MSVS/vs-7.0-files.py index 8f98166..b9827e7 100644 --- a/test/MSVS/vs-7.0-files.py +++ b/test/MSVS/vs-7.0-files.py @@ -87,9 +87,9 @@ expected_vcprojfile = """\ \t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE"> \t\t\t<Tool \t\t\t\tName="VCNMakeTool" -\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c Test.exe" -\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" +\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" +\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" \t\t\t\tOutput="Test.exe"/> \t\t</Configuration> \t</Configurations> diff --git a/test/MSVS/vs-7.1-files.py b/test/MSVS/vs-7.1-files.py index 3ad2e97..057f34f 100644 --- a/test/MSVS/vs-7.1-files.py +++ b/test/MSVS/vs-7.1-files.py @@ -87,9 +87,9 @@ expected_vcprojfile = """\ \t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE"> \t\t\t<Tool \t\t\t\tName="VCNMakeTool" -\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c Test.exe" -\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" +\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" +\t\t\t\tRebuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" \t\t\t\tOutput="Test.exe"/> \t\t</Configuration> \t</Configurations> diff --git a/test/MSVS/vs-8.0-files.py b/test/MSVS/vs-8.0-files.py index 1d3c469..d7aa0d9 100644 --- a/test/MSVS/vs-8.0-files.py +++ b/test/MSVS/vs-8.0-files.py @@ -87,9 +87,9 @@ expected_vcprojfile = """\ \t\t\t> \t\t\t<Tool \t\t\t\tName="VCNMakeTool" -\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct Test.exe" -\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c Test.exe" +\t\t\t\tBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" +\t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" \t\t\t\tOutput="Test.exe" \t\t\t\tPreprocessorDefinitions="" \t\t\t\tIncludeSearchPath="" diff --git a/test/Parallel/duplicate-children.py b/test/Parallel/duplicate-children.py new file mode 100644 index 0000000..26d873b --- /dev/null +++ b/test/Parallel/duplicate-children.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that parallel builds work correctly when a Node is duplicated +in the children (once in the sources and once in the depends list). +""" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.write('cat.py', """\ +import sys +fp = open(sys.argv[1], 'wb') +for fname in sys.argv[2:]: + fp.write(open(fname, 'rb').read()) +fp.close() +""") + +test.write('sleep.py', """\ +import sys +import time +time.sleep(int(sys.argv[1])) +""") + +test.write('SConstruct', """ +# Test case for SCons issue #1608 +# Create a file "foo.in" in the current directory before running scons. +env = Environment() +env.Command('foo.out', ['foo.in'], '%(_python_)s cat.py $TARGET $SOURCE && %(_python_)s sleep.py 3') +env.Command('foobar', ['foo.out'], '%(_python_)s cat.py $TARGET $SOURCES') +env.Depends('foobar', 'foo.out') +""" % locals()) + +test.write('foo.in', "foo.in\n") + +test.run(arguments = '-j2 .') + +test.must_match('foo.out', "foo.in\n") +test.must_match('foobar', "foo.in\n") + +test.pass_test() diff --git a/test/QT/Tool.py b/test/QT/Tool.py new file mode 100644 index 0000000..9079225 --- /dev/null +++ b/test/QT/Tool.py @@ -0,0 +1,148 @@ +#!/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 applying env.Tool('qt') after running Configure checks +works properly. This was broken in 0.96.95. + +The configuration here is a moderately stripped-down version of the +real-world configuration for lprof (lprof.sourceforge.net). It's probably +not completely minimal, but we're leaving it as since it represents a +good real-world sanity check on the interaction of some key subsystems. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import os +import os.path + +def DoWithVariables(variables, prefix, what): + saved_variables = { } + for name in variables.keys(): + saved_variables[ name ] = env[ name ][:] + env[ name ].append(variables[ name ]) + + result = what() + + for name in saved_variables.keys(): + env[ name ] = saved_variables[ name ] + env[ prefix+name ] = variables[ name ] + + return result + +def CheckForQtAt(context, qtdir): + context.Message('Checking for Qt at %s... ' % qtdir) + libp = os.path.join(qtdir, 'lib') + cppp = os.path.join(qtdir, 'include') + result = AttemptLinkWithVariables(context, + { "LIBS": "qt-mt", "LIBPATH": libp , "CPPPATH": cppp }, + ''' +#include <qapplication.h> +int main(int argc, char **argv) { + QApplication qapp(argc, argv); + return 0; +} +''',".cpp","QT_") + context.Result(result) + return result + +def CheckForQt(context): + # list is currently POSIX centric - what happens with Windows? + potential_qt_dirs = [ + "/usr/share/qt3", # Debian unstable + "/usr/share/qt", + "/usr", + "/usr/local", + "/usr/lib/qt3", # Suse + "/usr/lib/qt", + "/usr/qt/3", # Gentoo + "/usr/pkg/qt3" # pkgsrc (NetBSD) + ] + + if os.environ.has_key('QTDIR'): + potential_qt_dirs.insert(0, os.environ[ 'QTDIR' ]) + + if env[ 'qt_directory' ] != "/": + uic_path = os.path.join(env['qt_directory'], 'bin', 'uic') + if os.path.isfile(uic_path): + potential_qt_dirs.insert(0, env[ 'qt_directory' ]) + else: + print "QT not found. Invalid qt_directory value - failed to find uic." + return 0 + + for i in potential_qt_dirs: + context.env.Replace(QTDIR = i) + if CheckForQtAt(context, i): + # additional checks to validate QT installation + if not os.path.isfile(os.path.join(i, 'bin', 'uic')): + print "QT - failed to find uic." + return 0 + if not os.path.isfile(os.path.join(i, 'bin', 'moc')): + print "QT - failed to find moc." + return 0 + if not os.path.exists(os.path.join(i, 'lib')): + print "QT - failed to find QT lib path." + return 0 + if not os.path.exists(os.path.join(i, 'include')): + print "QT - failed to find QT include path." + return 0 + return 1 + else: + if i==env['qt_directory']: + print "QT directory not valid. Failed QT test build." + return 0 + return 0 + +def AttemptLinkWithVariables(context, variables, code, extension, prefix): + return DoWithVariables(variables, + prefix, + lambda c=context, code=code, e=extension: + c.TryLink(code, e)) + +env = Environment(CPPPATH=['.'], LIBPATH=['.'], LIBS=[]) + +opts = Options('lprof.conf') +opts.Add(PathOption("qt_directory", "Path to Qt directory", "/")) +opts.Update(env) + +env['QT_LIB'] = 'qt-mt' +config = env.Configure(custom_tests = { + 'CheckForQt' : CheckForQt, +}) + +if not config.CheckForQt(): + print "Failed to find valid QT environment." + Exit(1) + +env.Tool('qt', ['$TOOL_PATH']) +""") + +test.run(arguments = '.') + +test.pass_test() diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py new file mode 100644 index 0000000..e34ddaa --- /dev/null +++ b/test/TEX/auxiliaries.py @@ -0,0 +1,139 @@ +#!/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 sections of LaTeX output that use auxiliary files (a +bibliography in our configuration below) are consistent when re-run +after modifying the input file. + +This checks for a bug that was triggered by the presence of auxiliary +files which were detected by SCons but then removed prior to invoking +TeX, causing the auxiliary sections to be excluded from the output. +That was fixed (courtesy Joel B. Mohler) by making all the relevant +auxiliary files Precious(). + +Test configuration courtesy Dmitry Mikhin. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +dvips = test.where_is('dvips') +latex = test.where_is('latex') + +if not dvips or not latex: + test.skip_test("Could not find dvips or latex; skipping test(s).\n") + + +test.subdir(['docs']) + +test.write(['SConstruct'], """\ +env = Environment(tools = ['pdftex', 'dvipdf', 'dvips', 'tex', 'latex'], + ENV = {}, + BUILD_DIR = '#build/docs') + +# Use 'duplicate=1' because LaTeX toolchain does not work properly for +# input/output files outside of the current directory + +env.BuildDir('$BUILD_DIR', 'docs', duplicate=1) +env.SConscript('$BUILD_DIR/SConscript', exports = ['env']) +""") + +test.write(['docs', 'SConscript'], """\ +Import('env') +envc = env.Clone() + +test_dvi = envc.DVI(source='test.tex') +test_ps = envc.PostScript(source='test.tex') +test_pdf = envc.PDF(source='test.tex') + +envc.Default(test_dvi) +envc.Default(test_ps) +envc.Default(test_pdf) +""") + +test.write(['docs', 'my.bib'], """\ +@ARTICLE{Mikhin, + author = "Dmitry {\uppercase{Y}u}. Mikhin", + title = "Blah!", + journal = "Some yellow paper", + year = "2007", + volume = "7", + number = "3", + pages = "1--2" +} +""") + +tex_input = r"""\documentclass{article} + +\title{BUG IN SCONS} + +\author{Dmitry Yu. Mikhin} + +\begin{document} + +\maketitle + + +\begin{abstract} +\noindent A bug in BibTeX processing? +\end{abstract} + + +\section{The problem} + +Provide a citation here: \cite{Mikhin}. + + +\bibliography{my} +\bibliographystyle{unsrtnat} + +\end{document} +""" + +test.write(['docs', 'test.tex'], tex_input) + +test.run(stderr=None) + +pdf_output_1 = test.read(['build', 'docs', 'test.pdf']) +ps_output_1 = test.read(['build', 'docs', 'test.ps']) + +# Adding blank lines will cause SCons to re-run the builds, but the +# actual contents of the output files shouldn't be any different. +# This assumption won't work if it's ever used with a toolchain that does +# something to the output like put a commented-out timestamp in a header. +test.write(['docs', 'test.tex'], tex_input + "\n\n\n") + +test.run(stderr=None) + +pdf_output_2 = test.read(['build', 'docs', 'test.pdf']) +ps_output_2 = test.read(['build', 'docs', 'test.ps']) + +test.fail_test(pdf_output_1 != pdf_output_2) +test.fail_test(ps_output_1 != ps_output_2) + +test.pass_test() diff --git a/test/TEX/bibtex-latex-rerun.py b/test/TEX/bibtex-latex-rerun.py new file mode 100644 index 0000000..2293216 --- /dev/null +++ b/test/TEX/bibtex-latex-rerun.py @@ -0,0 +1,99 @@ +#!/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 re-run LaTeX after running BibTeX in response to +changes in a .bib file. + +Thanks to Rob Managan for the patch that fixed this, and to Joel B. Mohler +for code clean up and packaging the test case. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write(['SConstruct'], """\ +PDF( 'bibtest.tex' ) +""") + +test.write(['bibtest.tex'], r""" +\documentclass{article} +\begin{document} +Learn about cool math in \cite{koblitz:elliptic_curves}. +\bibliographystyle{alpha} +\bibliography{sources} +\end{document} +""") + +sources_bib_content = r""" +@book{koblitz:elliptic_curves, + author = "Neal Koblitz", + title = "Elliptic Curves and Modular Forms", + year = "%s", + publisher = "Springer-Verlag New York Inc." +} +""" + + + +test.write('sources.bib', sources_bib_content % '1981') + +test.run() + +pdf_output_1 = test.read('bibtest.pdf') + + + +test.write('sources.bib', sources_bib_content % '1982') + +test.run() + +pdf_output_2 = test.read('bibtest.pdf') + +# If the PDF file is the same as it was previously, then it didn't +# pick up the change from 1981 to 1982, so fail. +test.fail_test(pdf_output_1 == pdf_output_2) + + + +# Double-check: clean everything and rebuild from scratch, which +# should force the PDF file to be the 1982 version. + +test.run(arguments = '-c') + +test.run() + +pdf_output_3 = test.read('bibtest.pdf') + +# If the PDF file is now different than the second run, then something +# else odd has happened, so fail. (Note that this test will be incorrect +# if the tool does something like insert a timestamp in the PDF file.) +test.fail_test(pdf_output_2 != pdf_output_3) + + + +test.pass_test() diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py index f827ac9..d4e2d79 100644 --- a/test/TEX/multi-run.py +++ b/test/TEX/multi-run.py @@ -42,7 +42,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') +test.subdir('work1', 'work2', 'work4') input_file = r""" @@ -55,6 +55,15 @@ As stated in \cite{X}, this is a bug-a-boo. \end{document} """ +input_file2 = r""" +\documentclass{article} +\begin{document} +Hello world. +% \bibliography{fooref} +% \bibliographystyle{plain} +\end{document} +""" + bibfile = r""" @Article{X, author = "Mr. X", @@ -86,6 +95,8 @@ PDF( "foo.tex" ) print foo_log test.fail_test(1) + + if latex: test.write(['work2', 'SConstruct'], """\ @@ -106,4 +117,16 @@ PDF( "foo.ltx" ) print foo_log test.fail_test(1) + + + test.write(['work4', 'SConstruct'], """\ +DVI( "foo.ltx" ) +""") + test.write(['work4', 'foo.ltx'], input_file2) + + test.run(chdir = 'work4', arguments = '.') + + test.up_to_date(chdir = 'work4', arguments = '.') + + test.pass_test() diff --git a/test/gnutools.py b/test/gnutools.py index 4bcea00..2180217 100644 --- a/test/gnutools.py +++ b/test/gnutools.py @@ -31,10 +31,13 @@ Testing the gnu tool chain, i.e. the tools 'gcc', 'g++' and 'gnulink'. import TestSCons import string import sys + _python_ = TestSCons._python_ _exe = TestSCons._exe -_dll = TestSCons._dll -dll_ = TestSCons.dll_ + +def dll(s): + return TestSCons.dll_ + s + TestSCons._dll + test = TestSCons.TestSCons() test.subdir('gnutools') @@ -111,40 +114,32 @@ env.SharedLibrary('c-and-cpp', Split('cfile1.c cppfile1.cpp')) test.run(chdir='work1') -def testObject(test, obj, command, flags): +def testObject(test, obj, expect): contents = test.read(test.workpath('work1', obj)) line1 = string.split(contents,'\n')[0] - items = string.split(line1, ' ') - cmd = '' - for i in items: - if i != '': - if cmd: - cmd = cmd + ' ' + i - else: - cmd = i - res = ((flags and (cmd == command + ' ' + flags)) or - (not flags and (cmd == command))) - if not res: print "'"+obj+command+flags+"'"+"!='"+str(line1)+"'" - return res - -if sys.platform == 'cygwin': - fpic = '' + actual = string.join(string.split(line1)) + if not expect == actual: + print "%s: %s != %s\n" % (obj, repr(expect), repr(actual)) + test.fail_test() + +if sys.platform in ('win32', 'cygwin'): + c_fpic = '' else: - fpic = ' -fPIC' - -test.fail_test(not testObject(test, 'cfile1.o', 'gcc', '-c') or - not testObject(test, 'cfile2.o', 'gcc', '-c') or - not testObject(test, 'cppfile1.o', 'g++', '-c') or - not testObject(test, 'cppfile2.o', 'g++', '-c') or - not testObject(test, 'cfile1.os', 'gcc', '-c' + fpic) or - not testObject(test, 'cfile2.os', 'gcc', '-c' + fpic) or - not testObject(test, 'cppfile1.os', 'g++', '-c' + fpic) or - not testObject(test, 'cppfile2.os', 'g++', '-c' + fpic) or - not testObject(test, 'c-only' + _exe, 'gcc', '') or - not testObject(test, 'cpp-only' + _exe, 'g++', '') or - not testObject(test, 'c-and-cpp' + _exe, 'g++', '') or - not testObject(test, dll_ + 'c-only' + _dll, 'gcc', '-shared') or - not testObject(test, dll_ + 'cpp-only' + _dll, 'g++', '-shared') or - not testObject(test, dll_ + 'c-and-cpp' + _dll, 'g++', '-shared')) + c_fpic = ' -fPIC' + +testObject(test, 'cfile1.o', 'gcc -c') +testObject(test, 'cfile2.o', 'gcc -c') +testObject(test, 'cppfile1.o', 'g++ -c') +testObject(test, 'cppfile2.o', 'g++ -c') +testObject(test, 'cfile1.os', 'gcc -c' + c_fpic) +testObject(test, 'cfile2.os', 'gcc -c' + c_fpic) +testObject(test, 'cppfile1.os', 'g++ -c -fPIC') +testObject(test, 'cppfile2.os', 'g++ -c -fPIC') +testObject(test, 'c-only' + _exe, 'gcc') +testObject(test, 'cpp-only' + _exe, 'g++') +testObject(test, 'c-and-cpp' + _exe, 'g++') +testObject(test, dll('c-only'), 'gcc -shared') +testObject(test, dll('cpp-only'), 'g++ -shared') +testObject(test, dll('c-and-cpp'), 'g++ -shared') test.pass_test() diff --git a/test/import.py b/test/import.py index 92797df..d267f00 100644 --- a/test/import.py +++ b/test/import.py @@ -52,6 +52,7 @@ platforms = [ for platform in platforms: test.write('SConstruct', """ +print "Platform %(platform)s" env = Environment(platform = '%(platform)s') import SCons.Platform.%(platform)s x = SCons.Platform.%(platform)s.generate @@ -198,6 +199,7 @@ error_output = { # An SConstruct for importing Tool names that have illegal characters # for Python variable names. indirect_import = """\ +print "Tool %(tool)s (indirect)" env = Environment(tools = ['%(tool)s']) SCons = __import__('SCons.Tool.%(tool)s', globals(), locals(), []) @@ -208,6 +210,7 @@ m.generate(env) # An SConstruct for importing Tool names "normally." direct_import = """\ +print "Tool %(tool)s (direct)" env = Environment(tools = ['%(tool)s']) import SCons.Tool.%(tool)s diff --git a/test/option/debug-pdb.py b/test/option/debug-pdb.py new file mode 100644 index 0000000..fa703d5 --- /dev/null +++ b/test/option/debug-pdb.py @@ -0,0 +1,41 @@ +#!/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 + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +""") + +test.run(arguments = "--debug=pdb", stdin = "n\ns\nq\n") +test.fail_test(string.find(test.stdout(), "(Pdb)") == -1) +test.fail_test(string.find(test.stdout(), "SCons") == -1) + +test.pass_test() diff --git a/test/option--debug.py b/test/option/debug-presub.py index a56f261..cdbefbd 100644 --- a/test/option--debug.py +++ b/test/option/debug-presub.py @@ -24,60 +24,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import sys -import string -import re -import time - import TestSCons _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.write('SConstruct', """ -env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') -env.Program('foo', Split('foo.c bar.c')) -""") - -test.write('foo.c', r""" -#include "foo.h" -int main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("f1.c\n"); - exit (0); -} -""") - -test.write('bar.c', """ -#include "bar.h" -""") - -test.write('foo.h', """ -#ifndef FOO_H -#define FOO_H -#include "bar.h" -#endif -""") - -test.write('bar.h', """ -#ifndef BAR_H -#define BAR_H -#include "foo.h" -#endif -""") - -############################ -# test --debug=pdb - -test.run(arguments = "--debug=pdb", stdin = "n\ns\nq\n") -test.fail_test(string.find(test.stdout(), "(Pdb)") == -1) -test.fail_test(string.find(test.stdout(), "SCons") == -1) - -############################ -# test --debug=presub - test.write('cat.py', """\ import sys open(sys.argv[2], "wb").write(open(sys.argv[1], "rb").read()) @@ -96,7 +48,7 @@ FILE = Builder(action="$FILECOM") TEMP = Builder(action="$TEMPCOM") LIST = Builder(action="$LISTCOM") FUNC = Builder(action=cat) -env = Environment(PYTHON='%(_python_)s', +env = Environment(PYTHON=r'%(_python_)s', BUILDERS = {'FILE':FILE, 'TEMP':TEMP, 'LIST':LIST, 'FUNC':FUNC}, FILECOM="$PYTHON cat.py $SOURCES $TARGET", TEMPCOM="$PYTHON cat.py $SOURCES temp\\n$PYTHON cat.py temp $TARGET", @@ -119,6 +71,10 @@ env.LIST('file15.out', 'file15.in') env.LIST('file16.out', 'file16.in') env.FUNC('file17.out', 'file17.in') env.FUNC('file18.out', 'file18.in') + +env2 = Environment(PYTHON=r'%(_python_)s', + CCCOM="$PYTHON cat.py $SOURCES $TARGET") +env2.Object('file20.obj', 'file20.c') """ % locals()) test.write('file01.in', "file01.in\n") @@ -139,6 +95,8 @@ test.write('file16.in', "file16.in\n") test.write('file17.in', "file17.in\n") test.write('file18.in', "file18.in\n") +test.write('file20.c', "file20.c\n") + expect = """\ Building file01.out with action: $PYTHON cat.py $SOURCES $TARGET @@ -215,6 +173,9 @@ cat(["file17.out"], ["file17.in"]) Building file18.out with action: cat(target, source, env) cat(["file18.out"], ["file18.in"]) +Building file20.obj with action: + $PYTHON cat.py $SOURCES $TARGET +%(_python_)s cat.py file20.c file20.obj """ % locals() test.run(arguments = "--debug=presub .", stdout=test.wrap_stdout(expect)) @@ -237,4 +198,6 @@ test.must_match('file16.out', "file16.in\n") test.must_match('file17.out', "file17.in\n") test.must_match('file18.out', "file18.in\n") +test.must_match('file20.obj', "file20.c\n") + test.pass_test() diff --git a/test/option/debug-time.py b/test/option/debug-time.py index b1471ba..51cfacf 100644 --- a/test/option/debug-time.py +++ b/test/option/debug-time.py @@ -30,49 +30,51 @@ import string import re import time +_python_ = TestSCons._python_ + test = TestSCons.TestSCons() -test.write('SConstruct', """ -env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') -env.Program('foo', Split('foo.c bar.c')) +test.write('sleep_cat.py', """\ +import sys +import time +time.sleep(int(sys.argv[1])) +fp = open(sys.argv[2], 'wb') +for arg in sys.argv[3:]: + fp.write(open(arg, 'rb').read()) +fp.close() +sys.exit(0) """) -test.write('foo.c', r""" -#include <stdio.h> -#include <stdlib.h> -#include "foo.h" -int main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf("f1.c\n"); - exit (0); -} -""") +test.write('SConstruct', """ +env = Environment(PYTHON = r'%(_python_)s', + SLEEP_CAT = r'sleep_cat.py', + CATCOM = '$PYTHON $SLEEP_CAT $SECONDS $TARGET $SOURCES', + SECONDS = ARGUMENTS.get('SLEEP', '0')) +f1 = env.Command('f1.out', 'f1.in', '$CATCOM') +f2 = env.Command('f2.out', 'f2.in', '$CATCOM') +f3 = env.Command('f3.out', 'f3.in', '$CATCOM') +f4 = env.Command('f4.out', 'f4.in', '$CATCOM') +env.Command('output', [f1, f2, f3, f4], '$CATCOM') +""" % locals()) -test.write('bar.c', """ -#include "bar.h" -""") +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") -test.write('foo.h', """ -#ifndef FOO_H -#define FOO_H -#include "bar.h" -#endif -""") -test.write('bar.h', """ -#ifndef BAR_H -#define BAR_H -#include "foo.h" -#endif -""") -def num(match, line): - return float(re.search(match, line).group(1)) +def num(s, match): + return float(re.search(match, s).group(1)) + +def within_tolerance(expected, actual, tolerance): + return abs((expected-actual)/actual) <= tolerance + + -# Try to make things a little more equal by measuring Python overhead -# executing a minimal file, and reading the scons.py script itself from -# disk so that it's already been cached. +# Try to make our results a little more accurate and repeatable by +# measuring Python overhead executing a minimal file, and reading the +# scons.py script itself from disk so that it's already been cached. test.write('pass.py', "pass\n") test.read(test.program) @@ -80,55 +82,85 @@ start_time = time.time() test.run(program=TestSCons.python, arguments=test.workpath('pass.py')) overhead = time.time() - start_time + + start_time = time.time() -test.run(arguments = "--debug=time .") +test.run(arguments = "-j1 --debug=time . SLEEP=0") complete_time = time.time() - start_time + + expected_total_time = complete_time - overhead -lines = string.split(test.stdout(), '\n') -expected_command_time = 0.0 -for cmdline in filter(lambda x: x[:23] == "Command execution time:", lines): - n = num(r'Command execution time: (\d+\.\d+) seconds', cmdline) - expected_command_time = expected_command_time + n +pattern = r'Command execution time: (\d+\.\d+) seconds' +times = map(float, re.findall(pattern, test.stdout())) +expected_command_time = reduce(lambda x, y: x + y, times, 0.0) -stdout = test.stdout() -total_time = num(r'Total build time: (\d+\.\d+) seconds', stdout) -sconscript_time = num(r'Total SConscript file execution time: (\d+\.\d+) seconds', stdout) -scons_time = num(r'Total SCons execution time: (\d+\.\d+) seconds', stdout) -command_time = num(r'Total command execution time: (\d+\.\d+) seconds', stdout) +stdout = test.stdout() -def within_tolerance(expected, actual, tolerance): - return abs((expected-actual)/actual) <= tolerance +total_time = num(stdout, r'Total build time: (\d+\.\d+) seconds') +sconscript_time = num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') +scons_time = num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') +command_time = num(stdout, r'Total command execution time: (\d+\.\d+) seconds') failures = [] if not within_tolerance(expected_command_time, command_time, 0.01): failures.append("""\ -SCons reported a total command execution time of %s, -but command execution times really totalled %s, +SCons -j1 reported a total command execution time of %(command_time)s, +but command execution times really totalled %(expected_command_time)s, outside of the 1%% tolerance. -""" % (command_time, expected_command_time)) +""" % locals()) added_times = sconscript_time+scons_time+command_time if not within_tolerance(total_time, added_times, 0.01): failures.append("""\ -SCons reported a total build time of %s, -but the various execution times actually totalled %s, +SCons -j1 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, outside of the 1%% tolerance. -""" % (total_time, added_times)) +""" % locals()) if not within_tolerance(total_time, expected_total_time, 0.15): failures.append("""\ -SCons reported total build time of %s, -but the actual measured build time was %s -(end-to-end time of %s less Python overhead of %s), +SCons -j1 reported total build time of %(total_time)s, +but the actual measured build time was %(expected_total_time)s +(end-to-end time of %(complete_time)s less Python overhead of %(overhead)s), outside of the 15%% tolerance. -""" % (total_time, expected_total_time, complete_time, overhead)) +""" % locals()) if failures: print string.join([test.stdout()] + failures, '\n') test.fail_test(1) + + +test.run(arguments = "-c") + +test.run(arguments = "-j4 --debug=time . SLEEP=1") + + + +stdout = test.stdout() + +total_time = num(stdout, r'Total build time: (\d+\.\d+) seconds') +sconscript_time = num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') +scons_time = num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') +command_time = num(stdout, r'Total command execution time: (\d+\.\d+) seconds') + +failures = [] + +added_times = sconscript_time+scons_time+command_time +if not within_tolerance(total_time, added_times, 0.01): + failures.append("""\ +SCons -j4 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, +outside of the 1%% tolerance. +""" % locals()) + +if failures: + print string.join([test.stdout()] + failures, '\n') + test.fail_test(1) + + test.pass_test() diff --git a/test/site_scons/no-site-dir.py b/test/site_scons/no-site-dir.py index 6f2f26e..3fc5a6d 100644 --- a/test/site_scons/no-site-dir.py +++ b/test/site_scons/no-site-dir.py @@ -71,9 +71,14 @@ e=Environment() print e.subst('no site: M4 is $M4, M4_MINE is $M4_MINE') """) -test.run(arguments = '-Q --no-site-dir .', -stdout = """no site: M4 is m4, M4_MINE is -scons: `.' is up to date.\n""") +test.run(arguments = '-Q --no-site-dir .') + +not_expected = """Hi there, I am in site_scons/site_init.py! +no site: M4 is my_m4, M4_MINE is 1 +scons: `.' is up to date. +""" + +test.fail_test(test.stdout() == not_expected) diff --git a/test/site_scons/sys-path.py b/test/site_scons/sys-path.py new file mode 100644 index 0000000..7af45aa --- /dev/null +++ b/test/site_scons/sys-path.py @@ -0,0 +1,65 @@ +#!/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 site_scons dir is added to sys.path as an +absolute path, so it will work from a subdir. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.subdir('site_scons') +test.subdir('sub1') + +test.write(['site_scons', 'testmod1.py'], """ +print "Imported site_scons/testmod1.py." +""") +test.write(['site_scons', 'testmod2.py'], """ +print "Imported site_scons/testmod2.py." +""") + +test.write(['sub1', 'SConscript'], """ +import sys +import testmod2 # This call did not work before the fix + +""") + +test.write('SConstruct', """ +import sys +import testmod1 # this always worked +SConscript('sub1/SConscript') +""") + +test.run(arguments = '-Q .', + stdout = """Imported site_scons/testmod1.py. +Imported site_scons/testmod2.py. +scons: `.' is up to date.\n""") + +test.pass_test() + +# end of file |