Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / python / test / test_fakepwd.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{twisted.python.fakepwd}.
6 """
7
8 try:
9     import pwd
10 except ImportError:
11     pwd = None
12
13 try:
14     import spwd
15 except ImportError:
16     spwd = None
17
18 import os
19 from operator import getitem
20
21 from twisted.trial.unittest import TestCase
22 from twisted.python.fakepwd import UserDatabase, ShadowDatabase
23 from twisted.python.compat import set
24
25
26 class UserDatabaseTestsMixin:
27     """
28     L{UserDatabaseTestsMixin} defines tests which apply to any user database
29     implementation.  Subclasses should mix it in, implement C{setUp} to create
30     C{self.database} bound to a user database instance, and implement
31     C{getExistingUserInfo} to return information about a user (such information
32     should be unique per test method).
33     """
34     def test_getpwuid(self):
35         """
36         I{getpwuid} accepts a uid and returns the user record associated with
37         it.
38         """
39         for i in range(2):
40             # Get some user which exists in the database.
41             username, password, uid, gid, gecos, dir, shell = self.getExistingUserInfo()
42
43             # Now try to look it up and make sure the result is correct.
44             entry = self.database.getpwuid(uid)
45             self.assertEqual(entry.pw_name, username)
46             self.assertEqual(entry.pw_passwd, password)
47             self.assertEqual(entry.pw_uid, uid)
48             self.assertEqual(entry.pw_gid, gid)
49             self.assertEqual(entry.pw_gecos, gecos)
50             self.assertEqual(entry.pw_dir, dir)
51             self.assertEqual(entry.pw_shell, shell)
52
53
54     def test_noSuchUID(self):
55         """
56         I{getpwuid} raises L{KeyError} when passed a uid which does not exist
57         in the user database.
58         """
59         self.assertRaises(KeyError, self.database.getpwuid, -13)
60
61
62     def test_getpwnam(self):
63         """
64         I{getpwnam} accepts a username and returns the user record associated
65         with it.
66         """
67         for i in range(2):
68             # Get some user which exists in the database.
69             username, password, uid, gid, gecos, dir, shell = self.getExistingUserInfo()
70
71             # Now try to look it up and make sure the result is correct.
72             entry = self.database.getpwnam(username)
73             self.assertEqual(entry.pw_name, username)
74             self.assertEqual(entry.pw_passwd, password)
75             self.assertEqual(entry.pw_uid, uid)
76             self.assertEqual(entry.pw_gid, gid)
77             self.assertEqual(entry.pw_gecos, gecos)
78             self.assertEqual(entry.pw_dir, dir)
79             self.assertEqual(entry.pw_shell, shell)
80
81
82     def test_noSuchName(self):
83         """
84         I{getpwnam} raises L{KeyError} when passed a username which does not
85         exist in the user database.
86         """
87         self.assertRaises(
88             KeyError, self.database.getpwnam,
89             'no' 'such' 'user' 'exists' 'the' 'name' 'is' 'too' 'long' 'and' 'has'
90             '\1' 'in' 'it' 'too')
91
92
93     def test_recordLength(self):
94         """
95         The user record returned by I{getpwuid}, I{getpwnam}, and I{getpwall}
96         has a length.
97         """
98         db = self.database
99         username, password, uid, gid, gecos, dir, shell = self.getExistingUserInfo()
100         for entry in [db.getpwuid(uid), db.getpwnam(username), db.getpwall()[0]]:
101             self.assertIsInstance(len(entry), int)
102             self.assertEquals(len(entry), 7)
103
104
105     def test_recordIndexable(self):
106         """
107         The user record returned by I{getpwuid}, I{getpwnam}, and I{getpwall}
108         is indexable, with successive indexes starting from 0 corresponding to
109         the values of the C{pw_name}, C{pw_passwd}, C{pw_uid}, C{pw_gid},
110         C{pw_gecos}, C{pw_dir}, and C{pw_shell} attributes, respectively.
111         """
112         db = self.database
113         username, password, uid, gid, gecos, dir, shell = self.getExistingUserInfo()
114         for entry in [db.getpwuid(uid), db.getpwnam(username), db.getpwall()[0]]:
115             self.assertEqual(entry[0], username)
116             self.assertEqual(entry[1], password)
117             self.assertEqual(entry[2], uid)
118             self.assertEqual(entry[3], gid)
119             self.assertEqual(entry[4], gecos)
120             self.assertEqual(entry[5], dir)
121             self.assertEqual(entry[6], shell)
122
123             self.assertEqual(len(entry), len(list(entry)))
124             self.assertRaises(IndexError, getitem, entry, 7)
125
126
127
128 class UserDatabaseTests(TestCase, UserDatabaseTestsMixin):
129     """
130     Tests for L{UserDatabase}.
131     """
132     def setUp(self):
133         """
134         Create a L{UserDatabase} with no user data in it.
135         """
136         self.database = UserDatabase()
137         self._counter = 0
138
139
140     def getExistingUserInfo(self):
141         """
142         Add a new user to C{self.database} and return its information.
143         """
144         self._counter += 1
145         suffix = '_' + str(self._counter)
146         username = 'username' + suffix
147         password = 'password' + suffix
148         uid = self._counter
149         gid = self._counter + 1000
150         gecos = 'gecos' + suffix
151         dir = 'dir' + suffix
152         shell = 'shell' + suffix
153
154         self.database.addUser(username, password, uid, gid, gecos, dir, shell)
155         return (username, password, uid, gid, gecos, dir, shell)
156
157
158     def test_addUser(self):
159         """
160         L{UserDatabase.addUser} accepts seven arguments, one for each field of
161         a L{pwd.struct_passwd}, and makes the new record available via
162         L{UserDatabase.getpwuid}, L{UserDatabase.getpwnam}, and
163         L{UserDatabase.getpwall}.
164         """
165         username = 'alice'
166         password = 'secr3t'
167         uid = 123
168         gid = 456
169         gecos = 'Alice,,,'
170         home = '/users/alice'
171         shell = '/usr/bin/foosh'
172
173         db = self.database
174         db.addUser(username, password, uid, gid, gecos, home, shell)
175
176         for [entry] in [[db.getpwuid(uid)], [db.getpwnam(username)],
177                         db.getpwall()]:
178             self.assertEqual(entry.pw_name, username)
179             self.assertEqual(entry.pw_passwd, password)
180             self.assertEqual(entry.pw_uid, uid)
181             self.assertEqual(entry.pw_gid, gid)
182             self.assertEqual(entry.pw_gecos, gecos)
183             self.assertEqual(entry.pw_dir, home)
184             self.assertEqual(entry.pw_shell, shell)
185
186
187
188 class PwdModuleTests(TestCase, UserDatabaseTestsMixin):
189     """
190     L{PwdModuleTests} runs the tests defined by L{UserDatabaseTestsMixin}
191     against the built-in C{pwd} module.  This serves to verify that
192     L{UserDatabase} is really a fake of that API.
193     """
194     if pwd is None:
195         skip = "Cannot verify UserDatabase against pwd without pwd"
196     else:
197         database = pwd
198
199     def setUp(self):
200         self._users = iter(self.database.getpwall())
201         self._uids = set()
202
203
204     def getExistingUserInfo(self):
205         """
206         Read and return the next record from C{self._users}, filtering out
207         any records with previously seen uid values (as these cannot be
208         found with C{getpwuid} and only cause trouble).
209         """
210         while True:
211             entry = self._users.next()
212             uid = entry.pw_uid
213             if uid not in self._uids:
214                 self._uids.add(uid)
215                 return entry
216
217
218
219 class ShadowDatabaseTestsMixin:
220     """
221     L{ShadowDatabaseTestsMixin} defines tests which apply to any shadow user
222     database implementation.  Subclasses should mix it in, implement C{setUp} to
223     create C{self.database} bound to a shadow user database instance, and
224     implement C{getExistingUserInfo} to return information about a user (such
225     information should be unique per test method).
226     """
227     def test_getspnam(self):
228         """
229         L{getspnam} accepts a username and returns the user record associated
230         with it.
231         """
232         for i in range(2):
233             # Get some user which exists in the database.
234             (username, password, lastChange, min, max, warn, inact, expire,
235              flag) = self.getExistingUserInfo()
236
237             entry = self.database.getspnam(username)
238             self.assertEquals(entry.sp_nam, username)
239             self.assertEquals(entry.sp_pwd, password)
240             self.assertEquals(entry.sp_lstchg, lastChange)
241             self.assertEquals(entry.sp_min, min)
242             self.assertEquals(entry.sp_max, max)
243             self.assertEquals(entry.sp_warn, warn)
244             self.assertEquals(entry.sp_inact, inact)
245             self.assertEquals(entry.sp_expire, expire)
246             self.assertEquals(entry.sp_flag, flag)
247
248
249     def test_noSuchName(self):
250         """
251         I{getspnam} raises L{KeyError} when passed a username which does not
252         exist in the user database.
253         """
254         self.assertRaises(KeyError, self.database.getspnam, "alice")
255
256
257     def test_recordLength(self):
258         """
259         The shadow user record returned by I{getspnam} and I{getspall} has a
260         length.
261         """
262         db = self.database
263         username = self.getExistingUserInfo()[0]
264         for entry in [db.getspnam(username), db.getspall()[0]]:
265             self.assertIsInstance(len(entry), int)
266             self.assertEquals(len(entry), 9)
267
268
269     def test_recordIndexable(self):
270         """
271         The shadow user record returned by I{getpwnam} and I{getspall} is
272         indexable, with successive indexes starting from 0 corresponding to the
273         values of the C{sp_nam}, C{sp_pwd}, C{sp_lstchg}, C{sp_min}, C{sp_max},
274         C{sp_warn}, C{sp_inact}, C{sp_expire}, and C{sp_flag} attributes,
275         respectively.
276         """
277         db = self.database
278         (username, password, lastChange, min, max, warn, inact, expire,
279          flag) = self.getExistingUserInfo()
280         for entry in [db.getspnam(username), db.getspall()[0]]:
281             self.assertEquals(entry[0], username)
282             self.assertEquals(entry[1], password)
283             self.assertEquals(entry[2], lastChange)
284             self.assertEquals(entry[3], min)
285             self.assertEquals(entry[4], max)
286             self.assertEquals(entry[5], warn)
287             self.assertEquals(entry[6], inact)
288             self.assertEquals(entry[7], expire)
289             self.assertEquals(entry[8], flag)
290
291             self.assertEquals(len(entry), len(list(entry)))
292             self.assertRaises(IndexError, getitem, entry, 9)
293
294
295
296 class ShadowDatabaseTests(TestCase, ShadowDatabaseTestsMixin):
297     """
298     Tests for L{ShadowDatabase}.
299     """
300     def setUp(self):
301         """
302         Create a L{ShadowDatabase} with no user data in it.
303         """
304         self.database = ShadowDatabase()
305         self._counter = 0
306
307
308     def getExistingUserInfo(self):
309         """
310         Add a new user to C{self.database} and return its information.
311         """
312         self._counter += 1
313         suffix = '_' + str(self._counter)
314         username = 'username' + suffix
315         password = 'password' + suffix
316         lastChange = self._counter + 1
317         min = self._counter + 2
318         max = self._counter + 3
319         warn = self._counter + 4
320         inact = self._counter + 5
321         expire = self._counter + 6
322         flag = self._counter + 7
323
324         self.database.addUser(username, password, lastChange, min, max, warn,
325                               inact, expire, flag)
326         return (username, password, lastChange, min, max, warn, inact,
327                 expire, flag)
328
329
330     def test_addUser(self):
331         """
332         L{UserDatabase.addUser} accepts seven arguments, one for each field of
333         a L{pwd.struct_passwd}, and makes the new record available via
334         L{UserDatabase.getpwuid}, L{UserDatabase.getpwnam}, and
335         L{UserDatabase.getpwall}.
336         """
337         username = 'alice'
338         password = 'secr3t'
339         lastChange = 17
340         min = 42
341         max = 105
342         warn = 12
343         inact = 3
344         expire = 400
345         flag = 3
346
347         db = self.database
348         db.addUser(username, password, lastChange, min, max, warn, inact,
349                    expire, flag)
350
351         for [entry] in [[db.getspnam(username)], db.getspall()]:
352             self.assertEquals(entry.sp_nam, username)
353             self.assertEquals(entry.sp_pwd, password)
354             self.assertEquals(entry.sp_lstchg, lastChange)
355             self.assertEquals(entry.sp_min, min)
356             self.assertEquals(entry.sp_max, max)
357             self.assertEquals(entry.sp_warn, warn)
358             self.assertEquals(entry.sp_inact, inact)
359             self.assertEquals(entry.sp_expire, expire)
360             self.assertEquals(entry.sp_flag, flag)
361
362
363
364 class SPwdModuleTests(TestCase, ShadowDatabaseTestsMixin):
365     """
366     L{SPwdModuleTests} runs the tests defined by L{ShadowDatabaseTestsMixin}
367     against the built-in C{spwd} module.  This serves to verify that
368     L{ShadowDatabase} is really a fake of that API.
369     """
370     if spwd is None:
371         skip = "Cannot verify ShadowDatabase against spwd without spwd"
372     elif os.getuid() != 0:
373         skip = "Cannot access shadow user database except as root"
374     else:
375         database = spwd
376
377     def setUp(self):
378         self._users = iter(self.database.getspall())
379
380
381     def getExistingUserInfo(self):
382         """
383         Read and return the next record from C{self._users}.
384         """
385         return self._users.next()
386