Home | History | Annotate | Download | only in test
      1 "Test posix functions"
      2 
      3 from test import test_support
      4 
      5 # Skip these tests if there is no posix module.
      6 posix = test_support.import_module('posix')
      7 
      8 import errno
      9 import sys
     10 import time
     11 import os
     12 import platform
     13 import pwd
     14 import shutil
     15 import stat
     16 import sys
     17 import tempfile
     18 import unittest
     19 import warnings
     20 
     21 _DUMMY_SYMLINK = os.path.join(tempfile.gettempdir(),
     22                               test_support.TESTFN + '-dummy-symlink')
     23 
     24 warnings.filterwarnings('ignore', '.* potential security risk .*',
     25                         RuntimeWarning)
     26 
     27 class PosixTester(unittest.TestCase):
     28 
     29     def setUp(self):
     30         # create empty file
     31         fp = open(test_support.TESTFN, 'w+')
     32         fp.close()
     33         self.teardown_files = [ test_support.TESTFN ]
     34 
     35     def tearDown(self):
     36         for teardown_file in self.teardown_files:
     37             os.unlink(teardown_file)
     38 
     39     def testNoArgFunctions(self):
     40         # test posix functions which take no arguments and have
     41         # no side-effects which we need to cleanup (e.g., fork, wait, abort)
     42         NO_ARG_FUNCTIONS = [ "ctermid", "getcwd", "getcwdu", "uname",
     43                              "times", "getloadavg", "tmpnam",
     44                              "getegid", "geteuid", "getgid", "getgroups",
     45                              "getpid", "getpgrp", "getppid", "getuid",
     46                            ]
     47 
     48         with warnings.catch_warnings():
     49             warnings.filterwarnings("ignore", "", DeprecationWarning)
     50             for name in NO_ARG_FUNCTIONS:
     51                 posix_func = getattr(posix, name, None)
     52                 if posix_func is not None:
     53                     posix_func()
     54                     self.assertRaises(TypeError, posix_func, 1)
     55 
     56     @unittest.skipUnless(hasattr(posix, 'getresuid'),
     57                          'test needs posix.getresuid()')
     58     def test_getresuid(self):
     59         user_ids = posix.getresuid()
     60         self.assertEqual(len(user_ids), 3)
     61         for val in user_ids:
     62             self.assertGreaterEqual(val, 0)
     63 
     64     @unittest.skipUnless(hasattr(posix, 'getresgid'),
     65                          'test needs posix.getresgid()')
     66     def test_getresgid(self):
     67         group_ids = posix.getresgid()
     68         self.assertEqual(len(group_ids), 3)
     69         for val in group_ids:
     70             self.assertGreaterEqual(val, 0)
     71 
     72     @unittest.skipUnless(hasattr(posix, 'setresuid'),
     73                          'test needs posix.setresuid()')
     74     def test_setresuid(self):
     75         current_user_ids = posix.getresuid()
     76         self.assertIsNone(posix.setresuid(*current_user_ids))
     77         # -1 means don't change that value.
     78         self.assertIsNone(posix.setresuid(-1, -1, -1))
     79 
     80     @unittest.skipUnless(hasattr(posix, 'setresuid'),
     81                          'test needs posix.setresuid()')
     82     def test_setresuid_exception(self):
     83         # Don't do this test if someone is silly enough to run us as root.
     84         current_user_ids = posix.getresuid()
     85         if 0 not in current_user_ids:
     86             new_user_ids = (current_user_ids[0]+1, -1, -1)
     87             self.assertRaises(OSError, posix.setresuid, *new_user_ids)
     88 
     89     @unittest.skipUnless(hasattr(posix, 'setresgid'),
     90                          'test needs posix.setresgid()')
     91     def test_setresgid(self):
     92         current_group_ids = posix.getresgid()
     93         self.assertIsNone(posix.setresgid(*current_group_ids))
     94         # -1 means don't change that value.
     95         self.assertIsNone(posix.setresgid(-1, -1, -1))
     96 
     97     @unittest.skipUnless(hasattr(posix, 'setresgid'),
     98                          'test needs posix.setresgid()')
     99     def test_setresgid_exception(self):
    100         # Don't do this test if someone is silly enough to run us as root.
    101         current_group_ids = posix.getresgid()
    102         if 0 not in current_group_ids:
    103             new_group_ids = (current_group_ids[0]+1, -1, -1)
    104             self.assertRaises(OSError, posix.setresgid, *new_group_ids)
    105 
    106     @unittest.skipUnless(hasattr(posix, 'initgroups'),
    107                          "test needs os.initgroups()")
    108     def test_initgroups(self):
    109         # It takes a string and an integer; check that it raises a TypeError
    110         # for other argument lists.
    111         self.assertRaises(TypeError, posix.initgroups)
    112         self.assertRaises(TypeError, posix.initgroups, None)
    113         self.assertRaises(TypeError, posix.initgroups, 3, "foo")
    114         self.assertRaises(TypeError, posix.initgroups, "foo", 3, object())
    115 
    116         # If a non-privileged user invokes it, it should fail with OSError
    117         # EPERM.
    118         if os.getuid() != 0:
    119             try:
    120                 name = pwd.getpwuid(posix.getuid()).pw_name
    121             except KeyError:
    122                 # the current UID may not have a pwd entry
    123                 raise unittest.SkipTest("need a pwd entry")
    124             try:
    125                 posix.initgroups(name, 13)
    126             except OSError as e:
    127                 self.assertEqual(e.errno, errno.EPERM)
    128             else:
    129                 self.fail("Expected OSError to be raised by initgroups")
    130 
    131     @unittest.skipUnless(hasattr(posix, 'statvfs'),
    132                          'test needs posix.statvfs()')
    133     def test_statvfs(self):
    134         self.assertTrue(posix.statvfs(os.curdir))
    135 
    136     @unittest.skipUnless(hasattr(posix, 'fstatvfs'),
    137                          'test needs posix.fstatvfs()')
    138     def test_fstatvfs(self):
    139         fp = open(test_support.TESTFN)
    140         try:
    141             self.assertTrue(posix.fstatvfs(fp.fileno()))
    142         finally:
    143             fp.close()
    144 
    145     @unittest.skipUnless(hasattr(posix, 'ftruncate'),
    146                          'test needs posix.ftruncate()')
    147     def test_ftruncate(self):
    148         fp = open(test_support.TESTFN, 'w+')
    149         try:
    150             # we need to have some data to truncate
    151             fp.write('test')
    152             fp.flush()
    153             posix.ftruncate(fp.fileno(), 0)
    154         finally:
    155             fp.close()
    156 
    157     @unittest.skipUnless(hasattr(posix, 'dup'),
    158                          'test needs posix.dup()')
    159     def test_dup(self):
    160         fp = open(test_support.TESTFN)
    161         try:
    162             fd = posix.dup(fp.fileno())
    163             self.assertIsInstance(fd, int)
    164             os.close(fd)
    165         finally:
    166             fp.close()
    167 
    168     @unittest.skipUnless(hasattr(posix, 'confstr'),
    169                          'test needs posix.confstr()')
    170     def test_confstr(self):
    171         self.assertRaises(ValueError, posix.confstr, "CS_garbage")
    172         self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)
    173 
    174     @unittest.skipUnless(hasattr(posix, 'dup2'),
    175                          'test needs posix.dup2()')
    176     def test_dup2(self):
    177         fp1 = open(test_support.TESTFN)
    178         fp2 = open(test_support.TESTFN)
    179         try:
    180             posix.dup2(fp1.fileno(), fp2.fileno())
    181         finally:
    182             fp1.close()
    183             fp2.close()
    184 
    185     def fdopen_helper(self, *args):
    186         fd = os.open(test_support.TESTFN, os.O_RDONLY)
    187         fp2 = posix.fdopen(fd, *args)
    188         fp2.close()
    189 
    190     @unittest.skipUnless(hasattr(posix, 'fdopen'),
    191                          'test needs posix.fdopen()')
    192     def test_fdopen(self):
    193         self.fdopen_helper()
    194         self.fdopen_helper('r')
    195         self.fdopen_helper('r', 100)
    196 
    197     @unittest.skipUnless(hasattr(posix, 'fdopen'),
    198                          'test needs posix.fdopen()')
    199     def test_fdopen_directory(self):
    200         try:
    201             fd = os.open('.', os.O_RDONLY)
    202         except OSError as e:
    203             self.assertEqual(e.errno, errno.EACCES)
    204             self.skipTest("system cannot open directories")
    205         with self.assertRaises(IOError) as cm:
    206             os.fdopen(fd, 'r')
    207         self.assertEqual(cm.exception.errno, errno.EISDIR)
    208 
    209     @unittest.skipUnless(hasattr(posix, 'fdopen') and
    210                          not sys.platform.startswith("sunos"),
    211                          'test needs posix.fdopen()')
    212     def test_fdopen_keeps_fd_open_on_errors(self):
    213         fd = os.open(test_support.TESTFN, os.O_RDONLY)
    214         self.assertRaises(OSError, posix.fdopen, fd, 'w')
    215         os.close(fd) # fd should not be closed.
    216 
    217     @unittest.skipUnless(hasattr(posix, 'O_EXLOCK'),
    218                          'test needs posix.O_EXLOCK')
    219     def test_osexlock(self):
    220         fd = os.open(test_support.TESTFN,
    221                      os.O_WRONLY|os.O_EXLOCK|os.O_CREAT)
    222         self.assertRaises(OSError, os.open, test_support.TESTFN,
    223                           os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)
    224         os.close(fd)
    225 
    226         if hasattr(posix, "O_SHLOCK"):
    227             fd = os.open(test_support.TESTFN,
    228                          os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
    229             self.assertRaises(OSError, os.open, test_support.TESTFN,
    230                               os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)
    231             os.close(fd)
    232 
    233     @unittest.skipUnless(hasattr(posix, 'O_SHLOCK'),
    234                          'test needs posix.O_SHLOCK')
    235     def test_osshlock(self):
    236         fd1 = os.open(test_support.TESTFN,
    237                       os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
    238         fd2 = os.open(test_support.TESTFN,
    239                       os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
    240         os.close(fd2)
    241         os.close(fd1)
    242 
    243         if hasattr(posix, "O_EXLOCK"):
    244             fd = os.open(test_support.TESTFN,
    245                          os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
    246             self.assertRaises(OSError, os.open, test_support.TESTFN,
    247                               os.O_RDONLY|os.O_EXLOCK|os.O_NONBLOCK)
    248             os.close(fd)
    249 
    250     @unittest.skipUnless(hasattr(posix, 'fstat'),
    251                          'test needs posix.fstat()')
    252     def test_fstat(self):
    253         fp = open(test_support.TESTFN)
    254         try:
    255             self.assertTrue(posix.fstat(fp.fileno()))
    256         finally:
    257             fp.close()
    258 
    259     @unittest.skipUnless(hasattr(posix, 'stat'),
    260                          'test needs posix.stat()')
    261     def test_stat(self):
    262         self.assertTrue(posix.stat(test_support.TESTFN))
    263 
    264     @unittest.skipUnless(hasattr(posix, 'stat'), 'test needs posix.stat()')
    265     @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()')
    266     def test_makedev(self):
    267         st = posix.stat(test_support.TESTFN)
    268         dev = st.st_dev
    269         self.assertIsInstance(dev, (int, long))
    270         self.assertGreaterEqual(dev, 0)
    271 
    272         major = posix.major(dev)
    273         self.assertIsInstance(major, (int, long))
    274         self.assertGreaterEqual(major, 0)
    275         self.assertEqual(posix.major(int(dev)), major)
    276         self.assertEqual(posix.major(long(dev)), major)
    277         self.assertRaises(TypeError, posix.major, float(dev))
    278         self.assertRaises(TypeError, posix.major)
    279         self.assertRaises((ValueError, OverflowError), posix.major, -1)
    280 
    281         minor = posix.minor(dev)
    282         self.assertIsInstance(minor, (int, long))
    283         self.assertGreaterEqual(minor, 0)
    284         self.assertEqual(posix.minor(int(dev)), minor)
    285         self.assertEqual(posix.minor(long(dev)), minor)
    286         self.assertRaises(TypeError, posix.minor, float(dev))
    287         self.assertRaises(TypeError, posix.minor)
    288         self.assertRaises((ValueError, OverflowError), posix.minor, -1)
    289 
    290         self.assertEqual(posix.makedev(major, minor), dev)
    291         self.assertEqual(posix.makedev(int(major), int(minor)), dev)
    292         self.assertEqual(posix.makedev(long(major), long(minor)), dev)
    293         self.assertRaises(TypeError, posix.makedev, float(major), minor)
    294         self.assertRaises(TypeError, posix.makedev, major, float(minor))
    295         self.assertRaises(TypeError, posix.makedev, major)
    296         self.assertRaises(TypeError, posix.makedev)
    297 
    298     def _test_all_chown_common(self, chown_func, first_param, stat_func):
    299         """Common code for chown, fchown and lchown tests."""
    300         def check_stat(uid, gid):
    301             if stat_func is not None:
    302                 stat = stat_func(first_param)
    303                 self.assertEqual(stat.st_uid, uid)
    304                 self.assertEqual(stat.st_gid, gid)
    305         uid = os.getuid()
    306         gid = os.getgid()
    307         # test a successful chown call
    308         chown_func(first_param, uid, gid)
    309         check_stat(uid, gid)
    310         chown_func(first_param, -1, gid)
    311         check_stat(uid, gid)
    312         chown_func(first_param, uid, -1)
    313         check_stat(uid, gid)
    314 
    315         if uid == 0:
    316             # Try an amusingly large uid/gid to make sure we handle
    317             # large unsigned values.  (chown lets you use any
    318             # uid/gid you like, even if they aren't defined.)
    319             #
    320             # This problem keeps coming up:
    321             #   http://bugs.python.org/issue1747858
    322             #   http://bugs.python.org/issue4591
    323             #   http://bugs.python.org/issue15301
    324             # Hopefully the fix in 4591 fixes it for good!
    325             #
    326             # This part of the test only runs when run as root.
    327             # Only scary people run their tests as root.
    328 
    329             big_value = 2**31
    330             chown_func(first_param, big_value, big_value)
    331             check_stat(big_value, big_value)
    332             chown_func(first_param, -1, -1)
    333             check_stat(big_value, big_value)
    334             chown_func(first_param, uid, gid)
    335             check_stat(uid, gid)
    336         elif platform.system() in ('HP-UX', 'SunOS'):
    337             # HP-UX and Solaris can allow a non-root user to chown() to root
    338             # (issue #5113)
    339             raise unittest.SkipTest("Skipping because of non-standard chown() "
    340                                     "behavior")
    341         else:
    342             # non-root cannot chown to root, raises OSError
    343             self.assertRaises(OSError, chown_func, first_param, 0, 0)
    344             check_stat(uid, gid)
    345             self.assertRaises(OSError, chown_func, first_param, 0, -1)
    346             check_stat(uid, gid)
    347             if 0 not in os.getgroups():
    348                 self.assertRaises(OSError, chown_func, first_param, -1, 0)
    349                 check_stat(uid, gid)
    350         # test illegal types
    351         for t in str, float:
    352             self.assertRaises(TypeError, chown_func, first_param, t(uid), gid)
    353             check_stat(uid, gid)
    354             self.assertRaises(TypeError, chown_func, first_param, uid, t(gid))
    355             check_stat(uid, gid)
    356 
    357     @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()")
    358     def test_chown(self):
    359         # raise an OSError if the file does not exist
    360         os.unlink(test_support.TESTFN)
    361         self.assertRaises(OSError, posix.chown, test_support.TESTFN, -1, -1)
    362 
    363         # re-create the file
    364         open(test_support.TESTFN, 'w').close()
    365         self._test_all_chown_common(posix.chown, test_support.TESTFN,
    366                                     getattr(posix, 'stat', None))
    367 
    368     @unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()")
    369     def test_fchown(self):
    370         os.unlink(test_support.TESTFN)
    371 
    372         # re-create the file
    373         test_file = open(test_support.TESTFN, 'w')
    374         try:
    375             fd = test_file.fileno()
    376             self._test_all_chown_common(posix.fchown, fd,
    377                                         getattr(posix, 'fstat', None))
    378         finally:
    379             test_file.close()
    380 
    381     @unittest.skipUnless(hasattr(posix, 'lchown'), "test needs os.lchown()")
    382     def test_lchown(self):
    383         os.unlink(test_support.TESTFN)
    384         # create a symlink
    385         os.symlink(_DUMMY_SYMLINK, test_support.TESTFN)
    386         self._test_all_chown_common(posix.lchown, test_support.TESTFN,
    387                                     getattr(posix, 'lstat', None))
    388 
    389     @unittest.skipUnless(hasattr(posix, 'chdir'), 'test needs posix.chdir()')
    390     def test_chdir(self):
    391         posix.chdir(os.curdir)
    392         self.assertRaises(OSError, posix.chdir, test_support.TESTFN)
    393 
    394     @unittest.skipUnless(hasattr(posix, 'lsdir'), 'test needs posix.lsdir()')
    395     def test_lsdir(self):
    396         self.assertIn(test_support.TESTFN, posix.lsdir(os.curdir))
    397 
    398     @unittest.skipUnless(hasattr(posix, 'access'), 'test needs posix.access()')
    399     def test_access(self):
    400         self.assertTrue(posix.access(test_support.TESTFN, os.R_OK))
    401 
    402     @unittest.skipUnless(hasattr(posix, 'umask'), 'test needs posix.umask()')
    403     def test_umask(self):
    404         old_mask = posix.umask(0)
    405         self.assertIsInstance(old_mask, int)
    406         posix.umask(old_mask)
    407 
    408     @unittest.skipUnless(hasattr(posix, 'strerror'),
    409                          'test needs posix.strerror()')
    410     def test_strerror(self):
    411         self.assertTrue(posix.strerror(0))
    412 
    413     @unittest.skipUnless(hasattr(posix, 'pipe'), 'test needs posix.pipe()')
    414     def test_pipe(self):
    415         reader, writer = posix.pipe()
    416         os.close(reader)
    417         os.close(writer)
    418 
    419     @unittest.skipUnless(hasattr(posix, 'tempnam'),
    420                          'test needs posix.tempnam()')
    421     def test_tempnam(self):
    422         with warnings.catch_warnings():
    423             warnings.filterwarnings("ignore", "tempnam", DeprecationWarning)
    424             self.assertTrue(posix.tempnam())
    425             self.assertTrue(posix.tempnam(os.curdir))
    426             self.assertTrue(posix.tempnam(os.curdir, 'blah'))
    427 
    428     @unittest.skipUnless(hasattr(posix, 'tmpfile'),
    429                          'test needs posix.tmpfile()')
    430     def test_tmpfile(self):
    431         with warnings.catch_warnings():
    432             warnings.filterwarnings("ignore", "tmpfile", DeprecationWarning)
    433             fp = posix.tmpfile()
    434             fp.close()
    435 
    436     @unittest.skipUnless(hasattr(posix, 'utime'), 'test needs posix.utime()')
    437     def test_utime(self):
    438         now = time.time()
    439         posix.utime(test_support.TESTFN, None)
    440         self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (None, None))
    441         self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (now, None))
    442         self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (None, now))
    443         posix.utime(test_support.TESTFN, (int(now), int(now)))
    444         posix.utime(test_support.TESTFN, (now, now))
    445 
    446     def _test_chflags_regular_file(self, chflags_func, target_file):
    447         st = os.stat(target_file)
    448         self.assertTrue(hasattr(st, 'st_flags'))
    449 
    450         # ZFS returns EOPNOTSUPP when attempting to set flag UF_IMMUTABLE.
    451         try:
    452             chflags_func(target_file, st.st_flags | stat.UF_IMMUTABLE)
    453         except OSError as err:
    454             if err.errno != errno.EOPNOTSUPP:
    455                 raise
    456             msg = 'chflag UF_IMMUTABLE not supported by underlying fs'
    457             self.skipTest(msg)
    458 
    459         try:
    460             new_st = os.stat(target_file)
    461             self.assertEqual(st.st_flags | stat.UF_IMMUTABLE, new_st.st_flags)
    462             try:
    463                 fd = open(target_file, 'w+')
    464             except IOError as e:
    465                 self.assertEqual(e.errno, errno.EPERM)
    466         finally:
    467             posix.chflags(target_file, st.st_flags)
    468 
    469     @unittest.skipUnless(hasattr(posix, 'chflags'), 'test needs os.chflags()')
    470     def test_chflags(self):
    471         self._test_chflags_regular_file(posix.chflags, test_support.TESTFN)
    472 
    473     @unittest.skipUnless(hasattr(posix, 'lchflags'), 'test needs os.lchflags()')
    474     def test_lchflags_regular_file(self):
    475         self._test_chflags_regular_file(posix.lchflags, test_support.TESTFN)
    476 
    477     @unittest.skipUnless(hasattr(posix, 'lchflags'), 'test needs os.lchflags()')
    478     def test_lchflags_symlink(self):
    479         testfn_st = os.stat(test_support.TESTFN)
    480 
    481         self.assertTrue(hasattr(testfn_st, 'st_flags'))
    482 
    483         os.symlink(test_support.TESTFN, _DUMMY_SYMLINK)
    484         self.teardown_files.append(_DUMMY_SYMLINK)
    485         dummy_symlink_st = os.lstat(_DUMMY_SYMLINK)
    486 
    487         # ZFS returns EOPNOTSUPP when attempting to set flag UF_IMMUTABLE.
    488         try:
    489             posix.lchflags(_DUMMY_SYMLINK,
    490                            dummy_symlink_st.st_flags | stat.UF_IMMUTABLE)
    491         except OSError as err:
    492             if err.errno != errno.EOPNOTSUPP:
    493                 raise
    494             msg = 'chflag UF_IMMUTABLE not supported by underlying fs'
    495             self.skipTest(msg)
    496 
    497         try:
    498             new_testfn_st = os.stat(test_support.TESTFN)
    499             new_dummy_symlink_st = os.lstat(_DUMMY_SYMLINK)
    500 
    501             self.assertEqual(testfn_st.st_flags, new_testfn_st.st_flags)
    502             self.assertEqual(dummy_symlink_st.st_flags | stat.UF_IMMUTABLE,
    503                              new_dummy_symlink_st.st_flags)
    504         finally:
    505             posix.lchflags(_DUMMY_SYMLINK, dummy_symlink_st.st_flags)
    506 
    507     @unittest.skipUnless(hasattr(posix, 'getcwd'),
    508                          'test needs posix.getcwd()')
    509     def test_getcwd_long_pathnames(self):
    510         dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef'
    511         curdir = os.getcwd()
    512         base_path = os.path.abspath(test_support.TESTFN) + '.getcwd'
    513 
    514         try:
    515             os.mkdir(base_path)
    516             os.chdir(base_path)
    517         except:
    518             self.skipTest("cannot create directory for testing")
    519 
    520         try:
    521             def _create_and_do_getcwd(dirname, current_path_length = 0):
    522                 try:
    523                     os.mkdir(dirname)
    524                 except:
    525                     self.skipTest("mkdir cannot create directory sufficiently "
    526                                   "deep for getcwd test")
    527 
    528                 os.chdir(dirname)
    529                 try:
    530                     os.getcwd()
    531                     if current_path_length < 4099:
    532                         _create_and_do_getcwd(dirname, current_path_length + len(dirname) + 1)
    533                 except OSError as e:
    534                     expected_errno = errno.ENAMETOOLONG
    535                     # The following platforms have quirky getcwd()
    536                     # behaviour -- see issue 9185 and 15765 for
    537                     # more information.
    538                     quirky_platform = (
    539                         'sunos' in sys.platform or
    540                         'netbsd' in sys.platform or
    541                         'openbsd' in sys.platform
    542                     )
    543                     if quirky_platform:
    544                         expected_errno = errno.ERANGE
    545                     self.assertEqual(e.errno, expected_errno)
    546                 finally:
    547                     os.chdir('..')
    548                     os.rmdir(dirname)
    549 
    550             _create_and_do_getcwd(dirname)
    551 
    552         finally:
    553             os.chdir(curdir)
    554             shutil.rmtree(base_path)
    555 
    556     @unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()")
    557     def test_getgroups(self):
    558         with os.popen('id -G 2>/dev/null') as idg:
    559             groups = idg.read().strip()
    560             ret = idg.close()
    561 
    562         if ret != None or not groups:
    563             raise unittest.SkipTest("need working 'id -G'")
    564 
    565         # Issues 16698: OS X ABIs prior to 10.6 have limits on getgroups()
    566         if sys.platform == 'darwin':
    567             import sysconfig
    568             dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.0'
    569             if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6):
    570                 raise unittest.SkipTest("getgroups(2) is broken prior to 10.6")
    571 
    572         # 'id -G' and 'os.getgroups()' should return the same
    573         # groups, ignoring order and duplicates.
    574         # #10822 - it is implementation defined whether posix.getgroups()
    575         # includes the effective gid so we include it anyway, since id -G does
    576         self.assertEqual(
    577                 set([int(x) for x in groups.split()]),
    578                 set(posix.getgroups() + [posix.getegid()]))
    579 
    580     @test_support.requires_unicode
    581     def test_path_with_null_unicode(self):
    582         fn = test_support.TESTFN_UNICODE
    583         try:
    584             fn.encode(test_support.TESTFN_ENCODING)
    585         except (UnicodeError, TypeError):
    586             self.skipTest("Requires unicode filenames support")
    587         fn_with_NUL = fn + u'\0'
    588         self.addCleanup(test_support.unlink, fn)
    589         test_support.unlink(fn)
    590         fd = None
    591         try:
    592             with self.assertRaises(TypeError):
    593                 fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises
    594         finally:
    595             if fd is not None:
    596                 os.close(fd)
    597         self.assertFalse(os.path.exists(fn))
    598         self.assertRaises(TypeError, os.mkdir, fn_with_NUL)
    599         self.assertFalse(os.path.exists(fn))
    600         open(fn, 'wb').close()
    601         self.assertRaises(TypeError, os.stat, fn_with_NUL)
    602 
    603     def test_path_with_null_byte(self):
    604         fn = test_support.TESTFN
    605         fn_with_NUL = fn + '\0'
    606         self.addCleanup(test_support.unlink, fn)
    607         test_support.unlink(fn)
    608         fd = None
    609         try:
    610             with self.assertRaises(TypeError):
    611                 fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises
    612         finally:
    613             if fd is not None:
    614                 os.close(fd)
    615         self.assertFalse(os.path.exists(fn))
    616         self.assertRaises(TypeError, os.mkdir, fn_with_NUL)
    617         self.assertFalse(os.path.exists(fn))
    618         open(fn, 'wb').close()
    619         self.assertRaises(TypeError, os.stat, fn_with_NUL)
    620 
    621 
    622 class PosixGroupsTester(unittest.TestCase):
    623 
    624     def setUp(self):
    625         if posix.getuid() != 0:
    626             raise unittest.SkipTest("not enough privileges")
    627         if not hasattr(posix, 'getgroups'):
    628             raise unittest.SkipTest("need posix.getgroups")
    629         if sys.platform == 'darwin':
    630             raise unittest.SkipTest("getgroups(2) is broken on OSX")
    631         self.saved_groups = posix.getgroups()
    632 
    633     def tearDown(self):
    634         if hasattr(posix, 'setgroups'):
    635             posix.setgroups(self.saved_groups)
    636         elif hasattr(posix, 'initgroups'):
    637             name = pwd.getpwuid(posix.getuid()).pw_name
    638             posix.initgroups(name, self.saved_groups[0])
    639 
    640     @unittest.skipUnless(hasattr(posix, 'initgroups'),
    641                          'test needs posix.initgroups()')
    642     def test_initgroups(self):
    643         # find missing group
    644 
    645         g = max(self.saved_groups or [0]) + 1
    646         name = pwd.getpwuid(posix.getuid()).pw_name
    647         posix.initgroups(name, g)
    648         self.assertIn(g, posix.getgroups())
    649 
    650     @unittest.skipUnless(hasattr(posix, 'setgroups'),
    651                          'test needs posix.setgroups()')
    652     def test_setgroups(self):
    653         for groups in [[0], range(16)]:
    654             posix.setgroups(groups)
    655             self.assertListEqual(groups, posix.getgroups())
    656 
    657 
    658 def test_main():
    659     test_support.run_unittest(PosixTester, PosixGroupsTester)
    660 
    661 if __name__ == '__main__':
    662     test_main()
    663