diff options
Diffstat (limited to 'test/Java')
-rw-r--r-- | test/Java/JARCHDIR.py | 46 | ||||
-rw-r--r-- | test/Java/JAVACCOM.py | 2 | ||||
-rw-r--r-- | test/Java/JAVACCOMSTR.py | 6 | ||||
-rw-r--r-- | test/Java/JAVACLASSPATH.py | 104 | ||||
-rw-r--r-- | test/Java/JAVASOURCEPATH.py | 81 | ||||
-rw-r--r-- | test/Java/Java-1.4.py | 93 | ||||
-rw-r--r-- | test/Java/Java-1.5.py | 93 | ||||
-rw-r--r-- | test/Java/Java-1.6.py | 93 | ||||
-rw-r--r-- | test/Java/multi-step.py | 567 | ||||
-rw-r--r-- | test/Java/source-files.py | 127 | ||||
-rw-r--r-- | test/Java/swig-dependencies.py | 135 |
11 files changed, 1280 insertions, 67 deletions
diff --git a/test/Java/JARCHDIR.py b/test/Java/JARCHDIR.py index 9250843..f7d9fca 100644 --- a/test/Java/JARCHDIR.py +++ b/test/Java/JARCHDIR.py @@ -28,8 +28,14 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Test that when JARCHDIR that our command to create .jar files correctly finds all the .class files (by putting -C in front of each class file argument). + +Includes logic to make sure that expansions of $JARCHDIR that include +${TARGET} or ${SOURCE} work. """ +import os +import string + import TestSCons test = TestSCons.TestSCons() @@ -50,6 +56,8 @@ else: if not where_jar: test.skip_test("Could not find Java jar, skipping test(s).\n") + + test.write('SConstruct', """ dir = 'dist' env = Environment(tools = ['javac', 'jar'], @@ -64,9 +72,19 @@ jar = env.Jar(File('c.jar', dir), bin) env = env.Clone(JARCHDIR = '.') inner = env.Jar('inner.jar', 'Inner$$Class.class') +target_env = env.Clone(JARCHDIR = '${TARGET.dir}') +target_env.Jar('out/t.jar', 'in/t.class') + +source_env = env.Clone(JARCHDIR = '${SOURCE.dir}') +source_env.Jar('out/s.jar', 'in/s.class') + Default(bin, jar, inner) """ % locals()) + + +test.subdir('in') + test.write('a.java', """\ package foo.bar; public class a {} @@ -77,8 +95,36 @@ package foo.bar; public class b {} """) +test.write(['in', 's.class'], "s.class\n") + +# Okay, this is bogus, but we're going with it for testing purposes. +# If jar gets a command line like: +# +# jar cf out/t.jar -C out /tmp/tmpXYZZY/in/t.class +# +# Empirically, it doesn't seem to treat the absolute path name +# of the argument class file as an absolute path, but looks for +# "out/tmp/tmpXYZZY/in/t.class". SCons, however, still looks for it in +# the path name specified on the command line. To make this test work, +# we're going to just create the t.class file in both locations, and +# we can revisit this if someone actually tries to use ${TARGET.dir} +# in a real-life expansion. Right now, it at least makes sure things +# don't blow up (i.e., validates that we pass the right arguments to +# env.subst() in the code that handle jar). + +p = test.workpath('out') +for d in string.split(test.workpath('in'), os.sep): + p = p + d + test.subdir(p) + p = p + os.sep + +test.write([p, 't.class'], "t.class\n") +test.write(['in', 't.class'], "t.class\n") + test.write('Inner$Class.class', "Inner$Class.class\n") test.run(arguments = '.') + + test.pass_test() diff --git a/test/Java/JAVACCOM.py b/test/Java/JAVACCOM.py index 7086a2a..b6a30e9 100644 --- a/test/Java/JAVACCOM.py +++ b/test/Java/JAVACCOM.py @@ -60,7 +60,7 @@ test.write(['src', 'file3.java'], "file3.java\n/*javac*/\n") test.run() -test.must_match(['classes', 'src', 'file1.class'], +test.must_match(['classes', 'file1.class'], "file1.java\nfile2.java\nfile3.java\n") diff --git a/test/Java/JAVACCOMSTR.py b/test/Java/JAVACCOMSTR.py index 44b1449..88fa31d 100644 --- a/test/Java/JAVACCOMSTR.py +++ b/test/Java/JAVACCOMSTR.py @@ -62,16 +62,16 @@ test.write(['src', 'file1.java'], "file1.java\n/*javac*/\n") test.write(['src', 'file2.java'], "file2.java\n/*javac*/\n") test.write(['src', 'file3.java'], "file3.java\n/*javac*/\n") -classes_src_file1_class = os.path.join('classes', 'src', 'file1.class') +classes_file1_class = os.path.join('classes', 'file1.class') src_file1_java= os.path.join('src', 'file1.java') src_file2_java= os.path.join('src', 'file2.java') src_file3_java= os.path.join('src', 'file3.java') test.run(stdout = test.wrap_stdout("""\ -Compiling class(es) %(classes_src_file1_class)s from %(src_file1_java)s %(src_file2_java)s %(src_file3_java)s +Compiling class(es) %(classes_file1_class)s from %(src_file1_java)s %(src_file2_java)s %(src_file3_java)s """ % locals())) -test.must_match(['classes', 'src', 'file1.class'], +test.must_match(['classes', 'file1.class'], "file1.java\nfile2.java\nfile3.java\n") diff --git a/test/Java/JAVACLASSPATH.py b/test/Java/JAVACLASSPATH.py new file mode 100644 index 0000000..0ae7dea --- /dev/null +++ b/test/Java/JAVACLASSPATH.py @@ -0,0 +1,104 @@ +#!/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 $JAVASOURCEPATH allows finding Java .class +files in alternate locations by adding the -classpath option +to the javac command line. +""" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +ENV = test.java_ENV() + +if test.detect_tool('javac', ENV=ENV): + where_javac = test.detect('JAVAC', 'javac', ENV=ENV) +else: + where_javac = test.where_is('javac') +if not where_javac: + test.skip_test("Could not find Java javac, skipping test(s).\n") + +if test.detect_tool('javah', ENV=ENV): + where_javah = test.detect('JAVAH', 'javah', ENV=ENV) +else: + where_javah = test.where_is('javah') +if not where_javah: + test.skip_test("Could not find Java javah, skipping test(s).\n") + +test.write('SConstruct', """ +env = Environment(tools = ['javac', 'javah'], + JAVAC = r'%(where_javac)s', + JAVAH = r'%(where_javah)s') +j1 = env.Java(target = 'class1', source = 'com1/Example1.java') +j2 = env.Java(target = 'class2', source = 'com2/Example2.java') +env.JavaH(target = 'outdir', source = [j1, j2], JAVACLASSPATH = 'class2') +""" % locals()) + +test.subdir('com1', 'com2') + +test.write(['com1', 'Example1.java'], """\ +package com; + +public class Example1 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com2', 'Example2.java'], """\ +package com; + +public class Example2 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.run(arguments = '.') + +test.must_exist(['class1', 'com', 'Example1.class']) +test.must_exist(['class2', 'com', 'Example2.class']) + +test.must_exist(['outdir', 'com_Example1.h']) +test.must_exist(['outdir', 'com_Example2.h']) + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Java/JAVASOURCEPATH.py b/test/Java/JAVASOURCEPATH.py new file mode 100644 index 0000000..069e228 --- /dev/null +++ b/test/Java/JAVASOURCEPATH.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 use of $JAVASOURCEPATH allows finding source .java +files in alternate locations by adding the -sourcepath option +to the javac command line. +""" + +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', 'javah'], + JAVAC = r'%(where_javac)s') +bar = env.Java(target = 'bar/classes', + source = 'bar/src/TestBar.java', + JAVASOURCEPATH = ['foo/src']) +""" % locals()) + +test.subdir('foo', + ['foo', 'src'], + ['foo', 'src', 'com'], + ['foo', 'src', 'com', 'foo'], + ['foo', 'src', 'com', 'foo', 'test'], + 'bar', ['bar', 'src']) + +test.write(['foo', 'src', 'com', 'foo', 'test', 'TestFoo.java'], """\ +package com.foo.test; +public class TestFoo {;} +""") + +test.write(['bar', 'src', 'TestBar.java'], """\ +package com.bar.test; +import com.foo.test.TestFoo; +class TestBar extends TestFoo {;} +""") + +test.run(arguments = '.') + +test.must_exist(['bar', 'classes', 'com', 'bar', 'test', 'TestBar.class']) +test.must_exist(['bar', 'classes', 'com', 'foo', 'test', 'TestFoo.class']) + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Java/Java-1.4.py b/test/Java/Java-1.4.py index 8c3af59..3d3d47a 100644 --- a/test/Java/Java-1.4.py +++ b/test/Java/Java-1.4.py @@ -58,6 +58,7 @@ 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']) +env.Java(target = 'class6', source = ['src6']) """ % locals()) test.subdir('com', @@ -67,7 +68,8 @@ test.subdir('com', 'src1', 'src2', 'src4', - 'src5') + 'src5', + 'src6') test.write(['com', 'sub', 'foo', 'Example1.java'], """\ package com.sub.foo; @@ -273,23 +275,27 @@ class TestSCons { class Foo { } """) -test.run(arguments = '.') +# Test private inner class instantiation, courtesy Tilo Prutz: +# http://scons.tigris.org/issues/show_bug.cgi?id=1594 +test.write(['src6', 'TestSCons.java'], """\ +class test +{ + test() + { + super(); + new inner(); + } -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 + static class inner + { + private inner() {} + } +} +""") -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')) + + +test.run(arguments = '.') expect_1 = [ test.workpath('class1', 'com', 'other', 'Example2.class'), @@ -327,9 +333,27 @@ expect_5 = [ test.workpath('class5', 'TestSCons.class'), ] +expect_6 = [ + test.workpath('class6', 'test$1.class'), + test.workpath('class6', 'test$inner.class'), + test.workpath('class6', 'test.class'), +] + failed = None -def classes_must_match(dir, expect, got): +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 + +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: @@ -339,13 +363,40 @@ def classes_must_match(dir, expect, got): sys.stderr.write(' %s\n' % c) failed = 1 -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) +def classes_must_not_exist(dir, expect): + global failed + present = filter(os.path.exists, expect) + if present: + sys.stderr.write("Found the following unexpected class files in '%s' after cleaning:\n" % dir) + for c in present: + sys.stderr.write(' %s\n' % c) + failed = 1 + +classes_must_match('class1', expect_1) +classes_must_match('class2', expect_2) +classes_must_match('class3', expect_3) +classes_must_match('class4', expect_4) +classes_must_match('class5', expect_5) +classes_must_match('class6', expect_6) test.fail_test(failed) test.up_to_date(options='--debug=explain', arguments = '.') +test.run(arguments = '-c .') + +classes_must_not_exist('class1', expect_1) +classes_must_not_exist('class2', expect_2) +classes_must_not_exist('class3', expect_3) +classes_must_not_exist('class4', expect_4) +classes_must_not_exist('class5', expect_5) +# This test case should pass, but doesn't. +# The expect_6 list contains the class files that the Java compiler +# actually creates, apparently because of the "private" instantiation +# of the "inner" class. Our parser doesn't currently detect this, so +# it doesn't know to remove that generated class file. +#classes_must_not_exist('class6', expect_6) + +test.fail_test(failed) + test.pass_test() diff --git a/test/Java/Java-1.5.py b/test/Java/Java-1.5.py index 0b3ba27..4ac3d96 100644 --- a/test/Java/Java-1.5.py +++ b/test/Java/Java-1.5.py @@ -59,6 +59,7 @@ 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']) +env.Java(target = 'class6', source = ['src6']) """ % locals()) test.subdir('com', @@ -68,7 +69,8 @@ test.subdir('com', 'src1', 'src2', 'src4', - 'src5') + 'src5', + 'src6') test.write(['com', 'sub', 'foo', 'Example1.java'], """\ package com.sub.foo; @@ -274,23 +276,27 @@ class TestSCons { class Foo { } """) -test.run(arguments = '.') +# Test private inner class instantiation, courtesy Tilo Prutz: +# http://scons.tigris.org/issues/show_bug.cgi?id=1594 +test.write(['src6', 'TestSCons.java'], """\ +class test +{ + test() + { + super(); + new inner(); + } -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 + static class inner + { + private inner() {} + } +} +""") -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')) + + +test.run(arguments = '.') expect_1 = [ test.workpath('class1', 'com', 'other', 'Example2.class'), @@ -328,9 +334,27 @@ expect_5 = [ test.workpath('class5', 'TestSCons.class'), ] +expect_6 = [ + test.workpath('class6', 'test$1.class'), + test.workpath('class6', 'test$inner.class'), + test.workpath('class6', 'test.class'), +] + failed = None -def classes_must_match(dir, expect, got): +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 + +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: @@ -340,13 +364,40 @@ def classes_must_match(dir, expect, got): sys.stderr.write(' %s\n' % c) failed = 1 -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) +def classes_must_not_exist(dir, expect): + global failed + present = filter(os.path.exists, expect) + if present: + sys.stderr.write("Found the following unexpected class files in '%s' after cleaning:\n" % dir) + for c in present: + sys.stderr.write(' %s\n' % c) + failed = 1 + +classes_must_match('class1', expect_1) +classes_must_match('class2', expect_2) +classes_must_match('class3', expect_3) +classes_must_match('class4', expect_4) +classes_must_match('class5', expect_5) +classes_must_match('class6', expect_6) test.fail_test(failed) test.up_to_date(options='--debug=explain', arguments = '.') +test.run(arguments = '-c .') + +classes_must_not_exist('class1', expect_1) +classes_must_not_exist('class2', expect_2) +classes_must_not_exist('class3', expect_3) +classes_must_not_exist('class4', expect_4) +classes_must_not_exist('class5', expect_5) +# This test case should pass, but doesn't. +# The expect_6 list contains the class files that the Java compiler +# actually creates, apparently because of the "private" instantiation +# of the "inner" class. Our parser doesn't currently detect this, so +# it doesn't know to remove that generated class file. +#classes_must_not_exist('class6', expect_6) + +test.fail_test(failed) + test.pass_test() diff --git a/test/Java/Java-1.6.py b/test/Java/Java-1.6.py index 0b4ddd7..f2b629a 100644 --- a/test/Java/Java-1.6.py +++ b/test/Java/Java-1.6.py @@ -59,6 +59,7 @@ 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']) +env.Java(target = 'class6', source = ['src6']) """ % locals()) test.subdir('com', @@ -68,7 +69,8 @@ test.subdir('com', 'src1', 'src2', 'src4', - 'src5') + 'src5', + 'src6') test.write(['com', 'sub', 'foo', 'Example1.java'], """\ package com.sub.foo; @@ -274,23 +276,27 @@ class TestSCons { class Foo { } """) -test.run(arguments = '.') +# Test private inner class instantiation, courtesy Tilo Prutz: +# http://scons.tigris.org/issues/show_bug.cgi?id=1594 +test.write(['src6', 'TestSCons.java'], """\ +class test +{ + test() + { + super(); + new inner(); + } -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 + static class inner + { + private inner() {} + } +} +""") -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')) + + +test.run(arguments = '.') expect_1 = [ test.workpath('class1', 'com', 'other', 'Example2.class'), @@ -328,9 +334,27 @@ expect_5 = [ test.workpath('class5', 'TestSCons.class'), ] +expect_6 = [ + test.workpath('class6', 'test$1.class'), + test.workpath('class6', 'test$inner.class'), + test.workpath('class6', 'test.class'), +] + failed = None -def classes_must_match(dir, expect, got): +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 + +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: @@ -340,13 +364,40 @@ def classes_must_match(dir, expect, got): sys.stderr.write(' %s\n' % c) failed = 1 -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) +def classes_must_not_exist(dir, expect): + global failed + present = filter(os.path.exists, expect) + if present: + sys.stderr.write("Found the following unexpected class files in '%s' after cleaning:\n" % dir) + for c in present: + sys.stderr.write(' %s\n' % c) + failed = 1 + +classes_must_match('class1', expect_1) +classes_must_match('class2', expect_2) +classes_must_match('class3', expect_3) +classes_must_match('class4', expect_4) +classes_must_match('class5', expect_5) +classes_must_match('class6', expect_6) test.fail_test(failed) test.up_to_date(options='--debug=explain', arguments = '.') +test.run(arguments = '-c .') + +classes_must_not_exist('class1', expect_1) +classes_must_not_exist('class2', expect_2) +classes_must_not_exist('class3', expect_3) +classes_must_not_exist('class4', expect_4) +classes_must_not_exist('class5', expect_5) +# This test case should pass, but doesn't. +# The expect_6 list contains the class files that the Java compiler +# actually creates, apparently because of the "private" instantiation +# of the "inner" class. Our parser doesn't currently detect this, so +# it doesn't know to remove that generated class file. +#classes_must_not_exist('class6', expect_6) + +test.fail_test(failed) + test.pass_test() diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py new file mode 100644 index 0000000..1b69838 --- /dev/null +++ b/test/Java/multi-step.py @@ -0,0 +1,567 @@ +#!/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__" + +""" +Real-world test (courtesy Leanid Nazdrynau) of the multi-step +capabilities of the various Java Builders. +""" + +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") + +swig = test.where_is('swig') +if not swig: + test.skip_test('Can not find installed "swig", skipping test.\n') + + + +test.subdir(['src'], + ['src', 'HelloApplet'], + ['src', 'HelloApplet', 'com'], + ['src', 'javah'], + ['src', 'jni'], + ['src', 'server'], + ['src', 'server', 'JavaSource'], + ['src', 'server', 'JavaSource', 'com'], + ['src', 'server', 'JavaSource', 'com', 'gnu'], + ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons'], + ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web'], + ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools'], + ['src', 'server', 'WebContent'], + ['src', 'server', 'WebContent', 'META-INF'], + ['src', 'server', 'WebContent', 'WEB-INF'], + ['src', 'server', 'WebContent', 'WEB-INF', 'conf'], + ['src', 'server', 'WebContent', 'WEB-INF', 'lib'], + ['src', 'server', 'WebContent', 'theme']) + +test.write(['SConstruct'], """\ +import os,sys +env=Environment(tools = ['default', 'javac', 'javah']) +Export('env') +env.PrependENVPath('PATH',os.environ.get('PATH',[])) +env['INCPREFIX']='-I' +env.Append(SWIGFLAGS=['-c++','$_CPPINCFLAGS']) + +#this is for JNI +#env.Append(CCFLAGS=['/IN:/jdk/v1.3.1/include','/IN:/jdk/v1.3.1/include/win32']) + +#this for windows only C++ build +#env.Append(CXXFLAGS='-GX') + +env.Append(CPPPATH='.') + +env.BuildDir('buildout', 'src', duplicate=0) + +if sys.platform=='darwin': + env.Append(CPPPATH=['/System/Library/Frameworks/JavaVM.framework/Headers']) + +#If you do not have swig on your system please remove 'buildout/jni/SConscript' line from next call +env.SConscript(['buildout/server/JavaSource/SConscript', + 'buildout/HelloApplet/SConscript', + 'buildout/jni/SConscript', + 'buildout/javah/SConscript']) +""") + +test.write(['src', 'HelloApplet', 'Hello.html'], """\ +<HTML> +<HEAD> +<TITLE> Applet Hello </TITLE> +</HEAD> +<BODY> +<CENTER> +<applet name="Hello" archive="HelloApplet.jar" code="com.Hello.Hello.class" + width="800" height="286" MAYSCRIPT> +</applet> +</CENTER> +</BODY> +</HTML> + +""") + +test.write(['src', 'HelloApplet', 'SConscript'], """\ +import os +Import ("env") +denv=env.Copy() +classes=denv.Java(target='classes',source=['com']) +#set correct path for jar +denv['JARCHDIR']=os.path.join(denv.Dir('.').get_abspath(),'classes') +denv.Jar('HelloApplet',classes) + + +#To sign applet you have to create keystore before and made a calls like this + +#keystore='/path/to/jarsignkey' +#denv['JARSIGNFLAGS']='-keystore '+keystore+' -storepass pass -keypass passkey' +#denv['JARSIGNALIAS']='ALIAS' +#denv['JARCOM']=[denv['JARCOM'],'$JARSIGNCOM'] + +""") + +test.write(['src', 'HelloApplet', 'com', 'Hello.java'], """\ +package com.Hello; +import java.awt.*; +import java.applet.*; + +public class Hello extends Applet { + public void paint(Graphics g) { + g.drawString("Hello from SCons signed applet",250,150); + } + } + +""") + +test.write(['src', 'javah', 'MyID.cc'], """\ +#include "MyID.h" +int getMyID() +{ + return 0; +} +""") + +test.write(['src', 'javah', 'MyID.java'], """\ +import java.util.*; +import java.io.IOException; +import java.lang.reflect.*; + +public class MyID +{ + static private long current = System.currentTimeMillis(); + static public String get() + { + current++; + return new Long( current ).toString(); + } +} +""") + +test.write(['src', 'javah', 'SConscript'], """\ +Import('env') +denv=env.Copy() +denv['JARCHDIR']=denv.Dir('.').get_abspath() +denv.Jar('myid','MyID.java') +denv.JavaH(denv.Dir('.').get_abspath(),'MyID.java') +denv.SharedLibrary('myid','MyID.cc') + +""") + +test.write(['src', 'jni', 'A.java'], """\ +package web.jni; + +import web.jni.*; + +public class A +{ +class C +{ + void echo2( String text ) + { + System.out.println( text+"aa" ); + + } +} +class B +{ + void echo( String text ) + { + System.out.println( text ); + C c = new C(); + c.echo2("from B callin C"); + } +} + public void main( String[] x) + { + B b = new B(); + b.echo("123"); + C c = new C(); + c.echo2("456"); + } +} +""") + +test.write(['src', 'jni', 'JniWrapper.cc'], """\ +#include <vector> +#include <iostream> + +#include "JniWrapper.h" + + + +JniWrapper::JniWrapper( JNIEnv *pEnv ) + : mpEnv( pEnv ) +{ +} + +JniWrapper::JniWrapper( const JniWrapper& rJniWrapper ) + : mpEnv( rJniWrapper.mpEnv ) +{ +} + +JniWrapper::~JniWrapper() +{ + +} + +JniWrapper& JniWrapper::operator=( const JniWrapper& rJniWrapper ) +{ + if ( this != &rJniWrapper ) + { + mpEnv = rJniWrapper.mpEnv; + } + return *this; +} + +std::string JniWrapper::unmarshalString( jstring value ) +{ + std::string result; + if( value ) + { + const char *pStr = mpEnv->GetStringUTFChars( value, 0 ); + result = pStr; + mpEnv->ReleaseStringUTFChars( value, pStr ); + } + return result; +} + +jobject JniWrapper::marshalDouble( double value ) +{ + jclass classObject = mpEnv->FindClass( "java/lang/Double" ); + jmethodID constructorId = mpEnv->GetMethodID( classObject, "<init>", "(D)V" ); + jobject result = mpEnv->NewObject( classObject, constructorId, value ); + + return result; +} + +jobject JniWrapper::getVectorElement( jobject values, int i ) +{ + jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); + jmethodID methodID = mpEnv->GetMethodID( vectorClass, + "elementAt", + "(I)Ljava/lang/Object;" ); + jobject result = mpEnv->CallObjectMethod( values, methodID, i ); + + return result; +} + +jobject JniWrapper::newVector() +{ + jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); + jmethodID constructorID = mpEnv->GetMethodID( vectorClass, "<init>", "()V" ); + jobject result = mpEnv->NewObject( vectorClass, constructorID ); + + return result; +} + +void JniWrapper::addElement( jobject vector, jobject element ) +{ + jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); + jmethodID addElementMethodID = mpEnv->GetMethodID( vectorClass, + "addElement", + "(Ljava/lang/Object;)V" ); + + mpEnv->CallVoidMethod( vector, addElementMethodID, element ); +} + +jobject JniWrapper::marshalDoubleVector( const std::vector<double>& rVector ) +{ + jobject result = newVector(); + + for ( int i = 0; i < rVector.size(); i++ ) + { + addElement( result, marshalDouble( rVector[i] ) ); + } + + return result; +} + +std::pair<std::string, std::string> JniWrapper::unmarshalPairString( jobject vector ) +{ + std::pair<std::string, std::string> result; + result.first = unmarshalString( (jstring)getVectorElement( vector, 0 ) ); + result.second = unmarshalString( (jstring)getVectorElement( vector, 1 ) ); + + return result; +} +""") + +test.write(['src', 'jni', 'JniWrapper.h'], """\ +#ifndef JniWrapper_h +#define JniWrapper_h + +#include <jni.h> +/** + * Provides routines for dealing with JNI translation etc. + */ + +class JniWrapper +{ +public: + JniWrapper( JNIEnv *pEnv ); + JniWrapper( const JniWrapper& rJniWrapper ); + virtual ~JniWrapper(); + JniWrapper& operator=( const JniWrapper& rJniWrapper ); + + + std::string unmarshalString( jstring value ); + + jstring marshalString( const std::string& value ); + + jbyteArray marshalByteArray( const std::string& value ); + + double unmarshalDouble( jobject value ); + + jobject marshalDouble( double value ); + jobject marshallStringVector( const std::vector<std::string>& rMap ); + + jobject marshalDoubleVector( const std::vector<double>& rVector ); + std::pair<std::string, std::string> unmarshalPairString( jobject ); + +protected: + JNIEnv *mpEnv; + +private: + JniWrapper(); + jobject newVector(); + void addElement( jobject vector, jobject element ); + jobject getVectorElement( jobject values, int i ); + +}; + +#endif // JniWrapper_h + + +""") + +test.write(['src', 'jni', 'SConscript'], """\ +Import ("env") +denv=env.Copy() + +denv.Append(SWIGFLAGS=['-java']) +denv.SharedLibrary('scons',['JniWrapper.cc','Sample.i']) +denv['JARCHDIR']=denv.Dir('.').get_abspath() +denv.Jar(['Sample.i','A.java']) +""") + +test.write(['src', 'jni', 'Sample.h'], """\ +#include <vector> +#include <iostream> + +class SampleTest +{ +public: + std::vector<double> test1( std::pair<std::string, std::string> param ) + { + std::vector<double> result; + result.push_back(10); + return result; + } +}; + +""") + +test.write(['src', 'jni', 'Sample.i'], """\ +%module Sample + +%{ +#include "Sample.h" +#include "JniWrapper.h" +%} + +%typemap(jni) std::vector<double>, std::vector<double>& "jobject" +%typemap(jtype) std::vector<double>, std::vector<double>& "java.util.Vector" +%typemap(jstype) std::vector<double>, std::vector<double>& "java.util.Vector" + +// return a Vector of Doubles +%typemap(javaout) std::vector<double> { + return $jnicall; +} +%typemap(out) std::vector<double> { + JniWrapper JniWrapper(jenv); + $result = JniWrapper.marshalDoubleVector( $1 ); +} + +/********************************************************************* + * + * Pairs of String (IN/OUT) + * + *********************************************************************/ +%typemap(jni) std::pair<std::string, std::string>, const std::pair<std::string, std::string>& "jobject" +%typemap(jtype) std::pair<std::string, std::string>, const std::pair<std::string, std::string>& "java.util.Vector" +%typemap(jstype) std::pair<std::string, std::string>, const std::pair<std::string, std::string>& "java.util.Vector" +%typemap(javain) std::pair<std::string, std::string>, const std::pair<std::string, std::string>& "$javainput" + +// pass in by reference a Vector of std::string +%typemap(in) const std::pair<std::string, std::string>& { + $1 = new std::pair<std::string, std::string>(); + JniWrapper JniWrapper(jenv); + *($1) = JniWrapper.unmarshalPairString( $input ); +} + +//cleanup +%typemap(freearg) const std::pair<std::string, std::string>& { + delete $1; +} + +%include "Sample.h" + +// generate:Sample.java +// generate:SampleJni.java +// generate:SampleTest.java +""") + +test.write(['src', 'server', 'JavaSource', 'SConscript'], """\ +import os +Import ("env") +classes=env.Java(target='classes',source=['com']) + +HelloApplet=os.path.join('#/buildout/HelloApplet/HelloApplet.jar') +env['WARXFILES']=['SConscript','.cvsignore'] +env['WARXDIRS']=['CVS'] +#env.War('scons',[classes,Dir('../WebContent'),HelloApplet]) +""") + +test.write(['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools', 'Bool.java'], """\ +package com.gnu.scons.web.tools; +public class Bool { + boolean flag; + + public Bool() + { + flag = false; + } + + public Bool( boolean aFlag ) + { + flag = aFlag; + } + + public boolean booleanValue() + { + return flag; + } +} +""") + +test.write(['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools', 'StringUtils.java'], """\ +package com.gnu.scons.web.tools; + +import java.util.Iterator; +import java.util.Map; + +public class StringUtils +{ + public static String toPercent( String value ) + { + if ( value.equals("") ) + { + return ""; + } + else + { + return value + "%"; + } + } + +} +""") + +test.write(['src', 'server', 'WebContent', 'index.html'], """\ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<HTML> +<HEAD> +<META http-equiv="refresh" content="0;URL=go?action=home"> +<TITLE>index.html</TITLE> +</HEAD> +<BODY> +<P><a href="go?action=home">go?action=home</a></P> +</BODY> +</HTML> +""") + +test.write(['src', 'server', 'WebContent', 'META-INF', 'MANIFEST.MF'], """\ +Manifest-Version: 1.0 +Class-Path: + +""") + +test.write(['src', 'server', 'WebContent', 'WEB-INF', 'web.xml'], """\ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> +<web-app id="WebExample"> + <display-name>scons</display-name> + <servlet> + <servlet-name>WebExample</servlet-name> + <display-name>WebExample</display-name> + <servlet-class>com.gnu.scons.web.tool.WebExample</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>WebExample</servlet-name> + <url-pattern>/go</url-pattern> + </servlet-mapping> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + <welcome-file>index.htm</welcome-file> + </welcome-file-list> +</web-app> +""") + +test.write(['src', 'server', 'WebContent', 'WEB-INF', 'conf', 'app.properties'], """\ +logging = webExample.Example +""") + +test.write(['src', 'server', 'WebContent', 'theme', 'Master.css'], """\ +body +{ + font-family: Helvetica,Sans-Serif; + font-size: 11pt; +} +""") + +test.run(arguments = '.') + +test.must_exist(['buildout', 'javah', 'myid.jar']) +test.must_exist(['buildout', 'javah', 'MyID', 'MyID.class']) + +test.must_exist(['buildout', 'jni', 'Sample.class']) +test.must_exist(['buildout', 'jni', 'Sample.java']) +test.must_exist(['buildout', 'jni', 'SampleJNI.class']) +test.must_exist(['buildout', 'jni', 'SampleJNI.java']) +test.must_exist(['buildout', 'jni', 'SampleTest.class']) +test.must_exist(['buildout', 'jni', 'SampleTest.java']) + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Java/source-files.py b/test/Java/source-files.py new file mode 100644 index 0000000..8d2506f --- /dev/null +++ b/test/Java/source-files.py @@ -0,0 +1,127 @@ +#!/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 pass the Java() builder explicit lists of .java +files as sources. +""" + +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', 'javah'], + JAVAC = r'%(where_javac)s') +env.Java(target = 'class1', source = 'com/Example1.java') +env.Java(target = 'class2', source = ['com/Example2.java', 'com/Example3.java']) +""" % locals()) + +test.subdir('com', 'src') + +test.write(['com', 'Example1.java'], """\ +package com; + +public class Example1 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'Example2.java'], """\ +package com; + +public class Example2 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'Example3.java'], """\ +package com; + +public class Example3 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.write(['com', 'Example4.java'], """\ +package com; + +public class Example4 +{ + + public static void main(String[] args) + { + + } + +} +""") + +test.run(arguments = '.') + +test.must_exist (['class1', 'com', 'Example1.class']) +test.must_not_exist(['class1', 'com', 'Example2.class']) +test.must_not_exist(['class1', 'com', 'Example3.class']) +test.must_not_exist(['class1', 'com', 'Example4.class']) + +test.must_not_exist(['class2', 'com', 'Example1.class']) +test.must_exist (['class2', 'com', 'Example2.class']) +test.must_exist (['class2', 'com', 'Example3.class']) +test.must_not_exist(['class2', 'com', 'Example4.class']) + +test.up_to_date(arguments = '.') + +test.pass_test() diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py new file mode 100644 index 0000000..c6961f2 --- /dev/null +++ b/test/Java/swig-dependencies.py @@ -0,0 +1,135 @@ +#!/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 dependencies on SWIG-generated .java files work correctly. + +Test case courtesy Jonathan (toolshed@tigris.org). +""" + +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") + + +test.subdir(['foo'], + ['java'], + ['java', 'build']) + +test.write(['SConstruct'], """\ +import os + +env = Environment(ENV = os.environ) + +env.Append(CPPFLAGS = ' -g -Wall') + +Export('env') + +SConscript('#foo/SConscript') +SConscript('#java/SConscript') +""") + +test.write(['foo', 'SConscript'], """\ +Import('env') + +env.SharedLibrary('foo', 'foo.cpp') +""") + +test.write(['foo', 'foo.cpp'], """\ +#include "foo.h" + +int fooAdd(int a, int b) { + return a + b; +} +""") + +test.write(['foo', 'foo.h'], """\ +int fooAdd(int, int); +""") + +test.write(['java', 'Java_foo_interface.i'], """\ +#include "foo.h" + +%module foopack +""") + +test.write(['java', 'SConscript'], """\ +import os + +Import('env') + +# unnecessary? +env = env.Copy() + +env.Prepend(CPPPATH = ['#foo',]) + +libadd = ['foo',] + +libpath = ['#foo',] + +#swigflags = '-c++ -java -Wall -package foopack -Ifoo' +swigflags = '-c++ -java -Wall -Ifoo' + +Java_foo_interface = env.SharedLibrary( + 'Java_foo_interface', + 'Java_foo_interface.i', + LIBS = libadd, + LIBPATH = libpath, + SWIGFLAGS = swigflags, + SWIGOUTDIR = Dir('build'), + SWIGCXXFILESUFFIX = "_wrap.cpp") + +foopack_jar_javac = env.Java('classes', 'build') + +env['JARCHDIR'] = 'java/classes' +foopack_jar = env.Jar(target = 'foopack.jar', source = 'classes') +""") + +test.run(arguments = '.') + +#test.must_exist(['java', 'classes', 'foopack', 'foopack.class']) +#test.must_exist(['java', 'classes', 'foopack', 'foopackJNI.class']) +test.must_exist(['java', 'classes', 'foopack.class']) +test.must_exist(['java', 'classes', 'foopackJNI.class']) + +test.up_to_date(arguments = '.') + +test.pass_test() |