1"""Test script for the grp module."""
2
3import unittest
4from test.support import import_helper
5
6
7grp = import_helper.import_module('grp')
8
9class GroupDatabaseTestCase(unittest.TestCase):
10
11    def check_value(self, value):
12        # check that a grp tuple has the entries and
13        # attributes promised by the docs
14        self.assertEqual(len(value), 4)
15        self.assertEqual(value[0], value.gr_name)
16        self.assertIsInstance(value.gr_name, str)
17        self.assertEqual(value[1], value.gr_passwd)
18        self.assertIsInstance(value.gr_passwd, str)
19        self.assertEqual(value[2], value.gr_gid)
20        self.assertIsInstance(value.gr_gid, int)
21        self.assertEqual(value[3], value.gr_mem)
22        self.assertIsInstance(value.gr_mem, list)
23
24    def test_values(self):
25        entries = grp.getgrall()
26
27        for e in entries:
28            self.check_value(e)
29
30    def test_values_extended(self):
31        entries = grp.getgrall()
32        if len(entries) > 1000:  # Huge group file (NIS?) -- skip the rest
33            self.skipTest('huge group file, extended test skipped')
34
35        for e in entries:
36            e2 = grp.getgrgid(e.gr_gid)
37            self.check_value(e2)
38            self.assertEqual(e2.gr_gid, e.gr_gid)
39            name = e.gr_name
40            if name.startswith('+') or name.startswith('-'):
41                # NIS-related entry
42                continue
43            e2 = grp.getgrnam(name)
44            self.check_value(e2)
45            # There are instances where getgrall() returns group names in
46            # lowercase while getgrgid() returns proper casing.
47            # Discovered on Ubuntu 5.04 (custom).
48            self.assertEqual(e2.gr_name.lower(), name.lower())
49
50    def test_errors(self):
51        self.assertRaises(TypeError, grp.getgrgid)
52        self.assertRaises(TypeError, grp.getgrgid, 3.14)
53        self.assertRaises(TypeError, grp.getgrnam)
54        self.assertRaises(TypeError, grp.getgrnam, 42)
55        self.assertRaises(TypeError, grp.getgrall, 42)
56        # embedded null character
57        self.assertRaisesRegex(ValueError, 'null', grp.getgrnam, 'a\x00b')
58
59        # try to get some errors
60        bynames = {}
61        bygids = {}
62        for (n, p, g, mem) in grp.getgrall():
63            if not n or n == '+':
64                continue # skip NIS entries etc.
65            bynames[n] = g
66            bygids[g] = n
67
68        allnames = list(bynames.keys())
69        namei = 0
70        fakename = allnames[namei]
71        while fakename in bynames:
72            chars = list(fakename)
73            for i in range(len(chars)):
74                if chars[i] == 'z':
75                    chars[i] = 'A'
76                    break
77                elif chars[i] == 'Z':
78                    continue
79                else:
80                    chars[i] = chr(ord(chars[i]) + 1)
81                    break
82            else:
83                namei = namei + 1
84                try:
85                    fakename = allnames[namei]
86                except IndexError:
87                    # should never happen... if so, just forget it
88                    break
89            fakename = ''.join(chars)
90
91        self.assertRaises(KeyError, grp.getgrnam, fakename)
92
93        # Choose a non-existent gid.
94        fakegid = 4127
95        while fakegid in bygids:
96            fakegid = (fakegid * 3) % 0x10000
97
98        self.assertRaises(KeyError, grp.getgrgid, fakegid)
99
100    def test_noninteger_gid(self):
101        entries = grp.getgrall()
102        if not entries:
103            self.skipTest('no groups')
104        # Choose an existent gid.
105        gid = entries[0][2]
106        self.assertRaises(TypeError, grp.getgrgid, float(gid))
107        self.assertRaises(TypeError, grp.getgrgid, str(gid))
108
109
110if __name__ == "__main__":
111    unittest.main()
112