1 """ 2 Test suite for _osx_support: shared OS X support functions. 3 """ 4 5 import os 6 import platform 7 import shutil 8 import stat 9 import sys 10 import unittest 11 12 import test.test_support 13 14 import _osx_support 15 16 @unittest.skipUnless(sys.platform.startswith("darwin"), "requires OS X") 17 class 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 276 def test_main(): 277 if sys.platform == 'darwin': 278 test.test_support.run_unittest(Test_OSXSupport) 279 280 if __name__ == "__main__": 281 test_main() 282