Home | History | Annotate | Download | only in test
      1 import sys
      2 import unittest
      3 from test import support
      4 
      5 pwd = support.import_module('pwd')
      6 
      7 def _getpwall():
      8     # Android does not have getpwall.
      9     if hasattr(pwd, 'getpwall'):
     10         return pwd.getpwall()
     11     elif hasattr(pwd, 'getpwuid'):
     12         return [pwd.getpwuid(0)]
     13     else:
     14         return []
     15 
     16 class PwdTest(unittest.TestCase):
     17 
     18     def test_values(self):
     19         entries = _getpwall()
     20 
     21         for e in entries:
     22             self.assertEqual(len(e), 7)
     23             self.assertEqual(e[0], e.pw_name)
     24             self.assertIsInstance(e.pw_name, str)
     25             self.assertEqual(e[1], e.pw_passwd)
     26             self.assertIsInstance(e.pw_passwd, str)
     27             self.assertEqual(e[2], e.pw_uid)
     28             self.assertIsInstance(e.pw_uid, int)
     29             self.assertEqual(e[3], e.pw_gid)
     30             self.assertIsInstance(e.pw_gid, int)
     31             self.assertEqual(e[4], e.pw_gecos)
     32             self.assertIsInstance(e.pw_gecos, str)
     33             self.assertEqual(e[5], e.pw_dir)
     34             self.assertIsInstance(e.pw_dir, str)
     35             self.assertEqual(e[6], e.pw_shell)
     36             self.assertIsInstance(e.pw_shell, str)
     37 
     38             # The following won't work, because of duplicate entries
     39             # for one uid
     40             #    self.assertEqual(pwd.getpwuid(e.pw_uid), e)
     41             # instead of this collect all entries for one uid
     42             # and check afterwards (done in test_values_extended)
     43 
     44     def test_values_extended(self):
     45         entries = _getpwall()
     46         entriesbyname = {}
     47         entriesbyuid = {}
     48 
     49         if len(entries) > 1000:  # Huge passwd file (NIS?) -- skip this test
     50             self.skipTest('passwd file is huge; extended test skipped')
     51 
     52         for e in entries:
     53             entriesbyname.setdefault(e.pw_name, []).append(e)
     54             entriesbyuid.setdefault(e.pw_uid, []).append(e)
     55 
     56         # check whether the entry returned by getpwuid()
     57         # for each uid is among those from getpwall() for this uid
     58         for e in entries:
     59             if not e[0] or e[0] == '+':
     60                 continue # skip NIS entries etc.
     61             self.assertIn(pwd.getpwnam(e.pw_name), entriesbyname[e.pw_name])
     62             self.assertIn(pwd.getpwuid(e.pw_uid), entriesbyuid[e.pw_uid])
     63 
     64     def test_errors(self):
     65         self.assertRaises(TypeError, pwd.getpwuid)
     66         self.assertRaises(TypeError, pwd.getpwuid, 3.14)
     67         self.assertRaises(TypeError, pwd.getpwnam)
     68         self.assertRaises(TypeError, pwd.getpwnam, 42)
     69         if hasattr(pwd, 'getpwall'):
     70             self.assertRaises(TypeError, pwd.getpwall, 42)
     71 
     72         # try to get some errors
     73         bynames = {}
     74         byuids = {}
     75         for (n, p, u, g, gecos, d, s) in _getpwall():
     76             bynames[n] = u
     77             byuids[u] = n
     78 
     79         allnames = list(bynames.keys())
     80         namei = 0
     81         fakename = allnames[namei]
     82         while fakename in bynames:
     83             chars = list(fakename)
     84             for i in range(len(chars)):
     85                 if chars[i] == 'z':
     86                     chars[i] = 'A'
     87                     break
     88                 elif chars[i] == 'Z':
     89                     continue
     90                 else:
     91                     chars[i] = chr(ord(chars[i]) + 1)
     92                     break
     93             else:
     94                 namei = namei + 1
     95                 try:
     96                     fakename = allnames[namei]
     97                 except IndexError:
     98                     # should never happen... if so, just forget it
     99                     break
    100             fakename = ''.join(chars)
    101 
    102         self.assertRaises(KeyError, pwd.getpwnam, fakename)
    103 
    104         # In some cases, byuids isn't a complete list of all users in the
    105         # system, so if we try to pick a value not in byuids (via a perturbing
    106         # loop, say), pwd.getpwuid() might still be able to find data for that
    107         # uid. Using sys.maxint may provoke the same problems, but hopefully
    108         # it will be a more repeatable failure.
    109         # Android accepts a very large span of uids including sys.maxsize and
    110         # -1; it raises KeyError with 1 or 2 for example.
    111         fakeuid = sys.maxsize
    112         self.assertNotIn(fakeuid, byuids)
    113         if not support.is_android:
    114             self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
    115 
    116         # -1 shouldn't be a valid uid because it has a special meaning in many
    117         # uid-related functions
    118         if not support.is_android:
    119             self.assertRaises(KeyError, pwd.getpwuid, -1)
    120         # should be out of uid_t range
    121         self.assertRaises(KeyError, pwd.getpwuid, 2**128)
    122         self.assertRaises(KeyError, pwd.getpwuid, -2**128)
    123 
    124 if __name__ == "__main__":
    125     unittest.main()
    126