• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2Test suite for _osx_support: shared OS X support functions.
3"""
4
5import os
6import platform
7import shutil
8import stat
9import sys
10import unittest
11
12import test.test_support
13
14import _osx_support
15
16@unittest.skipUnless(sys.platform.startswith("darwin"), "requires OS X")
17class Test_OSXSupport(unittest.TestCase):
18
19    def setUp(self):
20        self.maxDiff = None
21        self.prog_name = 'bogus_program_xxxx'
22        self.temp_path_dir = os.path.abspath(os.getcwd())
23        self.env = test.test_support.EnvironmentVarGuard()
24        self.addCleanup(self.env.__exit__)
25        for cv in ('CFLAGS', 'LDFLAGS', 'CPPFLAGS',
26                            'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
27                            'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
28                            'PY_CORE_CFLAGS'):
29            if cv in self.env:
30                self.env.unset(cv)
31
32    def add_expected_saved_initial_values(self, config_vars, expected_vars):
33        # Ensure that the initial values for all modified config vars
34        # are also saved with modified keys.
35        expected_vars.update(('_OSX_SUPPORT_INITIAL_'+ k,
36                config_vars[k]) for k in config_vars
37                    if config_vars[k] != expected_vars[k])
38
39    def test__find_executable(self):
40        if self.env['PATH']:
41            self.env['PATH'] = self.env['PATH'] + ':'
42        self.env['PATH'] = self.env['PATH'] + os.path.abspath(self.temp_path_dir)
43        test.test_support.unlink(self.prog_name)
44        self.assertIsNone(_osx_support._find_executable(self.prog_name))
45        self.addCleanup(test.test_support.unlink, self.prog_name)
46        with open(self.prog_name, 'w') as f:
47            f.write("#!/bin/sh\n/bin/echo OK\n")
48        os.chmod(self.prog_name, stat.S_IRWXU)
49        self.assertEqual(self.prog_name,
50                            _osx_support._find_executable(self.prog_name))
51
52    def test__read_output(self):
53        if self.env['PATH']:
54            self.env['PATH'] = self.env['PATH'] + ':'
55        self.env['PATH'] = self.env['PATH'] + os.path.abspath(self.temp_path_dir)
56        test.test_support.unlink(self.prog_name)
57        self.addCleanup(test.test_support.unlink, self.prog_name)
58        with open(self.prog_name, 'w') as f:
59            f.write("#!/bin/sh\n/bin/echo ExpectedOutput\n")
60        os.chmod(self.prog_name, stat.S_IRWXU)
61        self.assertEqual('ExpectedOutput',
62                            _osx_support._read_output(self.prog_name))
63
64    def test__find_build_tool(self):
65        out = _osx_support._find_build_tool('cc')
66        self.assertTrue(os.path.isfile(out),
67                            'cc not found - check xcode-select')
68
69    def test__get_system_version(self):
70        self.assertTrue(platform.mac_ver()[0].startswith(
71                                    _osx_support._get_system_version()))
72
73    def test__remove_original_values(self):
74        config_vars = {
75        'CC': 'gcc-test -pthreads',
76        }
77        expected_vars = {
78        'CC': 'clang -pthreads',
79        }
80        cv = 'CC'
81        newvalue = 'clang -pthreads'
82        _osx_support._save_modified_value(config_vars, cv, newvalue)
83        self.assertNotEqual(expected_vars, config_vars)
84        _osx_support._remove_original_values(config_vars)
85        self.assertEqual(expected_vars, config_vars)
86
87    def test__save_modified_value(self):
88        config_vars = {
89        'CC': 'gcc-test -pthreads',
90        }
91        expected_vars = {
92        'CC': 'clang -pthreads',
93        }
94        self.add_expected_saved_initial_values(config_vars, expected_vars)
95        cv = 'CC'
96        newvalue = 'clang -pthreads'
97        _osx_support._save_modified_value(config_vars, cv, newvalue)
98        self.assertEqual(expected_vars, config_vars)
99
100    def test__save_modified_value_unchanged(self):
101        config_vars = {
102        'CC': 'gcc-test -pthreads',
103        }
104        expected_vars = config_vars.copy()
105        cv = 'CC'
106        newvalue = 'gcc-test -pthreads'
107        _osx_support._save_modified_value(config_vars, cv, newvalue)
108        self.assertEqual(expected_vars, config_vars)
109
110    def test__supports_universal_builds(self):
111        import platform
112        mac_ver_tuple = tuple(int(i) for i in
113                            platform.mac_ver()[0].split('.')[0:2])
114        self.assertEqual(mac_ver_tuple >= (10, 4),
115                            _osx_support._supports_universal_builds())
116
117    def test__find_appropriate_compiler(self):
118        compilers = (
119                        ('gcc-test', 'i686-apple-darwin11-llvm-gcc-4.2'),
120                        ('clang', 'clang version 3.1'),
121                    )
122        config_vars = {
123        'CC': 'gcc-test -pthreads',
124        'CXX': 'cc++-test',
125        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  ',
126        'LDFLAGS': '-arch ppc -arch i386   -g',
127        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
128        'BLDSHARED': 'gcc-test -bundle -arch ppc -arch i386 -g',
129        'LDSHARED': 'gcc-test -bundle -arch ppc -arch i386 '
130                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
131        }
132        expected_vars = {
133        'CC': 'clang -pthreads',
134        'CXX': 'clang++',
135        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  ',
136        'LDFLAGS': '-arch ppc -arch i386   -g',
137        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
138        'BLDSHARED': 'clang -bundle -arch ppc -arch i386 -g',
139        'LDSHARED': 'clang -bundle -arch ppc -arch i386 '
140                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
141        }
142        self.add_expected_saved_initial_values(config_vars, expected_vars)
143
144        suffix = (':' + self.env['PATH']) if self.env['PATH'] else ''
145        self.env['PATH'] = os.path.abspath(self.temp_path_dir) + suffix
146        for c_name, c_output in compilers:
147            test.test_support.unlink(c_name)
148            self.addCleanup(test.test_support.unlink, c_name)
149            with open(c_name, 'w') as f:
150                f.write("#!/bin/sh\n/bin/echo " + c_output)
151            os.chmod(c_name, stat.S_IRWXU)
152        self.assertEqual(expected_vars,
153                            _osx_support._find_appropriate_compiler(
154                                    config_vars))
155
156    def test__remove_universal_flags(self):
157        config_vars = {
158        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  ',
159        'LDFLAGS': '-arch ppc -arch i386   -g',
160        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
161        'BLDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 -g',
162        'LDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 '
163                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
164        }
165        expected_vars = {
166        'CFLAGS': '-fno-strict-aliasing  -g -O3    ',
167        'LDFLAGS': '    -g',
168        'CPPFLAGS': '-I.  ',
169        'BLDSHARED': 'gcc-4.0 -bundle    -g',
170        'LDSHARED': 'gcc-4.0 -bundle      -g',
171        }
172        self.add_expected_saved_initial_values(config_vars, expected_vars)
173
174        self.assertEqual(expected_vars,
175                            _osx_support._remove_universal_flags(
176                                    config_vars))
177
178    def test__remove_unsupported_archs(self):
179        config_vars = {
180        'CC': 'clang',
181        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  ',
182        'LDFLAGS': '-arch ppc -arch i386   -g',
183        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
184        'BLDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 -g',
185        'LDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 '
186                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
187        }
188        expected_vars = {
189        'CC': 'clang',
190        'CFLAGS': '-fno-strict-aliasing  -g -O3  -arch i386  ',
191        'LDFLAGS': ' -arch i386   -g',
192        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
193        'BLDSHARED': 'gcc-4.0 -bundle   -arch i386 -g',
194        'LDSHARED': 'gcc-4.0 -bundle   -arch i386 '
195                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
196        }
197        self.add_expected_saved_initial_values(config_vars, expected_vars)
198
199        suffix = (':' + self.env['PATH']) if self.env['PATH'] else ''
200        self.env['PATH'] = os.path.abspath(self.temp_path_dir) + suffix
201        c_name = 'clang'
202        test.test_support.unlink(c_name)
203        self.addCleanup(test.test_support.unlink, c_name)
204        # exit status 255 means no PPC support in this compiler chain
205        with open(c_name, 'w') as f:
206            f.write("#!/bin/sh\nexit 255")
207        os.chmod(c_name, stat.S_IRWXU)
208        self.assertEqual(expected_vars,
209                            _osx_support._remove_unsupported_archs(
210                                    config_vars))
211
212    def test__override_all_archs(self):
213        self.env['ARCHFLAGS'] = '-arch x86_64'
214        config_vars = {
215        'CC': 'clang',
216        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  ',
217        'LDFLAGS': '-arch ppc -arch i386   -g',
218        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
219        'BLDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 -g',
220        'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
221                        '-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
222        }
223        expected_vars = {
224        'CC': 'clang',
225        'CFLAGS': '-fno-strict-aliasing  -g -O3     -arch x86_64',
226        'LDFLAGS': '    -g -arch x86_64',
227        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
228        'BLDSHARED': 'gcc-4.0 -bundle    -g -arch x86_64',
229        'LDSHARED': 'gcc-4.0 -bundle   -isysroot '
230                        '/Developer/SDKs/MacOSX10.4u.sdk -g -arch x86_64',
231        }
232        self.add_expected_saved_initial_values(config_vars, expected_vars)
233
234        self.assertEqual(expected_vars,
235                            _osx_support._override_all_archs(
236                                    config_vars))
237
238    def test__check_for_unavailable_sdk(self):
239        config_vars = {
240        'CC': 'clang',
241        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  '
242                        '-isysroot /Developer/SDKs/MacOSX10.1.sdk',
243        'LDFLAGS': '-arch ppc -arch i386   -g',
244        'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.1.sdk',
245        'BLDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 -g',
246        'LDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 '
247                        '-isysroot /Developer/SDKs/MacOSX10.1.sdk -g',
248        }
249        expected_vars = {
250        'CC': 'clang',
251        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  '
252                        ' ',
253        'LDFLAGS': '-arch ppc -arch i386   -g',
254        'CPPFLAGS': '-I.  ',
255        'BLDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 -g',
256        'LDSHARED': 'gcc-4.0 -bundle  -arch ppc -arch i386 '
257                        ' -g',
258        }
259        self.add_expected_saved_initial_values(config_vars, expected_vars)
260
261        self.assertEqual(expected_vars,
262                            _osx_support._check_for_unavailable_sdk(
263                                    config_vars))
264
265    def test_get_platform_osx(self):
266        # Note, get_platform_osx is currently tested more extensively
267        # indirectly by test_sysconfig and test_distutils
268        config_vars = {
269        'CFLAGS': '-fno-strict-aliasing  -g -O3 -arch ppc -arch i386  '
270                        '-isysroot /Developer/SDKs/MacOSX10.1.sdk',
271        'MACOSX_DEPLOYMENT_TARGET': '10.6',
272        }
273        result = _osx_support.get_platform_osx(config_vars, ' ', ' ', ' ')
274        self.assertEqual(('macosx', '10.6', 'fat'), result)
275
276def test_main():
277    if sys.platform == 'darwin':
278        test.test_support.run_unittest(Test_OSXSupport)
279
280if __name__ == "__main__":
281    test_main()
282