~ack/landscape-client/sources.list-preserve-old-permissions

« back to all changes in this revision

Viewing changes to landscape/user/tests/test_management.py

  • Committer: Christopher Armstrong
  • Date: 2008-06-10 10:56:01 UTC
  • Revision ID: radix@twistedmatrix.com-20080610105601-l9qfvqjf88e7j8b6
Import landscape-client into public branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from landscape.lib import md5crypt
 
2
from landscape.user.management import UserManagement, UserManagementError
 
3
from landscape.user.tests.helpers import FakeUserProvider
 
4
from landscape.user.provider import UserNotFoundError, GroupNotFoundError
 
5
from landscape.tests.helpers import LandscapeTest, MakePathHelper, MockPopen
 
6
 
 
7
 
 
8
def guess_password(generated_password, plaintext_password):
 
9
    salt = generated_password[len("$1$"):generated_password.rfind("$")]
 
10
    crypted = md5crypt.md5crypt(plaintext_password, salt)
 
11
    return crypted
 
12
 
 
13
 
 
14
class UserWriteTest(LandscapeTest):
 
15
 
 
16
    helpers = [MakePathHelper]
 
17
 
 
18
    def setUp(self):
 
19
        LandscapeTest.setUp(self)
 
20
        self.shadow_file = self.make_path("""\
 
21
jdoe:$1$xFlQvTqe$cBtrNEDOIKMy/BuJoUdeG0:13348:0:99999:7:::
 
22
psmith:!:13348:0:99999:7:::
 
23
sbarnes:$1$q7sz09uw$q.A3526M/SHu8vUb.Jo1A/:13349:0:99999:7:::
 
24
""")
 
25
 
 
26
    def test_add_user(self):
 
27
        """L{UserManagement.add_user} should use C{adduser} to add users."""
 
28
        groups = [("users", "x", 1001, [])]
 
29
        provider = FakeUserProvider(groups=groups, popen=MockPopen(""))
 
30
        management = UserManagement(provider=provider)
 
31
        management.add_user("jdoe", "John Doe", "password", False, "users")
 
32
        self.assertEquals(len(provider.popen.popen_inputs), 2)
 
33
        self.assertEquals(provider.popen.popen_inputs[0],
 
34
                          ["adduser", "jdoe", "--disabled-password",
 
35
                           "--gecos", "John Doe,,,,", "--gid", "1001"])
 
36
 
 
37
        usermod = provider.popen.popen_inputs[1]
 
38
        self.assertEquals(len(usermod), 4, usermod)
 
39
        password = guess_password(usermod[2], "password")
 
40
        self.assertEquals(usermod, ["usermod", "-p", password, "jdoe"])
 
41
 
 
42
    def test_add_user_error(self):
 
43
        """
 
44
        L{UserManagement.add_user} should raise an L{UserManagementError} if
 
45
        C{adduser} fails.
 
46
        """
 
47
        provider = FakeUserProvider(popen=MockPopen("", return_codes=[1, 0]))
 
48
        management = UserManagement(provider=provider)
 
49
        self.assertRaises(UserManagementError, management.add_user,
 
50
                          "jdoe", u"John Doe", "password", False, None)
 
51
 
 
52
    def test_change_password_error(self):
 
53
        """
 
54
        L{UserManagement.add_user} should raise an L{UserManagementError} if
 
55
        C{usermod} fails.
 
56
        """
 
57
        provider = FakeUserProvider(popen=MockPopen("", return_codes=[0, 1]))
 
58
        management = UserManagement(provider=provider)
 
59
        self.assertRaises(UserManagementError, management.add_user,
 
60
                          "jdoe", u"John Doe", "password", False, None)
 
61
 
 
62
    def test_expire_password_error(self):
 
63
        """
 
64
        L{UserManagement.add_user} should raise an L{UserManagementError} if
 
65
        C{passwd} fails.
 
66
        """
 
67
        provider = FakeUserProvider(popen=MockPopen("",
 
68
                                                    return_codes=[0, 0,1]))
 
69
        management = UserManagement(provider=provider)
 
70
        self.assertRaises(UserManagementError, management.add_user,
 
71
                          "jdoe", u"John Doe", "password", True, None)
 
72
 
 
73
    def test_set_password(self):
 
74
        """
 
75
        L{UserManagement.set_password} should use C{usermod} to change
 
76
        a user's password.
 
77
        """
 
78
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
79
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
80
                                    popen=MockPopen("no output"))
 
81
        management = UserManagement(provider=provider)
 
82
        management.set_user_details("jdoe", password="password")
 
83
 
 
84
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
85
        password = provider.popen.popen_inputs[0][2]
 
86
        password = guess_password(password, "password")
 
87
        self.assertEquals(provider.popen.popen_inputs,
 
88
                          [["usermod", "-p", password, "jdoe"]])
 
89
 
 
90
    def test_set_password_with_system_user(self):
 
91
        """
 
92
        L{UserManagement.set_password} should allow us to edit system
 
93
        users.
 
94
        """
 
95
        data = [("root", "x", 0, 0, ",,,,", "/home/root", "/bin/zsh")]
 
96
        provider = FakeUserProvider(users=data,
 
97
                                    shadow_file=self.shadow_file,
 
98
                                    popen=MockPopen("no output"))
 
99
        management = UserManagement(provider=provider)
 
100
        management.set_user_details("root", password="password")
 
101
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
102
        password = provider.popen.popen_inputs[0][2]
 
103
        password = guess_password(password, "password")
 
104
        self.assertEquals(provider.popen.popen_inputs,
 
105
                          [["usermod", "-p", password, "root"]])
 
106
 
 
107
    def test_set_password_unicode(self):
 
108
        """
 
109
        Make sure passing unicode as username and password doesn't
 
110
        change things much (note that using something that's
 
111
        non-ASCII-encodable still probably won't work).
 
112
        """
 
113
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
114
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
115
                                    popen=MockPopen("no output"))
 
116
        management = UserManagement(provider=provider)
 
117
        management.set_user_details("jdoe", password=u"password")
 
118
 
 
119
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
120
        password = provider.popen.popen_inputs[0][2]
 
121
        password = guess_password(password, "password")
 
122
        self.assertEquals(provider.popen.popen_inputs,
 
123
                          [["usermod", "-p", password, "jdoe"]])
 
124
 
 
125
    def test_set_name(self):
 
126
        """
 
127
        L{UserManagement.set_user_details} should use C{chfn} to
 
128
        change a user's name.
 
129
        """
 
130
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
131
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
132
                                    popen=MockPopen("no output"))
 
133
        management = UserManagement(provider=provider)
 
134
        management.set_user_details("jdoe", name="JD")
 
135
 
 
136
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
137
        self.assertEquals(provider.popen.popen_inputs,
 
138
                          [["chfn", "-f", "JD", "jdoe"]])
 
139
 
 
140
    def test_set_location(self):
 
141
        """
 
142
        L{UserManagement.set_user_details} should use C{chfn} to
 
143
        change a user's location.
 
144
        """
 
145
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
146
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
147
                                    popen=MockPopen("no output"))
 
148
        management = UserManagement(provider=provider)
 
149
        management.set_user_details("jdoe", location="Everywhere")
 
150
 
 
151
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
152
        self.assertEquals(provider.popen.popen_inputs,
 
153
                          [["chfn", "-r", "Everywhere", "jdoe"]])
 
154
 
 
155
    def test_set_user_details_fails(self):
 
156
        """
 
157
        L{UserManagement.set_user_details} should raise an
 
158
        L{EditUserError} if C{chfn} fails.
 
159
        """
 
160
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
161
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
162
                                    popen=MockPopen("", return_codes=[1]))
 
163
        management = UserManagement(provider=provider)
 
164
        self.assertRaises(UserNotFoundError, management.set_user_details, 1000,
 
165
                          name="John Doe")
 
166
 
 
167
    def test_contact_details_in_general(self):
 
168
        """
 
169
        L{UserManagement.set_user_details} should use C{chfn} to
 
170
        change a user's contact details.
 
171
        """
 
172
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
173
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
174
                                    popen=MockPopen("no output"))
 
175
        management = UserManagement(provider=provider)
 
176
        location = u"Everywhere"
 
177
        work_number = u"1-800-123-4567"
 
178
        home_number = u"764-4321"
 
179
        management.set_user_details("jdoe", location=location,
 
180
                                    work_number=work_number,
 
181
                                    home_number=home_number)
 
182
 
 
183
        self.assertEquals(len(provider.popen.popen_inputs), 1)
 
184
        self.assertEquals(provider.popen.popen_inputs,
 
185
                          [["chfn", "-r", location, "-w", work_number,
 
186
                            "-h", home_number, "jdoe"]])
 
187
 
 
188
    def test_set_user_details_with_unknown_username(self):
 
189
        """
 
190
        L{UserManagement.set_user_details} should raise a
 
191
        L{UserManagementError} if the user being edited doesn't exist.
 
192
        """
 
193
        provider = FakeUserProvider(popen=MockPopen(""))
 
194
        management = UserManagement(provider=provider)
 
195
        self.assertRaises(UserNotFoundError, management.set_user_details,
 
196
                          "kevin", name=u"John Doe")
 
197
 
 
198
    def test_set_primary_group(self):
 
199
        """
 
200
        L{UserManagement.set_set_user_details} should use C{usermod} to change
 
201
        the user's primary group.
 
202
        """
 
203
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
204
        groups = [("users", "x", 1001, [])]
 
205
        provider = FakeUserProvider(users=data, groups=groups,
 
206
                                    shadow_file=self.shadow_file,
 
207
                                    popen=MockPopen("no output"))
 
208
 
 
209
        management = UserManagement(provider=provider)
 
210
        management.set_user_details("jdoe", primary_group_name="users")
 
211
 
 
212
        self.assertEquals(provider.popen.popen_inputs,
 
213
                          [["usermod", "-g", "1001", "jdoe"]])
 
214
 
 
215
    def test_set_primary_group_unknown_group(self):
 
216
        """
 
217
        L{UserManagement.set_user_details should use C{usermod} to change the
 
218
        user's primary group, in the event that we have an invalid group, we
 
219
        should raise a UserManagement error.
 
220
        """
 
221
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
222
        groups = [("staff", "x", 1001, [])]
 
223
        provider = FakeUserProvider(users=data, groups=groups,
 
224
                                    shadow_file=self.shadow_file,
 
225
                                    popen=MockPopen("group id 1002 unknown",
 
226
                                    return_codes=[1]))
 
227
        management = UserManagement(provider=provider)
 
228
        self.assertRaises(GroupNotFoundError, management.set_user_details,
 
229
                          "jdoe", primary_group_name="unknown")
 
230
 
 
231
    def test_lock_user(self):
 
232
        """L{UserManagement.lock_user} should use C{usermod} to lock users."""
 
233
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
234
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
235
                                    popen=MockPopen("no output"))
 
236
        management = UserManagement(provider=provider)
 
237
        management.lock_user("jdoe")
 
238
        self.assertEquals(provider.popen.popen_inputs,
 
239
                          [["usermod", "-L", "jdoe"]])
 
240
 
 
241
    def test_lock_user_fails(self):
 
242
        """
 
243
        L{UserManagement.lock_user} should raise a L{UserManagementError} if
 
244
        a C{usermod} fails.
 
245
        """
 
246
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
247
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
248
                                    popen=MockPopen("", [1]))
 
249
        management = UserManagement(provider=provider)
 
250
        self.assertRaises(UserNotFoundError, management.lock_user, 1000)
 
251
 
 
252
    def test_lock_user_with_unknown_uid(self):
 
253
        """
 
254
        L{UserManagement.lock_user} should raise a L{UserManagementError}
 
255
        if the user being removed doesn't exist.
 
256
        """
 
257
        provider = FakeUserProvider(popen=MockPopen(""))
 
258
        management = UserManagement(provider=provider)
 
259
        self.assertRaises(UserNotFoundError, management.lock_user, 1000)
 
260
 
 
261
    def test_unlock_user(self):
 
262
        """
 
263
        L{UserManagement.unlock_user} should use C{usermod} to unlock
 
264
        users.
 
265
        """
 
266
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
267
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
268
                                    popen=MockPopen("no output"))
 
269
        management = UserManagement(provider=provider)
 
270
        result = management.unlock_user("jdoe")
 
271
        self.assertEquals(provider.popen.popen_inputs,
 
272
                          [["usermod", "-U", "jdoe"]])
 
273
 
 
274
    def test_unlock_user_fails(self):
 
275
        """
 
276
        L{UserManagement.unlock_user} should raise an
 
277
        L{UserManagementError} if a C{usermod} fails.
 
278
        """
 
279
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
280
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
281
                                    popen=MockPopen("", [1]))
 
282
        management = UserManagement(provider=provider)
 
283
        self.assertRaises(UserNotFoundError, management.unlock_user, 1000)
 
284
 
 
285
    def test_unlock_user_with_unknown_uid(self):
 
286
        """
 
287
        L{UserManagement.unlock_user} should raise a
 
288
        L{UserManagementError} if the user being removed doesn't exist.
 
289
        """
 
290
        provider = FakeUserProvider(popen=MockPopen(""))
 
291
        management = UserManagement(provider=provider)
 
292
        self.assertRaises(UserNotFoundError, management.unlock_user, 1000)
 
293
 
 
294
    def test_remove_user(self):
 
295
        """
 
296
        L{UserManagement.remove_user} should use C{deluser} to remove
 
297
        users.
 
298
        """
 
299
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
300
        popen = MockPopen("Removing user `jdoe'...\r\ndone.")
 
301
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
302
                                    popen=popen)
 
303
        management = UserManagement(provider=provider)
 
304
        management.remove_user("jdoe")
 
305
        self.assertEquals(popen.popen_inputs, [["deluser", "jdoe"]])
 
306
 
 
307
    def test_remove_user_with_unknown_username(self):
 
308
        """
 
309
        L{UserManagement.remove_user} should raise a
 
310
        L{UserManagementError} if the user being removed doesn't exist.
 
311
        """
 
312
        provider = FakeUserProvider(popen=MockPopen(""))
 
313
        management = UserManagement(provider=provider)
 
314
        self.assertRaises(UserNotFoundError, management.remove_user, "smith")
 
315
 
 
316
    def test_remove_user_fails(self):
 
317
        """
 
318
        L{UserManagement.remove_user} should raise a
 
319
        L{UserManagementError} if the user can't be removed.
 
320
        """
 
321
        self.log_helper.ignore_errors(UserNotFoundError)
 
322
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
323
        popen = MockPopen("/usr/sbin/deluser: Only root may remove a user or "
 
324
                          "group from the system.", [1])
 
325
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
326
                                    popen=popen)
 
327
        management = UserManagement(provider=provider)
 
328
        self.assertRaises(UserNotFoundError, management.remove_user, "smith")
 
329
 
 
330
    def test_remove_user_and_home(self):
 
331
        """
 
332
        L{UserManagement.remove_user} should use C{deluser} to remove
 
333
        the contents of a user's home directory.
 
334
        """
 
335
        data = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
336
        popen = MockPopen("Removing user `jdoe`...\r\ndone.", [0])
 
337
        provider = FakeUserProvider(users=data, shadow_file=self.shadow_file,
 
338
                                    popen=popen)
 
339
        management = UserManagement(provider=provider)
 
340
        management.remove_user("jdoe", delete_home=True)
 
341
        self.assertEquals(popen.popen_inputs,
 
342
                          [["deluser", "jdoe", "--remove-home"]])
 
343
 
 
344
 
 
345
 
 
346
class GroupWriteTest(LandscapeTest):
 
347
 
 
348
    helpers = [MakePathHelper]
 
349
 
 
350
    def setUp(self):
 
351
        LandscapeTest.setUp(self)
 
352
        self.shadow_file = self.make_path("""\
 
353
jdoe:$1$xFlQvTqe$cBtrNEDOIKMy/BuJoUdeG0:13348:0:99999:7:::
 
354
psmith:!:13348:0:99999:7:::
 
355
sbarnes:$1$q7sz09uw$q.A3526M/SHu8vUb.Jo1A/:13349:0:99999:7:::
 
356
""")
 
357
 
 
358
    def test_add_group(self):
 
359
        """
 
360
        L{UserManagement.add_group} should use the system tool
 
361
        C{addgroup} to create groups.
 
362
        """
 
363
        provider = FakeUserProvider(popen=MockPopen("Result"))
 
364
        management = UserManagement(provider=provider)
 
365
        result = management.add_group("webdev")
 
366
        self.assertEquals(provider.popen.popen_inputs, [["addgroup", "webdev"]])
 
367
        self.assertEquals(result, "Result")
 
368
 
 
369
    def test_add_group_handles_errors(self):
 
370
        """
 
371
        If the system tool C{addgroup} returns a non-0 exit code,
 
372
        L{UserManagement.add_group} should raise an L{UserManagementError}.
 
373
        """
 
374
        provider = FakeUserProvider(popen=MockPopen("Error Result", [1]))
 
375
        management = UserManagement(provider=provider)
 
376
        self.assertRaises(UserManagementError, management.add_group, "kaboom")
 
377
 
 
378
    def test_set_group_details(self):
 
379
        """
 
380
        L{UserManagement.set_group_details} should use C{groupmode} to
 
381
        change a group's name.
 
382
        """
 
383
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
384
        groups = [("bizdev", "x", 1001, [])]
 
385
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
386
                                    groups=groups, popen=MockPopen("no output"))
 
387
        management = UserManagement(provider=provider)
 
388
        management.set_group_details("bizdev", "sales")
 
389
 
 
390
        self.assertEquals(provider.popen.popen_inputs,
 
391
                          [["groupmod", "-n", "sales", "bizdev"]])
 
392
 
 
393
    def test_set_group_details_with_unknown_groupname(self):
 
394
        """
 
395
        L{UserManagement.set_group_details} should raise a
 
396
        L{UserManagementError} if the group being updated doesn't exist.
 
397
        """
 
398
        provider = FakeUserProvider(popen=MockPopen(""))
 
399
        management = UserManagement(provider=provider)
 
400
        self.assertRaises(GroupNotFoundError, management.set_group_details,
 
401
                          "sales", u"newsales")
 
402
 
 
403
    def test_set_group_details_fails(self):
 
404
        """
 
405
        L{UserManagement.set_group_details} should raise a
 
406
        L{UserManagementError} if the group can't be renamed.
 
407
        """
 
408
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
409
        groups = [("bizdev", "x", 1001, [])]
 
410
        popen = MockPopen("groupmod: sales is not a unique name", [1])
 
411
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
412
                                    groups=groups, popen=popen)
 
413
        management = UserManagement(provider=provider)
 
414
        self.assertRaises(UserManagementError, management.set_group_details,
 
415
                          "bizdev", u"sales")
 
416
 
 
417
    def test_add_member(self):
 
418
        """
 
419
        L{UserManagement.add_group_member} should use the system tool
 
420
        C{gpasswd} via the process factory to add a member to a group.
 
421
        """
 
422
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
423
        groups = [("bizdev", "x", 1001, [])]
 
424
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
425
                                    groups=groups,
 
426
                                    popen=MockPopen(
 
427
                                    "Removing user jdoe from group bizdev"))
 
428
        management = UserManagement(provider=provider)
 
429
 
 
430
        output = management.add_group_member("jdoe", "bizdev")
 
431
        self.assertEquals(provider.popen.popen_inputs,
 
432
                          [["gpasswd", "-a", "jdoe", "bizdev"]])
 
433
        self.assertEquals(output, "Removing user jdoe from group bizdev")
 
434
 
 
435
    def test_add_member_with_unknown_groupname(self):
 
436
        """
 
437
        L{UserManagement.add_group_member} should raise a
 
438
        L{UserManagementError} if the group to add the member to doesn't
 
439
        exist.
 
440
        """
 
441
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
442
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
443
                                    popen=MockPopen(""))
 
444
        management = UserManagement(provider=provider)
 
445
        self.assertRaises(GroupNotFoundError, management.add_group_member,
 
446
                          "jdoe", "bizdev")
 
447
 
 
448
    def test_add_member_with_unknown_username(self):
 
449
        """
 
450
        L{UserManagement.add_group_member} should raise a
 
451
        L{UserManagementError} if the user being associated doesn't
 
452
        exist.
 
453
        """
 
454
        groups = [("bizdev", "x", 1001, [])]
 
455
        provider = FakeUserProvider(groups=groups, popen=MockPopen(""))
 
456
        management = UserManagement(provider=provider)
 
457
        self.assertRaises(UserNotFoundError, management.add_group_member,
 
458
                          "bizdev", "smith")
 
459
 
 
460
    def test_add_member_failure(self):
 
461
        """
 
462
        If adding a member to a group fails,
 
463
        L{UserManagement.add_group_member} should raise an
 
464
        L{UserManagementError}.
 
465
        """
 
466
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
467
        groups = [("bizdev", "x", 1001, [])]
 
468
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
469
                                    groups=groups,
 
470
                                    popen=MockPopen("no output", [1]))
 
471
        management = UserManagement(provider=provider)
 
472
        self.assertRaises(UserNotFoundError, management.add_group_member,
 
473
                          1000, 1001)
 
474
 
 
475
    def test_remove_member(self):
 
476
        """
 
477
        L{UserManagement.remove_group_member} should use the system
 
478
        tool C{gpasswd} via the process factory to remove a member
 
479
        from a group.
 
480
        """
 
481
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
482
        groups = [("bizdev", "x", 1001, [])]
 
483
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
484
                                    groups=groups,
 
485
                                    popen=MockPopen(
 
486
                                    "Removing user jdoe from group bizdev"))
 
487
        management = UserManagement(provider=provider)
 
488
        output = management.remove_group_member("jdoe", "bizdev")
 
489
        self.assertEquals(provider.popen.popen_inputs,
 
490
                          [["gpasswd", "-d", "jdoe", "bizdev"]])
 
491
        self.assertEquals(output, "Removing user jdoe from group bizdev")
 
492
 
 
493
    def test_remove_member_with_unknown_groupname(self):
 
494
        """
 
495
        L{UserManagement.remove_group_member} should raise a
 
496
        L{UserManagementError} if the group to remove the member to
 
497
        doesn't exist.
 
498
        """
 
499
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
500
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
501
                                    popen=MockPopen("", return_codes=[2]))
 
502
        management = UserManagement(provider=provider)
 
503
        self.assertRaises(GroupNotFoundError, management.remove_group_member,
 
504
                          "jdoe", "bizdev")
 
505
 
 
506
    def test_remove_member_with_unknown_username(self):
 
507
        """
 
508
        L{UserManagement.remove_group_member} should raise a
 
509
        L{UserManagementError} if the user being associated doesn't
 
510
        exist.
 
511
        """
 
512
        groups = [("bizdev", "x", 1001, [])]
 
513
        provider = FakeUserProvider(groups=groups,
 
514
                                    popen=MockPopen("", return_codes=[4]))
 
515
        management = UserManagement(provider=provider)
 
516
        self.assertRaises(UserNotFoundError, management.remove_group_member,
 
517
                          "jdoe", "bizdev")
 
518
 
 
519
    def test_remove_member_failure(self):
 
520
        """
 
521
        If removing a member from a group fails,
 
522
        L{UserManagement.remove_group_member} should raise a
 
523
        L{UserManagementError}.
 
524
        """
 
525
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
526
        groups = [("bizdev", "x", 1001, [])]
 
527
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
528
                                    groups=groups,
 
529
                                    popen=MockPopen("no output", [1]))
 
530
        management = UserManagement(provider=provider)
 
531
        self.assertRaises(UserManagementError,
 
532
                          management.remove_group_member, "jdoe", "bizdev")
 
533
 
 
534
    def test_remove_group(self):
 
535
        """
 
536
        L{UserManagement.remove_group} should use C{groupdel} to
 
537
        remove groups.
 
538
        """
 
539
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
540
        groups = [("bizdev", "x", 50, [])]
 
541
        popen = MockPopen("Removing group `bizdev'...\r\ndone.")
 
542
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
543
                                    groups=groups, popen=popen)
 
544
        management = UserManagement(provider=provider)
 
545
        output = management.remove_group("bizdev")
 
546
        self.assertEquals(provider.popen.popen_inputs, [["groupdel", "bizdev"]])
 
547
 
 
548
    def test_remove_group_with_unknown_groupname(self):
 
549
        """
 
550
        L{UserManagement.remove_group} should raise a
 
551
        L{GroupMissingError} if the group being removed doesn't exist.
 
552
        """
 
553
        provider = FakeUserProvider(popen=MockPopen(""))
 
554
        management = UserManagement(provider=provider)
 
555
        self.assertRaises(GroupNotFoundError, management.remove_group, "ubuntu")
 
556
 
 
557
    def test_remove_group_fails(self):
 
558
        """
 
559
        L{UserManagement.remove_user} should raise a
 
560
        L{RemoveUserError} if the user can't be removed.
 
561
        """
 
562
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/zsh")]
 
563
        groups = [("bizdev", "x", 50, [])]
 
564
        popen = MockPopen("/usr/sbin/deluser: Only root may remove a user or "
 
565
                          "group from the system.", [1])
 
566
        provider = FakeUserProvider(users=users, shadow_file=self.shadow_file,
 
567
                                    groups=groups, popen=popen)
 
568
        management = UserManagement(provider=provider)
 
569
        self.assertRaises(GroupNotFoundError, management.remove_group,
 
570
                          "ubuntu")