Removed DOCUMENT ME comments that were generated and applied source code
[utils] / security / src / test / java / org / wamblee / usermgt / UserAdministrationImplTest.java
1 /*
2  * Copyright 2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.usermgt;
17
18 import junit.framework.TestCase;
19
20 import org.apache.log4j.Logger;
21
22 import org.wamblee.security.encryption.Md5HexMessageDigester;
23
24 import org.wamblee.usermgt.UserMgtException.Reason;
25
26 import java.util.Set;
27
28 /**
29  * Test of user administration implementation.
30  * 
31  * @author Erik Brakkee
32  */
33 public class UserAdministrationImplTest extends TestCase {
34     private static final Logger LOGGER = Logger
35         .getLogger(UserAdministrationImplTest.class);
36
37     private static final String USER1 = "piet";
38
39     private static final String PASS1 = "passpiet";
40
41     private static final String USER2 = "kees";
42
43     private static final String PASS2 = "passkees";
44
45     private static final String GROUP1 = "cyclists";
46
47     private static final String GROUP2 = "runners";
48
49     private UserAdministration admin;
50
51     /*
52      * (non-Javadoc)
53      * 
54      * @see junit.framework.TestCase#setUp()
55      */
56     @Override
57     protected void setUp() throws Exception {
58         super.setUp();
59         admin = createAdmin();
60     }
61
62     protected UserAdministration createAdmin() {
63         UserSet users = new InMemoryUserSet(new RegexpNameValidator(
64             RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD,
65             "Password must contain at least 6 characters"),
66             new Md5HexMessageDigester());
67         GroupSet groups = new InMemoryGroupSet();
68
69         return new UserAdministrationImpl(users, groups,
70             new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
71                 Reason.INVALID_USERNAME, "Invalid user"),
72             new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
73                 Reason.INVALID_GROUPNAME, "Invalid group"));
74     }
75
76     protected User createUser(String aName, String aPassword, Group aGroup)
77         throws UserMgtException {
78         return UsermgtTestUtils.createUser(aName, aPassword, aGroup);
79     }
80
81     /**
82      * Constructs the admin, verify it contains no users and no groups.
83      */
84     public void testConstruct() {
85         assertEquals(0, admin.getUsers().size());
86         assertEquals(0, admin.getGroups().size());
87         assertEquals(0, admin.getUserCount());
88         assertEquals(0, admin.getGroupCount());
89     }
90
91     /**
92      * Creates a new group. Verifies the group is created correctly and that the
93      * user is added.
94      * 
95      */
96     public void testCreateGroup() throws UserMgtException {
97         Group group = admin.createGroup(GROUP1);
98         assertNotNull(group);
99         assertEquals(GROUP1, group.getName());
100
101         Set<Group> groups = admin.getGroups();
102         assertEquals(1, groups.size());
103         assertEquals(1, admin.getGroupCount());
104         assertTrue(groups.contains(group));
105     }
106
107     private void createInvalidGroup(String aUsername) {
108         try {
109             admin.createGroup(aUsername);
110             fail();
111         } catch (UserMgtException e) {
112             assertEquals(UserMgtException.Reason.INVALID_GROUPNAME, e
113                 .getReason());
114             assertEquals(0, admin.getGroupCount());
115         }
116     }
117
118     /**
119      * Creates a new group with an invalid name. Verifies that the appropriate
120      * exception is thrown.
121      * 
122      * @throws UserMgtException
123      */
124     public void testCreateInvalidGroupName() throws UserMgtException {
125         createInvalidGroup("");
126         createInvalidGroup("0abc"); // should not start with digits
127         createInvalidGroup("a b"); // should not contain spaces
128         createInvalidGroup(" aa");
129         createInvalidGroup("aa ");
130     }
131
132     /**
133      * Creates a new group which conflicts with an existing one. Verifies that
134      * the UserMgtException is thrown and that no group is added.
135      * 
136      */
137     public void testCreateDuplicateGroup() throws UserMgtException {
138         admin.createGroup(GROUP1);
139
140         try {
141             admin.createGroup(GROUP1);
142         } catch (UserMgtException e) {
143             assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason());
144             assertEquals(1, admin.getGroupCount());
145
146             return;
147         }
148
149         fail();
150     }
151
152     /**
153      * Creates a new user. Verifies the user is created correctly and that the
154      * user is added.
155      * 
156      */
157     public void testCreateUser() throws UserMgtException {
158         Group group = admin.createGroup(GROUP1);
159         User user = admin.createUser(USER1, PASS1, group);
160         assertNotNull(user);
161         assertEquals(USER1, user.getName());
162         user.checkPassword(PASS1);
163
164         Set<User> users = admin.getUsers();
165         assertEquals(1, users.size());
166         assertEquals(1, admin.getUserCount());
167         assertTrue(users.contains(user));
168     }
169
170     private void createInvalidUser(String aUsername, Group aGroup) {
171         try {
172             admin.createUser(aUsername, "pass", aGroup);
173             fail();
174         } catch (UserMgtException e) {
175             assertEquals(UserMgtException.Reason.INVALID_USERNAME, e
176                 .getReason());
177             assertEquals(0, admin.getUserCount());
178         }
179     }
180
181     /**
182      * Constructs users with invalid names. Verifies that the appropriate
183      * exception is thrown.
184      * 
185      */
186     public void testCreateInvalidUserName() throws UserMgtException {
187         Group group = admin.createGroup(GROUP1);
188         createInvalidUser("", group);
189         createInvalidUser("0abc", group); // should not start with digits
190         createInvalidUser("a b", group); // should not contain spaces
191         createInvalidUser(" aa", group);
192         createInvalidUser("aa ", group);
193     }
194
195     /**
196      * Creates a new user which conflicts with an existing one. Verifies that
197      * the UserMgtException is thrown and that no user is added.
198      * 
199      */
200     public void testCreateDuplicateUser() throws UserMgtException {
201         Group group = admin.createGroup(GROUP1);
202         admin.createUser(USER1, PASS1, group);
203
204         try {
205             admin.createUser(USER1, PASS2, group);
206             fail();
207         } catch (UserMgtException e) {
208             assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason());
209             assertEquals(1, admin.getUserCount());
210         }
211     }
212
213     /**
214      * Gets a known user by name. Verifies the correct user is obtained.
215      * Verifies that null is returned when trying to obtain an unknown user.
216      * 
217      */
218     public void testGetUser() throws UserMgtException {
219         Group group = admin.createGroup(GROUP1);
220         User user = admin.createUser(USER1, PASS1, group);
221         User user2 = admin.getUser(USER1);
222         assertTrue(user.equals(user2));
223         assertNull(admin.getUser(USER2));
224     }
225
226     /**
227      * Gets a known group by name. Verifies the correct group is obtained.
228      * Verifies that null is returned when the group is not known.
229      * 
230      */
231     public void testGetGroup() throws UserMgtException {
232         Group group = admin.createGroup(GROUP1);
233         Group group2 = admin.getGroup(GROUP1);
234         assertTrue(group.equals(group2));
235         assertNull(admin.getGroup(GROUP2));
236     }
237
238     /**
239      * Adds a user to a group. Verifies that the user is added using several API
240      * calls. Verifies that an exception occurs if the user is not already part
241      * of the group.
242      * 
243      */
244     public void testAddUserToGroup() throws UserMgtException {
245         Group group = admin.createGroup(GROUP1);
246         User user = admin.createUser(USER1, PASS1, group);
247         Group group2 = admin.createGroup(GROUP2);
248         assertTrue(user.isInGroup(group));
249         assertFalse(user.isInGroup(group2));
250         admin.addUserToGroup(user, group2);
251         assertTrue(user.isInGroup(group));
252         assertTrue(user.isInGroup(group2));
253
254         Set<User> users = admin.getUsers(group2);
255         assertNotNull(users);
256         assertEquals(1, users.size());
257         assertTrue(users.contains(user));
258
259         try {
260             admin.addUserToGroup(user, group);
261         } catch (UserMgtException e) {
262             assertEquals(UserMgtException.Reason.USER_ALREADY_IN_GROUP, e
263                 .getReason());
264
265             return;
266         }
267
268         fail();
269     }
270
271     /**
272      * Adds a user to a group where the user does not exist. Verifies that an
273      * exception occurs.
274      * 
275      */
276     public void testAddUserToGroupUnknownUser() throws UserMgtException {
277         Group group = admin.createGroup(GROUP1);
278         User user = createUser(USER1, PASS1, group);
279
280         try {
281             admin.addUserToGroup(user, group);
282         } catch (UserMgtException e) {
283             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
284
285             return;
286         }
287
288         fail();
289     }
290
291     /**
292      * Adds a user to a group where the user does not exist. Verifies that an
293      * exception occurs.
294      * 
295      */
296     public void testAddUserToGroupUnknownGroup() throws UserMgtException {
297         Group group = admin.createGroup(GROUP1);
298         User user = admin.createUser(USER1, PASS1, group);
299         Group group2 = new Group(GROUP2);
300
301         try {
302             admin.addUserToGroup(user, group2);
303         } catch (UserMgtException e) {
304             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
305
306             return;
307         }
308
309         fail();
310     }
311
312     /**
313      * Removes a user from a group. Verifies that the user is removed from the
314      * group using several API calls. Verifies that an exception occurs if the
315      * user not part of the group or if the user is only part of one group.
316      * 
317      */
318     public void testRemoveUserFromGroup() throws UserMgtException {
319         Group group = admin.createGroup(GROUP1);
320
321         User user = admin.createUser(USER1, PASS1, group);
322         Group group2 = admin.createGroup(GROUP2);
323         admin.addUserToGroup(user, group2);
324
325         Set<Group> groups = user.getGroups();
326         assertEquals(2, groups.size());
327         assertTrue(groups.contains(group));
328         assertTrue(groups.contains(group2));
329
330         admin.removeUserFromGroup(user, group);
331         groups = user.getGroups();
332         assertEquals(1, groups.size());
333         assertTrue(groups.contains(group2));
334         assertFalse(groups.contains(group));
335     }
336
337     /**
338      * Removes a user from a group where the user is not known. Verifies that an
339      * exception is thrown.
340      * 
341      */
342     public void testRemoveUserFromGroupUnknownUser() throws UserMgtException {
343         Group group = admin.createGroup(GROUP1);
344         User user = createUser(USER1, GROUP1, group);
345
346         try {
347             admin.removeUserFromGroup(user, group);
348         } catch (UserMgtException e) {
349             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
350         }
351     }
352
353     /**
354      * Removes a user from a group where the group is not known. Verifies that
355      * an exception is thrown.
356      * 
357      */
358     public void testRemoveUserFromGroupUnknownGroup() throws UserMgtException {
359         Group group = admin.createGroup(GROUP1);
360         User user = admin.createUser(USER1, PASS1, group);
361         Group group2 = new Group(GROUP2);
362
363         try {
364             admin.removeUserFromGroup(user, group2);
365         } catch (UserMgtException e) {
366             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
367         }
368     }
369
370     /**
371      * Removes a user from a group where the user is only part of one group.
372      * Verifies that an exception is thrown.
373      * 
374      */
375     public void testRemoveUserFromGroupOnlyGroup() throws UserMgtException {
376         Group group = admin.createGroup(GROUP1);
377         User user = admin.createUser(USER1, PASS1, group);
378
379         try {
380             admin.removeUserFromGroup(user, group);
381         } catch (UserMgtException e) {
382             assertEquals(UserMgtException.Reason.USER_MUST_BE_IN_A_GROUP, e
383                 .getReason());
384         }
385     }
386
387     /**
388      * Gets the list of users and groups. Verifies that the correct suers and
389      * groups are returned. Verifies also that the relations from user to group
390      * are correct.
391      * 
392      */
393     public void testGetUsersAndGroups() throws UserMgtException {
394         Group group1 = admin.createGroup(GROUP1);
395         Group group2 = admin.createGroup(GROUP2);
396
397         User user1 = admin.createUser(USER1, PASS1, group1);
398         admin.addUserToGroup(user1, group2);
399
400         User user2 = admin.createUser(USER2, PASS2, group2);
401
402         Set<User> users = admin.getUsers();
403         assertEquals(2, users.size());
404         assertTrue(users.contains(user1));
405         assertTrue(users.contains(user2));
406
407         Set<Group> groups = admin.getGroups();
408         assertEquals(2, groups.size());
409         assertTrue(groups.contains(group1));
410         assertTrue(groups.contains(group2));
411
412         assertTrue(user1.isInGroup(group1));
413         assertTrue(user1.isInGroup(group2));
414         assertFalse(user2.isInGroup(group1));
415         assertTrue(user2.isInGroup(group2));
416
417         Set<Group> groups1 = user1.getGroups();
418         assertEquals(2, groups1.size());
419
420         Set<Group> groups2 = user2.getGroups();
421         assertEquals(1, groups2.size());
422     }
423
424     /**
425      * Renames a user. Verifies that the user is renamed. Verifies that
426      * exceptions are thrown when an attempt is made to rename the user to
427      * itself or to another existing user, or when the group does not exist.
428      * 
429      */
430     public void testRenameUser() throws UserMgtException {
431         Group group = admin.createGroup(GROUP1);
432         User user1 = admin.createUser(USER1, PASS1, group);
433         admin.renameUser(user1, USER2);
434         assertEquals(USER2, user1.getName());
435         assertEquals(user1, admin.getUser(USER2));
436
437         admin.createUser(USER1, PASS1, group);
438
439         try {
440             admin.renameUser(user1, USER1);
441         } catch (UserMgtException e) {
442             assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason());
443
444             // do a trivial reanem
445             try {
446                 admin.renameUser(user1, user1.getName());
447             } catch (UserMgtException e2) {
448                 assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2
449                     .getReason());
450
451                 return;
452             }
453
454             fail();
455         }
456
457         fail();
458     }
459
460     /**
461      * Renames a user to a user with an invalid username. Verifies that the
462      * appropriate exception is thrown.
463      * 
464      */
465     public void testRenameUserInvalidUsername() throws UserMgtException {
466         Group group = admin.createGroup(GROUP1);
467         User user1 = admin.createUser(USER1, PASS1, group);
468
469         try {
470             admin.renameUser(user1, USER2);
471         } catch (UserMgtException e) {
472             assertEquals(e.getReason(), Reason.INVALID_USERNAME);
473         }
474     }
475
476     /**
477      * Renames a group. Verifies that the group is renamed. Verifies that
478      * exceptions are thrown when an attempt is made to rename the group to
479      * itself or to another existing group or when the group does not exist.
480      * 
481      */
482     public void testRenameGroup() throws UserMgtException {
483         Group group = admin.createGroup(GROUP1);
484         admin.renameGroup(group, GROUP2);
485         assertEquals(GROUP2, group.getName());
486         assertEquals(group, admin.getGroup(GROUP2));
487
488         admin.createGroup(GROUP1);
489
490         try {
491             admin.renameGroup(group, GROUP1);
492         } catch (UserMgtException e) {
493             assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason());
494
495             // do a trivial reanem
496             try {
497                 admin.renameGroup(group, group.getName());
498             } catch (UserMgtException e2) {
499                 assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2
500                     .getReason());
501
502                 return;
503             }
504
505             fail();
506
507             return;
508         }
509
510         fail();
511     }
512
513     /**
514      * Renames a group to a group with an invalid name. Verifies that the
515      * appropriate exception is thrown.
516      * 
517      */
518     public void testRenameGroupInvalidGroupname() throws UserMgtException {
519         Group group = admin.createGroup(GROUP1);
520
521         try {
522             admin.renameGroup(group, "a b");
523         } catch (UserMgtException e) {
524             assertEquals(e.getReason(), Reason.INVALID_GROUPNAME);
525         }
526     }
527
528     /**
529      * Removes a user. Verifies that the user is removed. Verifies that the an
530      * exception is thrown when the user does not exist.
531      * 
532      */
533     public void testRemoveUser() throws UserMgtException {
534         Group group = admin.createGroup(GROUP1);
535         User user = admin.createUser(USER1, PASS1, group);
536
537         assertEquals(1, admin.getUserCount());
538         admin.removeUser(user);
539         assertEquals(0, admin.getUserCount());
540
541         admin.createUser(USER1, PASS1, group);
542         assertEquals(1, admin.getUserCount());
543
544         User user2 = createUser(USER2, PASS2, group);
545
546         try {
547             admin.removeUser(user2);
548         } catch (UserMgtException e) {
549             assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason());
550         }
551     }
552
553     /**
554      * Removes a group. Verifies that the group is removed. Verifies that the an
555      * exception is thrown when the group does not exist or if there are still
556      * users in the group.
557      * 
558      */
559     public void testRemoveGroup() throws UserMgtException {
560         Group group1 = admin.createGroup(GROUP1);
561         assertEquals(1, admin.getGroupCount());
562         admin.removeGroup(group1);
563         assertEquals(0, admin.getGroupCount());
564         group1 = admin.createGroup(GROUP1);
565
566         admin.createUser(USER1, PASS1, group1);
567
568         try {
569             admin.removeGroup(group1);
570         } catch (UserMgtException e) {
571             assertEquals(UserMgtException.Reason.GROUP_STILL_OCCUPIED, e
572                 .getReason());
573
574             return;
575         }
576
577         fail();
578     }
579
580     /**
581      * Tries to remove an unknown group. Verifies that an exception is thrown.
582      * 
583      */
584     public void testRemoveGroupUnknownGroup() throws UserMgtException {
585         Group group = admin.createGroup(GROUP1);
586         Group group2 = new Group(GROUP2);
587
588         try {
589             admin.removeGroup(group2);
590         } catch (UserMgtException e) {
591             assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason());
592         }
593     }
594
595     /**
596      * Changes the password, verifies that this succeeds.
597      * 
598      * @throws UserMgtException
599      */
600     public void testChangePassword() throws UserMgtException {
601         Group group = admin.createGroup(GROUP1);
602         User user = admin.createUser(USER1, PASS1, group);
603         user.changePassword(PASS1, PASS2);
604
605         // retrieve the user and verifies the password hasn't changed.
606         User user2 = admin.getUser(USER1);
607
608         try {
609             user2.checkPassword(PASS2);
610             fail(); // password should not have changed already.
611         } catch (UserMgtException e) {
612             // ok.
613         }
614
615         // now notify the admin of the change in the user
616         admin.userModified(user);
617
618         user2 = admin.getUser(USER1);
619         user2.checkPassword(PASS2); // this time it should succeed.
620     }
621
622     /**
623      * Performance test. Finds a user by name.
624      * 
625      */
626     public void testPerformanceFindUserByName() throws UserMgtException {
627         Group group = admin.createGroup(GROUP1);
628         admin.createUser(USER1, PASS1, group);
629
630         int n = 1000;
631         long time = System.currentTimeMillis();
632
633         for (int i = 0; i < n; i++) {
634             admin.getUser(USER1);
635         }
636
637         LOGGER.info("Looked up a user " + n + " times in " +
638             ((float) (System.currentTimeMillis() - time) / 1000.0));
639     }
640 }