1"""Tests for distutils.util."""
2import os
3import sys
4import unittest
5from copy import copy
6from test.support import run_unittest
7
8from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
9from distutils.util import (get_platform, convert_path, change_root,
10                            check_environ, split_quoted, strtobool,
11                            rfc822_escape, byte_compile,
12                            grok_environment_error)
13from distutils import util # used to patch _environ_checked
14from distutils.sysconfig import get_config_vars
15from distutils import sysconfig
16from distutils.tests import support
17import _osx_support
18
19class UtilTestCase(support.EnvironGuard, unittest.TestCase):
20
21    def setUp(self):
22        super(UtilTestCase, self).setUp()
23        # saving the environment
24        self.name = os.name
25        self.platform = sys.platform
26        self.version = sys.version
27        self.sep = os.sep
28        self.join = os.path.join
29        self.isabs = os.path.isabs
30        self.splitdrive = os.path.splitdrive
31        self._config_vars = copy(sysconfig._config_vars)
32
33        # patching os.uname
34        if hasattr(os, 'uname'):
35            self.uname = os.uname
36            self._uname = os.uname()
37        else:
38            self.uname = None
39            self._uname = None
40
41        os.uname = self._get_uname
42
43    def tearDown(self):
44        # getting back the environment
45        os.name = self.name
46        sys.platform = self.platform
47        sys.version = self.version
48        os.sep = self.sep
49        os.path.join = self.join
50        os.path.isabs = self.isabs
51        os.path.splitdrive = self.splitdrive
52        if self.uname is not None:
53            os.uname = self.uname
54        else:
55            del os.uname
56        sysconfig._config_vars = copy(self._config_vars)
57        super(UtilTestCase, self).tearDown()
58
59    def _set_uname(self, uname):
60        self._uname = uname
61
62    def _get_uname(self):
63        return self._uname
64
65    def test_get_platform(self):
66
67        # windows XP, 32bits
68        os.name = 'nt'
69        sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
70                       '[MSC v.1310 32 bit (Intel)]')
71        sys.platform = 'win32'
72        self.assertEqual(get_platform(), 'win32')
73
74        # windows XP, amd64
75        os.name = 'nt'
76        sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
77                       '[MSC v.1310 32 bit (Amd64)]')
78        sys.platform = 'win32'
79        self.assertEqual(get_platform(), 'win-amd64')
80
81        # windows XP, itanium
82        os.name = 'nt'
83        sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
84                       '[MSC v.1310 32 bit (Itanium)]')
85        sys.platform = 'win32'
86        self.assertEqual(get_platform(), 'win-ia64')
87
88        # macbook
89        os.name = 'posix'
90        sys.version = ('2.5 (r25:51918, Sep 19 2006, 08:49:13) '
91                       '\n[GCC 4.0.1 (Apple Computer, Inc. build 5341)]')
92        sys.platform = 'darwin'
93        self._set_uname(('Darwin', 'macziade', '8.11.1',
94                   ('Darwin Kernel Version 8.11.1: '
95                    'Wed Oct 10 18:23:28 PDT 2007; '
96                    'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
97        _osx_support._remove_original_values(get_config_vars())
98        get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
99
100        get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
101                                       '-fwrapv -O3 -Wall -Wstrict-prototypes')
102
103        cursize = sys.maxsize
104        sys.maxsize = (2 ** 31)-1
105        try:
106            self.assertEqual(get_platform(), 'macosx-10.3-i386')
107        finally:
108            sys.maxsize = cursize
109
110        # macbook with fat binaries (fat, universal or fat64)
111        _osx_support._remove_original_values(get_config_vars())
112        get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
113        get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
114                                       '/Developer/SDKs/MacOSX10.4u.sdk  '
115                                       '-fno-strict-aliasing -fno-common '
116                                       '-dynamic -DNDEBUG -g -O3')
117
118        self.assertEqual(get_platform(), 'macosx-10.4-fat')
119
120        _osx_support._remove_original_values(get_config_vars())
121        os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
122        self.assertEqual(get_platform(), 'macosx-10.4-fat')
123
124
125        _osx_support._remove_original_values(get_config_vars())
126        get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
127                                       '/Developer/SDKs/MacOSX10.4u.sdk  '
128                                       '-fno-strict-aliasing -fno-common '
129                                       '-dynamic -DNDEBUG -g -O3')
130
131        self.assertEqual(get_platform(), 'macosx-10.4-intel')
132
133        _osx_support._remove_original_values(get_config_vars())
134        get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
135                                       '/Developer/SDKs/MacOSX10.4u.sdk  '
136                                       '-fno-strict-aliasing -fno-common '
137                                       '-dynamic -DNDEBUG -g -O3')
138        self.assertEqual(get_platform(), 'macosx-10.4-fat3')
139
140        _osx_support._remove_original_values(get_config_vars())
141        get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
142                                       '/Developer/SDKs/MacOSX10.4u.sdk  '
143                                       '-fno-strict-aliasing -fno-common '
144                                       '-dynamic -DNDEBUG -g -O3')
145        self.assertEqual(get_platform(), 'macosx-10.4-universal')
146
147        _osx_support._remove_original_values(get_config_vars())
148        get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
149                                       '/Developer/SDKs/MacOSX10.4u.sdk  '
150                                       '-fno-strict-aliasing -fno-common '
151                                       '-dynamic -DNDEBUG -g -O3')
152
153        self.assertEqual(get_platform(), 'macosx-10.4-fat64')
154
155        for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
156            _osx_support._remove_original_values(get_config_vars())
157            get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
158                                           '/Developer/SDKs/MacOSX10.4u.sdk  '
159                                           '-fno-strict-aliasing -fno-common '
160                                           '-dynamic -DNDEBUG -g -O3'%(arch,))
161
162            self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
163
164
165        # linux debian sarge
166        os.name = 'posix'
167        sys.version = ('2.3.5 (#1, Jul  4 2007, 17:28:59) '
168                       '\n[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]')
169        sys.platform = 'linux2'
170        self._set_uname(('Linux', 'aglae', '2.6.21.1dedibox-r7',
171                    '#1 Mon Apr 30 17:25:38 CEST 2007', 'i686'))
172
173        self.assertEqual(get_platform(), 'linux-i686')
174
175        # XXX more platforms to tests here
176
177    def test_convert_path(self):
178        # linux/mac
179        os.sep = '/'
180        def _join(path):
181            return '/'.join(path)
182        os.path.join = _join
183
184        self.assertEqual(convert_path('/home/to/my/stuff'),
185                         '/home/to/my/stuff')
186
187        # win
188        os.sep = '\\'
189        def _join(*path):
190            return '\\'.join(path)
191        os.path.join = _join
192
193        self.assertRaises(ValueError, convert_path, '/home/to/my/stuff')
194        self.assertRaises(ValueError, convert_path, 'home/to/my/stuff/')
195
196        self.assertEqual(convert_path('home/to/my/stuff'),
197                         'home\\to\\my\\stuff')
198        self.assertEqual(convert_path('.'),
199                         os.curdir)
200
201    def test_change_root(self):
202        # linux/mac
203        os.name = 'posix'
204        def _isabs(path):
205            return path[0] == '/'
206        os.path.isabs = _isabs
207        def _join(*path):
208            return '/'.join(path)
209        os.path.join = _join
210
211        self.assertEqual(change_root('/root', '/old/its/here'),
212                         '/root/old/its/here')
213        self.assertEqual(change_root('/root', 'its/here'),
214                         '/root/its/here')
215
216        # windows
217        os.name = 'nt'
218        def _isabs(path):
219            return path.startswith('c:\\')
220        os.path.isabs = _isabs
221        def _splitdrive(path):
222            if path.startswith('c:'):
223                return ('', path.replace('c:', ''))
224            return ('', path)
225        os.path.splitdrive = _splitdrive
226        def _join(*path):
227            return '\\'.join(path)
228        os.path.join = _join
229
230        self.assertEqual(change_root('c:\\root', 'c:\\old\\its\\here'),
231                         'c:\\root\\old\\its\\here')
232        self.assertEqual(change_root('c:\\root', 'its\\here'),
233                         'c:\\root\\its\\here')
234
235        # BugsBunny os (it's a great os)
236        os.name = 'BugsBunny'
237        self.assertRaises(DistutilsPlatformError,
238                          change_root, 'c:\\root', 'its\\here')
239
240        # XXX platforms to be covered: mac
241
242    def test_check_environ(self):
243        util._environ_checked = 0
244        if 'HOME' in os.environ:
245            del os.environ['HOME']
246
247        # posix without HOME
248        if os.name == 'posix':  # this test won't run on windows
249            check_environ()
250            import pwd
251            self.assertEqual(os.environ['HOME'], pwd.getpwuid(os.getuid())[5])
252        else:
253            check_environ()
254
255        self.assertEqual(os.environ['PLAT'], get_platform())
256        self.assertEqual(util._environ_checked, 1)
257
258    def test_split_quoted(self):
259        self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
260                         ['one', 'two', 'three', 'four'])
261
262    def test_strtobool(self):
263        yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1')
264        no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N')
265
266        for y in yes:
267            self.assertTrue(strtobool(y))
268
269        for n in no:
270            self.assertFalse(strtobool(n))
271
272    def test_rfc822_escape(self):
273        header = 'I am a\npoor\nlonesome\nheader\n'
274        res = rfc822_escape(header)
275        wanted = ('I am a%(8s)spoor%(8s)slonesome%(8s)s'
276                  'header%(8s)s') % {'8s': '\n'+8*' '}
277        self.assertEqual(res, wanted)
278
279    def test_dont_write_bytecode(self):
280        # makes sure byte_compile raise a DistutilsError
281        # if sys.dont_write_bytecode is True
282        old_dont_write_bytecode = sys.dont_write_bytecode
283        sys.dont_write_bytecode = True
284        try:
285            self.assertRaises(DistutilsByteCompileError, byte_compile, [])
286        finally:
287            sys.dont_write_bytecode = old_dont_write_bytecode
288
289    def test_grok_environment_error(self):
290        # test obsolete function to ensure backward compat (#4931)
291        exc = IOError("Unable to find batch file")
292        msg = grok_environment_error(exc)
293        self.assertEqual(msg, "error: Unable to find batch file")
294
295
296def test_suite():
297    return unittest.makeSuite(UtilTestCase)
298
299if __name__ == "__main__":
300    run_unittest(test_suite())
301