Fix test to work with all versions of Python
[scons.git] / test / SWIG / live.py
1 #!/usr/bin/env python
2 #
3 # __COPYRIGHT__
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #
24
25 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26
27 """
28 Test SWIG behavior with a live, installed SWIG.
29 """
30
31 import os.path
32 import string
33 import sys
34
35 import TestSCons
36
37 # swig-python expects specific filenames.
38 # the platform specific suffix won't necessarily work.
39 if sys.platform == 'win32':
40     _dll = '.dll'
41 else:
42     _dll   = '.so'
43
44 test = TestSCons.TestSCons()
45
46 swig = test.where_is('swig')
47 if not swig:
48     test.skip_test('Can not find installed "swig", skipping test.\n')
49
50
51 python = test.where_is('python')
52
53 # handle testing on other platforms:
54 ldmodule_prefix = '_'
55
56 test.run(program = python, stdin = """\
57 import os, sys
58 try:
59         py_ver = 'python%d.%d' % sys.version_info[:2]
60 except AttributeError:
61         py_ver = 'python' + sys.version[:3]
62 print os.path.join(sys.prefix, 'include', py_ver)
63 print os.path.join(sys.prefix, 'lib', py_ver, 'config')
64 print py_ver
65 """)
66
67 #TODO(1.5) config_info = test.stdout().strip().split('\n')
68 config_info = string.split(string.strip(test.stdout()), '\n')
69 python_include,python_libpath,python_lib = config_info
70
71 Python_h = os.path.join(python_include, 'Python.h')
72 if not os.path.exists(Python_h):
73     test.skip_test('Can not find %s, skipping test.\n' % Python_h)
74
75 test.write("wrapper.py",
76 """import os
77 import string
78 import sys
79 open('%s', 'wb').write("wrapper.py\\n")
80 os.system(string.join(sys.argv[1:], " "))
81 """ % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
82
83 test.write('SConstruct', """\
84 foo = Environment(SWIGFLAGS='-python',
85                   CPPPATH=r'%(python_include)s',
86                   LDMODULEPREFIX='%(ldmodule_prefix)s',
87                   LDMODULESUFFIX='%(_dll)s',
88                   SWIG=r'%(swig)s',
89                   LIBPATH=r'%(python_libpath)s',
90                   LIBS='%(python_lib)s',
91                   )
92
93 import sys
94 if sys.version[0] == '1':
95     # SWIG requires the -classic flag on pre-2.0 Python versions.
96     foo.Append(SWIGFLAGS = ' -classic')
97
98 swig = foo.Dictionary('SWIG')
99 bar = foo.Clone(SWIG = r'"%(python)s" wrapper.py ' + swig)
100 foo.LoadableModule(target = 'foo', source = ['foo.c', 'foo.i'])
101 bar.LoadableModule(target = 'bar', source = ['bar.c', 'bar.i'])
102 """ % locals())
103
104 test.write("foo.c", """\
105 char *
106 foo_string()
107 {
108     return "This is foo.c!";
109 }
110 """)
111
112 test.write("foo.i", """\
113 %module foo
114 %{
115 /* Put header files here (optional) */
116 /*
117  * This duplication shouldn't be necessary, I guess, but it seems
118  * to suppress "cast to pointer from integer of different size"
119  * warning messages on some systems.
120  */
121 extern char *foo_string();
122 %}
123
124 extern char *foo_string();
125 """)
126
127 test.write("bar.c", """\
128 char *
129 bar_string()
130 {
131     return "This is bar.c!";
132 }
133 """)
134
135 test.write("bar.i", """\
136 %module \t bar
137 %{
138 /* Put header files here (optional) */
139 /*
140  * This duplication shouldn't be necessary, I guess, but it seems
141  * to suppress "cast to pointer from integer of different size"
142  * warning messages on some systems.
143  */
144 extern char *bar_string();
145 %}
146
147 extern char *bar_string();
148 """)
149
150 test.run(arguments = ldmodule_prefix+'foo' + _dll)
151
152 test.must_not_exist(test.workpath('wrapper.out'))
153
154 test.run(program = python, stdin = """\
155 import foo
156 print foo.foo_string()
157 """, stdout="""\
158 This is foo.c!
159 """)
160
161 test.up_to_date(arguments = ldmodule_prefix+'foo' + _dll)
162
163 test.run(arguments = ldmodule_prefix+'bar' + _dll)
164
165 test.must_match('wrapper.out', "wrapper.py\n")
166
167 test.run(program = python, stdin = """\
168 import foo
169 import bar
170 print foo.foo_string()
171 print bar.bar_string()
172 """, stdout="""\
173 This is foo.c!
174 This is bar.c!
175 """)
176
177 test.up_to_date(arguments = '.')
178
179
180 test.pass_test()