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.getgrnam)
53        self.assertRaises(TypeError, grp.getgrall, 42)
54        # embedded null character
55        self.assertRaises(ValueError, grp.getgrnam, 'a\x00b')
56
57        # try to get some errors
58        bynames = {}
59        bygids = {}
60        for (n, p, g, mem) in grp.getgrall():
61            if not n or n == '+':
62                continue # skip NIS entries etc.
63            bynames[n] = g
64            bygids[g] = n
65
66        allnames = list(bynames.keys())
67        namei = 0
68        fakename = allnames[namei]
69        while fakename in bynames:
70            chars = list(fakename)
71            for i in range(len(chars)):
72                if chars[i] == 'z':
73                    chars[i] = 'A'
74                    break
75                elif chars[i] == 'Z':
76                    continue
77                else:
78                    chars[i] = chr(ord(chars[i]) + 1)
79                    break
80            else:
81                namei = namei + 1
82                try:
83                    fakename = allnames[namei]
84                except IndexError:
85                    # should never happen... if so, just forget it
86                    break
87            fakename = ''.join(chars)
88
89        self.assertRaises(KeyError, grp.getgrnam, fakename)
90
91        # Choose a non-existent gid.
92        fakegid = 4127
93        while fakegid in bygids:
94            fakegid = (fakegid * 3) % 0x10000
95
96        self.assertRaises(KeyError, grp.getgrgid, fakegid)
97
98    def test_noninteger_gid(self):
99        entries = grp.getgrall()
100        if not entries:
101            self.skipTest('no groups')
102        # Choose an existent gid.
103        gid = entries[0][2]
104        self.assertRaises(TypeError, grp.getgrgid, float(gid))
105        self.assertRaises(TypeError, grp.getgrgid, str(gid))
106
107
108if __name__ == "__main__":
109    unittest.main()
110