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