Home | History | Annotate | Download | only in test
      1 from unittest import mock
      2 import os
      3 import platform
      4 import subprocess
      5 import sys
      6 import sysconfig
      7 import tempfile
      8 import unittest
      9 import warnings
     10 
     11 from test import support
     12 
     13 class PlatformTest(unittest.TestCase):
     14     def test_architecture(self):
     15         res = platform.architecture()
     16 
     17     @support.skip_unless_symlink
     18     def test_architecture_via_symlink(self): # issue3762
     19         # On Windows, the EXE needs to know where pythonXY.dll and *.pyd is at
     20         # so we add the directory to the path, PYTHONHOME and PYTHONPATH.
     21         env = None
     22         if sys.platform == "win32":
     23             env = {k.upper(): os.environ[k] for k in os.environ}
     24             env["PATH"] = "{};{}".format(
     25                 os.path.dirname(sys.executable), env.get("PATH", ""))
     26             env["PYTHONHOME"] = os.path.dirname(sys.executable)
     27             if sysconfig.is_python_build(True):
     28                 env["PYTHONPATH"] = os.path.dirname(os.__file__)
     29 
     30         def get(python, env=None):
     31             cmd = [python, '-c',
     32                 'import platform; print(platform.architecture())']
     33             p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
     34                                  stderr=subprocess.PIPE, env=env)
     35             r = p.communicate()
     36             if p.returncode:
     37                 print(repr(r[0]))
     38                 print(repr(r[1]), file=sys.stderr)
     39                 self.fail('unexpected return code: {0} (0x{0:08X})'
     40                           .format(p.returncode))
     41             return r
     42 
     43         real = os.path.realpath(sys.executable)
     44         link = os.path.abspath(support.TESTFN)
     45         os.symlink(real, link)
     46         try:
     47             self.assertEqual(get(real), get(link, env=env))
     48         finally:
     49             os.remove(link)
     50 
     51     def test_platform(self):
     52         for aliased in (False, True):
     53             for terse in (False, True):
     54                 res = platform.platform(aliased, terse)
     55 
     56     def test_system(self):
     57         res = platform.system()
     58 
     59     def test_node(self):
     60         res = platform.node()
     61 
     62     def test_release(self):
     63         res = platform.release()
     64 
     65     def test_version(self):
     66         res = platform.version()
     67 
     68     def test_machine(self):
     69         res = platform.machine()
     70 
     71     def test_processor(self):
     72         res = platform.processor()
     73 
     74     def setUp(self):
     75         self.save_version = sys.version
     76         self.save_git = sys._git
     77         self.save_platform = sys.platform
     78 
     79     def tearDown(self):
     80         sys.version = self.save_version
     81         sys._git = self.save_git
     82         sys.platform = self.save_platform
     83 
     84     def test_sys_version(self):
     85         # Old test.
     86         for input, output in (
     87             ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
     88              ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
     89             ('IronPython 1.0.60816 on .NET 2.0.50727.42',
     90              ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')),
     91             ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42',
     92              ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')),
     93             ('2.4.3 (truncation, date, t) \n[GCC]',
     94              ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')),
     95             ('2.4.3 (truncation, date, ) \n[GCC]',
     96              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
     97             ('2.4.3 (truncation, date,) \n[GCC]',
     98              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
     99             ('2.4.3 (truncation, date) \n[GCC]',
    100              ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
    101             ('2.4.3 (truncation, d) \n[GCC]',
    102              ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')),
    103             ('2.4.3 (truncation, ) \n[GCC]',
    104              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
    105             ('2.4.3 (truncation,) \n[GCC]',
    106              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
    107             ('2.4.3 (truncation) \n[GCC]',
    108              ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
    109             ):
    110             # branch and revision are not "parsed", but fetched
    111             # from sys._git.  Ignore them
    112             (name, version, branch, revision, buildno, builddate, compiler) \
    113                    = platform._sys_version(input)
    114             self.assertEqual(
    115                 (name, version, '', '', buildno, builddate, compiler), output)
    116 
    117         # Tests for python_implementation(), python_version(), python_branch(),
    118         # python_revision(), python_build(), and python_compiler().
    119         sys_versions = {
    120             ("2.6.1 (r261:67515, Dec  6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]",
    121              ('CPython', 'tags/r261', '67515'), self.save_platform)
    122             :
    123                 ("CPython", "2.6.1", "tags/r261", "67515",
    124                  ('r261:67515', 'Dec  6 2008 15:26:00'),
    125                  'GCC 4.0.1 (Apple Computer, Inc. build 5370)'),
    126 
    127             ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli")
    128             :
    129                 ("IronPython", "2.0.0", "", "", ("", ""),
    130                  ".NET 2.0.50727.3053"),
    131 
    132             ("2.6.1 (IronPython 2.6.1 (2.6.10920.0) on .NET 2.0.50727.1433)", None, "cli")
    133             :
    134                 ("IronPython", "2.6.1", "", "", ("", ""),
    135                  ".NET 2.0.50727.1433"),
    136 
    137             ("2.7.4 (IronPython 2.7.4 (2.7.0.40) on Mono 4.0.30319.1 (32-bit))", None, "cli")
    138             :
    139                 ("IronPython", "2.7.4", "", "", ("", ""),
    140                  "Mono 4.0.30319.1 (32-bit)"),
    141 
    142             ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]",
    143             ('Jython', 'trunk', '6107'), "java1.5.0_16")
    144             :
    145                 ("Jython", "2.5.0", "trunk", "6107",
    146                  ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"),
    147 
    148             ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]",
    149              ('PyPy', 'trunk', '63378'), self.save_platform)
    150             :
    151                 ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'),
    152                  "")
    153             }
    154         for (version_tag, scm, sys_platform), info in \
    155                 sys_versions.items():
    156             sys.version = version_tag
    157             if scm is None:
    158                 if hasattr(sys, "_git"):
    159                     del sys._git
    160             else:
    161                 sys._git = scm
    162             if sys_platform is not None:
    163                 sys.platform = sys_platform
    164             self.assertEqual(platform.python_implementation(), info[0])
    165             self.assertEqual(platform.python_version(), info[1])
    166             self.assertEqual(platform.python_branch(), info[2])
    167             self.assertEqual(platform.python_revision(), info[3])
    168             self.assertEqual(platform.python_build(), info[4])
    169             self.assertEqual(platform.python_compiler(), info[5])
    170 
    171     def test_system_alias(self):
    172         res = platform.system_alias(
    173             platform.system(),
    174             platform.release(),
    175             platform.version(),
    176         )
    177 
    178     def test_uname(self):
    179         res = platform.uname()
    180         self.assertTrue(any(res))
    181         self.assertEqual(res[0], res.system)
    182         self.assertEqual(res[1], res.node)
    183         self.assertEqual(res[2], res.release)
    184         self.assertEqual(res[3], res.version)
    185         self.assertEqual(res[4], res.machine)
    186         self.assertEqual(res[5], res.processor)
    187 
    188     @unittest.skipUnless(sys.platform.startswith('win'), "windows only test")
    189     def test_uname_win32_ARCHITEW6432(self):
    190         # Issue 7860: make sure we get architecture from the correct variable
    191         # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be
    192         # using it, per
    193         # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx
    194         try:
    195             with support.EnvironmentVarGuard() as environ:
    196                 if 'PROCESSOR_ARCHITEW6432' in environ:
    197                     del environ['PROCESSOR_ARCHITEW6432']
    198                 environ['PROCESSOR_ARCHITECTURE'] = 'foo'
    199                 platform._uname_cache = None
    200                 system, node, release, version, machine, processor = platform.uname()
    201                 self.assertEqual(machine, 'foo')
    202                 environ['PROCESSOR_ARCHITEW6432'] = 'bar'
    203                 platform._uname_cache = None
    204                 system, node, release, version, machine, processor = platform.uname()
    205                 self.assertEqual(machine, 'bar')
    206         finally:
    207             platform._uname_cache = None
    208 
    209     def test_java_ver(self):
    210         res = platform.java_ver()
    211         if sys.platform == 'java':
    212             self.assertTrue(all(res))
    213 
    214     def test_win32_ver(self):
    215         res = platform.win32_ver()
    216 
    217     def test_mac_ver(self):
    218         res = platform.mac_ver()
    219 
    220         if platform.uname().system == 'Darwin':
    221             # We're on a MacOSX system, check that
    222             # the right version information is returned
    223             fd = os.popen('sw_vers', 'r')
    224             real_ver = None
    225             for ln in fd:
    226                 if ln.startswith('ProductVersion:'):
    227                     real_ver = ln.strip().split()[-1]
    228                     break
    229             fd.close()
    230             self.assertFalse(real_ver is None)
    231             result_list = res[0].split('.')
    232             expect_list = real_ver.split('.')
    233             len_diff = len(result_list) - len(expect_list)
    234             # On Snow Leopard, sw_vers reports 10.6.0 as 10.6
    235             if len_diff > 0:
    236                 expect_list.extend(['0'] * len_diff)
    237             self.assertEqual(result_list, expect_list)
    238 
    239             # res[1] claims to contain
    240             # (version, dev_stage, non_release_version)
    241             # That information is no longer available
    242             self.assertEqual(res[1], ('', '', ''))
    243 
    244             if sys.byteorder == 'little':
    245                 self.assertIn(res[2], ('i386', 'x86_64'))
    246             else:
    247                 self.assertEqual(res[2], 'PowerPC')
    248 
    249 
    250     @unittest.skipUnless(sys.platform == 'darwin', "OSX only test")
    251     def test_mac_ver_with_fork(self):
    252         # Issue7895: platform.mac_ver() crashes when using fork without exec
    253         #
    254         # This test checks that the fix for that issue works.
    255         #
    256         pid = os.fork()
    257         if pid == 0:
    258             # child
    259             info = platform.mac_ver()
    260             os._exit(0)
    261 
    262         else:
    263             # parent
    264             cpid, sts = os.waitpid(pid, 0)
    265             self.assertEqual(cpid, pid)
    266             self.assertEqual(sts, 0)
    267 
    268     def test_dist(self):
    269         with warnings.catch_warnings():
    270             warnings.filterwarnings(
    271                 'ignore',
    272                 r'dist\(\) and linux_distribution\(\) '
    273                 'functions are deprecated .*',
    274                 DeprecationWarning,
    275             )
    276             res = platform.dist()
    277 
    278     def test_libc_ver(self):
    279         if os.path.isdir(sys.executable) and \
    280            os.path.exists(sys.executable+'.exe'):
    281             # Cygwin horror
    282             executable = sys.executable + '.exe'
    283         else:
    284             executable = sys.executable
    285         res = platform.libc_ver(executable)
    286 
    287         self.addCleanup(support.unlink, support.TESTFN)
    288         with open(support.TESTFN, 'wb') as f:
    289             f.write(b'x'*(16384-10))
    290             f.write(b'GLIBC_1.23.4\0GLIBC_1.9\0GLIBC_1.21\0')
    291         self.assertEqual(platform.libc_ver(support.TESTFN),
    292                          ('glibc', '1.23.4'))
    293 
    294     @support.cpython_only
    295     def test__comparable_version(self):
    296         from platform import _comparable_version as V
    297         self.assertEqual(V('1.2.3'), V('1.2.3'))
    298         self.assertLess(V('1.2.3'), V('1.2.10'))
    299         self.assertEqual(V('1.2.3.4'), V('1_2-3+4'))
    300         self.assertLess(V('1.2spam'), V('1.2dev'))
    301         self.assertLess(V('1.2dev'), V('1.2alpha'))
    302         self.assertLess(V('1.2dev'), V('1.2a'))
    303         self.assertLess(V('1.2alpha'), V('1.2beta'))
    304         self.assertLess(V('1.2a'), V('1.2b'))
    305         self.assertLess(V('1.2beta'), V('1.2c'))
    306         self.assertLess(V('1.2b'), V('1.2c'))
    307         self.assertLess(V('1.2c'), V('1.2RC'))
    308         self.assertLess(V('1.2c'), V('1.2rc'))
    309         self.assertLess(V('1.2RC'), V('1.2.0'))
    310         self.assertLess(V('1.2rc'), V('1.2.0'))
    311         self.assertLess(V('1.2.0'), V('1.2pl'))
    312         self.assertLess(V('1.2.0'), V('1.2p'))
    313 
    314         self.assertLess(V('1.5.1'), V('1.5.2b2'))
    315         self.assertLess(V('3.10a'), V('161'))
    316         self.assertEqual(V('8.02'), V('8.02'))
    317         self.assertLess(V('3.4j'), V('1996.07.12'))
    318         self.assertLess(V('3.1.1.6'), V('3.2.pl0'))
    319         self.assertLess(V('2g6'), V('11g'))
    320         self.assertLess(V('0.9'), V('2.2'))
    321         self.assertLess(V('1.2'), V('1.2.1'))
    322         self.assertLess(V('1.1'), V('1.2.2'))
    323         self.assertLess(V('1.1'), V('1.2'))
    324         self.assertLess(V('1.2.1'), V('1.2.2'))
    325         self.assertLess(V('1.2'), V('1.2.2'))
    326         self.assertLess(V('0.4'), V('0.4.0'))
    327         self.assertLess(V('1.13++'), V('5.5.kw'))
    328         self.assertLess(V('0.960923'), V('2.2beta29'))
    329 
    330     def test_parse_release_file(self):
    331 
    332         for input, output in (
    333             # Examples of release file contents:
    334             ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64')),
    335             ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64')),
    336             ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586')),
    337             ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux')),
    338             ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche')),
    339             ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike')),
    340             ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant')),
    341             ('CentOS release 4', ('CentOS', '4', None)),
    342             ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia')),
    343             ('', ('', '', '')), # If there's nothing there.
    344             ):
    345             self.assertEqual(platform._parse_release_file(input), output)
    346 
    347     def test_popen(self):
    348         mswindows = (sys.platform == "win32")
    349 
    350         if mswindows:
    351             command = '"{}" -c "print(\'Hello\')"'.format(sys.executable)
    352         else:
    353             command = "'{}' -c 'print(\"Hello\")'".format(sys.executable)
    354         with warnings.catch_warnings():
    355             warnings.simplefilter("ignore", DeprecationWarning)
    356             with platform.popen(command) as stdout:
    357                 hello = stdout.read().strip()
    358                 stdout.close()
    359                 self.assertEqual(hello, "Hello")
    360 
    361         data = 'plop'
    362         if mswindows:
    363             command = '"{}" -c "import sys; data=sys.stdin.read(); exit(len(data))"'
    364         else:
    365             command = "'{}' -c 'import sys; data=sys.stdin.read(); exit(len(data))'"
    366         command = command.format(sys.executable)
    367         with warnings.catch_warnings():
    368             warnings.simplefilter("ignore", DeprecationWarning)
    369             with platform.popen(command, 'w') as stdin:
    370                 stdout = stdin.write(data)
    371                 ret = stdin.close()
    372                 self.assertIsNotNone(ret)
    373                 if os.name == 'nt':
    374                     returncode = ret
    375                 else:
    376                     returncode = ret >> 8
    377                 self.assertEqual(returncode, len(data))
    378 
    379     def test_linux_distribution_encoding(self):
    380         # Issue #17429
    381         with tempfile.TemporaryDirectory() as tempdir:
    382             filename = os.path.join(tempdir, 'fedora-release')
    383             with open(filename, 'w', encoding='utf-8') as f:
    384                 f.write('Fedora release 19 (Schr\xf6dinger\u2019s Cat)\n')
    385 
    386             with mock.patch('platform._UNIXCONFDIR', tempdir):
    387                 with warnings.catch_warnings():
    388                     warnings.filterwarnings(
    389                         'ignore',
    390                         r'dist\(\) and linux_distribution\(\) '
    391                         'functions are deprecated .*',
    392                         DeprecationWarning,
    393                     )
    394                     distname, version, distid = platform.linux_distribution()
    395 
    396                 self.assertEqual(distname, 'Fedora')
    397             self.assertEqual(version, '19')
    398             self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat')
    399 
    400 
    401 class DeprecationTest(unittest.TestCase):
    402 
    403     def test_dist_deprecation(self):
    404         with self.assertWarns(DeprecationWarning) as cm:
    405             platform.dist()
    406         self.assertEqual(str(cm.warning),
    407                          'dist() and linux_distribution() functions are '
    408                          'deprecated in Python 3.5')
    409 
    410     def test_linux_distribution_deprecation(self):
    411         with self.assertWarns(DeprecationWarning) as cm:
    412             platform.linux_distribution()
    413         self.assertEqual(str(cm.warning),
    414                          'dist() and linux_distribution() functions are '
    415                          'deprecated in Python 3.5')
    416 
    417 if __name__ == '__main__':
    418     unittest.main()
    419