76e7b46f222640dde84bd4ea7ec29dc5d101da6f
[utils] / security / impl / src / test / java / org / wamblee / security / authentication / UserAdministrationImplTest.java
1 /*
2  * Copyright 2005-2010 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.security.authentication;
17
18 import junit.framework.TestCase;
19
20 import org.apache.log4j.Logger;
21 import org.junit.Test;
22
23 import org.wamblee.security.authentication.Group;
24 import org.wamblee.security.authentication.GroupSet;
25 import org.wamblee.security.authentication.InMemoryGroupSet;
26 import org.wamblee.security.authentication.InMemoryUserSet;
27 import org.wamblee.security.authentication.RegexpNameValidator;
28 import org.wamblee.security.authentication.User;
29 import org.wamblee.security.authentication.UserAdministration;
30 import org.wamblee.security.authentication.UserAdministrationImpl;
31 import org.wamblee.security.authentication.UserMgtException;
32 import org.wamblee.security.authentication.UserSet;
33 import org.wamblee.security.authentication.UserMgtException.Reason;
34 import org.wamblee.security.encryption.Md5HexMessageDigester;
35
36 import java.util.List;
37 import java.util.Set;
38
39 /**
40  * Test of user administration implementation.
41  * 
42  * @author Erik Brakkee
43  */
44 public class UserAdministrationImplTest extends TestCase {
45     private static final Logger LOGGER = Logger
46         .getLogger(UserAdministrationImplTest.class);
47
48     private static final String USER1 = "piet";
49
50     private static final String PASS1 = "passpiet";
51
52     private static final String USER2 = "kees";
53
54     private static final String PASS2 = "passkees";
55
56     private static final String GROUP1 = "cyclists";
57
58     private static final String GROUP2 = "runners";
59
60     private UserAdministration admin;
61
62     /*
63      * (non-Javadoc)
64      * 
65      * @see junit.framework.TestCase#setUp()
66      */
67     @Override
68     protected void setUp() throws Exception {
69         super.setUp();
70         admin = createAdmin();
71     }
72
73     protected UserAdministration createAdmin() {
74         UserSet users = new InMemoryUserSet(new RegexpNameValidator(
75             RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD,
76             "Password must contain at least 6 characters"),
77             new Md5HexMessageDigester());
78         GroupSet groups = new InMemoryGroupSet();
79
80         return new UserAdministrationImpl(users, groups,
81             new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
82                 Reason.INVALID_USERNAME, "Invalid user"),
83             new RegexpNameValidator(RegexpNameValidator.ID_PATTERN,
84                 Reason.INVALID_GROUPNAME, "Invalid group"));
85     }
86
87     // Construction
88
89     /**
90      * Constructs the admin, verify it contains no users and no groups.
91      */
92     public void testConstruct() {
93         assertEquals(0, admin.getUsers().size());
94         assertEquals(0, admin.getGroups().size());
95         assertEquals(0, admin.getUserCount());
96         assertEquals(0, admin.getGroupCount());
97     }
98
99     // Basic user admin:
100     // void createUser(String aUser, String aPassword);
101     // boolean checkUser(String aUser);
102     // int getUserCount();
103     // List<String> getUsers();
104     // void renameUser(String aOldUserName, String aUserName);
105     // void removeUser(String aUser);
106     public void testCreateUser() {
107         assertFalse(admin.checkUser(USER1));
108         admin.createUser(USER1, PASS1);
109         assertTrue(admin.checkUser(USER1));
110         assertEquals(1, admin.getUserCount());
111         assertTrue(admin.checkPassword(USER1, PASS1));
112         assertFalse(admin.checkPassword(USER1, PASS2));
113     }
114
115     public void testCreateDuplicateUser() {
116         admin.createUser(USER1, PASS1);
117
118         try {
119             admin.createUser(USER1, PASS2);
120             fail();
121         } catch (UserMgtException e) {
122             assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason());
123             assertEquals(1, admin.getUserCount());
124         }
125     }
126
127     /**
128      * Constructs users with invalid names. Verifies that the appropriate
129      * exception is thrown.
130      * 
131      */
132     public void testCreateInvalidUserName() throws UserMgtException {
133         createInvalidUser("");
134         createInvalidUser("0abc"); // should not start with digits
135         createInvalidUser("a b"); // should not contain spaces
136         createInvalidUser(" aa");
137         createInvalidUser("aa ");
138     }
139
140     public void testRenameUser() {
141         admin.createUser(USER1, PASS1);
142         admin.renameUser(USER1, USER2);
143         List<String> users = admin.getUsers();
144         assertEquals(1, users.size());
145         assertTrue(users.contains(USER2));
146     }
147
148     public void testRenameUserInvalidUsername() {
149         admin.createUser(USER1, PASS1);
150         try {
151             admin.renameUser(USER1, "a b");
152             fail();
153         } catch (UserMgtException e) {
154             assertEquals(e.getReason(), Reason.INVALID_USERNAME);
155         }
156     }
157
158     public void testRenameUserToItself() {
159         admin.createUser(USER1, PASS1);
160         admin.renameUser(USER1, USER1);
161         assertTrue(admin.checkUser(USER1));
162     }
163
164     public void testRenameUserDuplicateUser() {
165         admin.createUser(USER1, PASS1);
166         admin.createUser(USER2, PASS2);
167         try {
168             admin.renameUser(USER1, USER2);
169             fail();
170         } catch (UserMgtException e) {
171             assertEquals(e.getReason(), Reason.DUPLICATE_USER);
172         }
173     }
174
175     // Basic group admin:
176     // void createGroup(String aName);
177     // boolean checkGroup(String aGroup);
178     // int getGroupCount();
179     // List<String> getGroups();
180
181     public void testCreateGroup() {
182         admin.createGroup(GROUP1);
183         List<String> groups = admin.getGroups();
184         assertEquals(1, groups.size());
185         assertEquals(1, admin.getGroupCount());
186         assertTrue(groups.contains(GROUP1));
187     }
188
189     public void testCreateGroupInvalidName() {
190         createInvalidGroup("");
191         createInvalidGroup("0abc"); // should not start with digits
192         createInvalidGroup("a b"); // should not contain spaces
193         createInvalidGroup(" aa");
194         createInvalidGroup("aa ");
195     }
196
197     public void testCreateGroupDuplicateGroup() {
198         admin.createGroup(GROUP1);
199
200         try {
201             admin.createGroup(GROUP1);
202         } catch (UserMgtException e) {
203             assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason());
204             assertEquals(1, admin.getGroupCount());
205
206             return;
207         }
208
209         fail();
210     }
211
212     // Passwords.
213     // boolean checkPassword(String aUser, String aPassword);
214     // boolean changePassword(String aUser, String aOldPassword, String
215     // aNewPassword);
216     // void setPassword(String aUser, String aPassword);
217
218     public void testChangePassword() {
219         admin.createUser(USER1, PASS1);
220         boolean changed = admin.changePassword(USER1, PASS1, PASS2);
221         assertTrue(changed);
222         assertTrue(admin.checkPassword(USER1, PASS2));
223         assertFalse(admin.checkPassword(USER1, PASS1));
224     }
225
226     public void testChangePasswordWrongPassword() {
227         admin.createUser(USER1, PASS1);
228         boolean changed = admin.changePassword(USER1, PASS2, PASS1);
229         assertFalse(changed);
230         assertFalse(admin.checkPassword(USER1, PASS2));
231         assertTrue(admin.checkPassword(USER1, PASS1));
232     }
233
234     public void testChangePasswordUnknownUser() {
235         admin.createUser(USER1, PASS1);
236         try {
237             boolean changed = admin.changePassword(USER1 + "unknown", PASS2,
238                 PASS1);
239         } catch (UserMgtException e) {
240             assertEquals(e.getReason(), Reason.UNKNOWN_USER);
241         }
242     }
243
244     public void testSetPassword() {
245         admin.createUser(USER1, PASS1);
246         admin.setPassword(USER1, PASS2);
247         assertTrue(admin.checkPassword(USER1, PASS2));
248         assertFalse(admin.checkPassword(USER1, PASS1));
249     }
250
251     public void testSetPasswordUnknownUser() {
252         admin.createUser(USER1, PASS1);
253         try {
254             admin.setPassword(USER1 + "unknown", PASS2);
255         } catch (UserMgtException e) {
256             assertEquals(e.getReason(), Reason.UNKNOWN_USER);
257         }
258     }
259
260     // Group membership
261     // boolean isInGroup(String aUser, String aGroup);
262     // List<String> getUsers(String aGroup);
263     // void addUserToGroup(String aUser, String aGroup);
264     // void removeUserFromGroup(String aUser, String aGroup);}
265
266     public void testAddUserToGroup() {
267         admin.createUser(USER1, PASS1);
268         assertFalse(admin.isInGroup(USER1, GROUP1));
269         admin.createGroup(GROUP1);
270         admin.addUserToGroup(USER1, GROUP1);
271         assertTrue(admin.isInGroup(USER1, GROUP1));
272         List<String> users = admin.getUsers(GROUP1);
273         assertEquals(1, users.size());
274         assertTrue(users.contains(USER1));
275     }
276
277     public void testMultipleGroups() {
278         admin.createUser(USER1, PASS1);
279         admin.createGroup(GROUP1);
280         admin.createGroup(GROUP2);
281         assertFalse(admin.isInGroup(USER1, GROUP1));
282         assertFalse(admin.isInGroup(USER1, GROUP2));
283         admin.addUserToGroup(USER1, GROUP1);
284         admin.addUserToGroup(USER1, GROUP2);
285         assertTrue(admin.isInGroup(USER1, GROUP1));
286         assertTrue(admin.isInGroup(USER1, GROUP2));
287     }
288
289     public void testAddUserToGroupUnknownUser() {
290         admin.createGroup(GROUP2);
291         try {
292             admin.addUserToGroup(USER1, GROUP2);
293         } catch (UserMgtException e) {
294             assertEquals(e.getReason(), Reason.UNKNOWN_USER);
295         }
296
297     }
298
299     public void testAddUserToGroupUnknownGroup() {
300         admin.createUser(USER1, PASS1);
301         try {
302             admin.addUserToGroup(USER1, GROUP2);
303         } catch (UserMgtException e) {
304             assertEquals(e.getReason(), Reason.UNKNOWN_GROUP);
305         }
306     }
307
308     public void testRemoveUserFromGroup() {
309         admin.createUser(USER1, GROUP1);
310         admin.createGroup(GROUP1);
311         admin.addUserToGroup(USER1, GROUP1);
312         assertTrue(admin.isInGroup(USER1, GROUP1));
313         admin.removeUserFromGroup(USER1, GROUP1);
314         assertFalse(admin.isInGroup(USER1, GROUP1));
315     }
316
317     public void testRemoveUserFromGroupUserNotInGroup() {
318         admin.createUser(USER1, GROUP1);
319         admin.createGroup(GROUP1);
320         admin.createGroup(GROUP2);
321         admin.addUserToGroup(USER1, GROUP1);
322         try {
323             admin.removeUserFromGroup(USER1, GROUP2);
324             fail();
325         } catch (UserMgtException e) {
326             assertEquals(Reason.USER_NOT_IN_GROUP, e.getReason());
327         }
328     }
329
330     public void testRemoveUserFromGroupUnknowUser() {
331         admin.createGroup(GROUP1);
332         try {
333             admin.removeUserFromGroup(USER1, GROUP2);
334             fail();
335         } catch (UserMgtException e) {
336             assertEquals(Reason.UNKNOWN_USER, e.getReason());
337         }
338     }
339
340     public void testRemoveUserFromGroupUnknownGroup() {
341         admin.createUser(USER1, PASS1);
342         try {
343             admin.removeUserFromGroup(USER1, GROUP2);
344             fail();
345         } catch (UserMgtException e) {
346             assertEquals(Reason.UNKNOWN_GROUP, e.getReason());
347         }
348     }
349
350     // void renameGroup(String aOldGroup, String aGroupName)
351
352     public void testRenameGroup() {
353         admin.createUser(USER1, PASS1);
354         admin.createGroup(GROUP1);
355         admin.addUserToGroup(USER1, GROUP1);
356         admin.renameGroup(GROUP1, GROUP2);
357         List<String> groups = admin.getGroups();
358         assertEquals(1, groups.size());
359         assertTrue(groups.contains(GROUP2));
360         assertTrue(admin.isInGroup(USER1, GROUP2));
361         assertFalse(admin.isInGroup(USER1, GROUP1));
362     }
363
364     public void testRenameGroupGroupNameInvalid() {
365         admin.createGroup(GROUP1);
366         try {
367             admin.renameGroup(GROUP1, "a b");
368             fail();
369         } catch (UserMgtException e) {
370             assertEquals(Reason.INVALID_GROUPNAME, e.getReason());
371         }
372     }
373
374     public void testRenameGroupGroupAlreadyExists() {
375         admin.createGroup(GROUP1);
376         admin.createGroup(GROUP2);
377         try {
378             admin.renameGroup(GROUP1, GROUP2);
379             fail();
380         } catch (UserMgtException e) {
381             assertEquals(Reason.DUPLICATE_GROUP, e.getReason());
382         }
383     }
384
385     // void removeGroup(String aGroup);
386
387     public void testRemoveGroup() {
388         admin.createGroup(GROUP1);
389         admin.removeGroup(GROUP1);
390         List<String> groups = admin.getGroups();
391         assertEquals(0, groups.size());
392     }
393
394     public void testRemoveGroupGroupDoesNotExist() {
395         try {
396             admin.removeGroup(GROUP1);
397             fail();
398         } catch (UserMgtException e) {
399             assertEquals(e.getReason(), Reason.UNKNOWN_GROUP);
400         }
401     }
402
403     public void testRemoveGroupButStillUsersInGroup() {
404         admin.createUser(USER1, PASS1);
405         admin.createGroup(GROUP1);
406         admin.addUserToGroup(USER1, GROUP1);
407         try {
408             admin.removeGroup(GROUP1);
409         } catch (UserMgtException e) {
410             assertEquals(e.getReason(), Reason.GROUP_STILL_OCCUPIED);
411         }
412     }
413
414     private void createInvalidGroup(String aUsername) {
415         try {
416             admin.createGroup(aUsername);
417             fail();
418         } catch (UserMgtException e) {
419             assertEquals(UserMgtException.Reason.INVALID_GROUPNAME, e
420                 .getReason());
421             assertEquals(0, admin.getGroupCount());
422         }
423     }
424
425     private void createInvalidUser(String aUsername) {
426         try {
427             admin.createUser(aUsername, "pass");
428             fail();
429         } catch (UserMgtException e) {
430             assertEquals(UserMgtException.Reason.INVALID_USERNAME, e
431                 .getReason());
432             assertEquals(0, admin.getUserCount());
433         }
434     }
435
436     /**
437      * Gets the list of users and groups. Verifies that the correct suers and
438      * groups are returned. Verifies also that the relations from user to group
439      * are correct.
440      * 
441      */
442     public void testGetUsersAndGroups() throws UserMgtException {
443         admin.createGroup(GROUP1);
444         admin.createGroup(GROUP2);
445
446         admin.createUser(USER1, PASS1);
447         admin.addUserToGroup(USER1, GROUP1);
448         admin.addUserToGroup(USER1, GROUP2);
449
450         admin.createUser(USER2, PASS2);
451         admin.addUserToGroup(USER2, GROUP2);
452
453         List<String> users = admin.getUsers();
454         assertEquals(2, users.size());
455         assertTrue(users.contains(USER1));
456         assertTrue(users.contains(USER2));
457
458         List<String> groups = admin.getGroups();
459         assertEquals(2, groups.size());
460         assertTrue(groups.contains(GROUP1));
461         assertTrue(groups.contains(GROUP2));
462
463         assertTrue(admin.isInGroup(USER1, GROUP1));
464         assertTrue(admin.isInGroup(USER1, GROUP2));
465         assertFalse(admin.isInGroup(USER2, GROUP1));
466         assertTrue(admin.isInGroup(USER2, GROUP2));
467
468         List<String> groups1 = admin.getGroups(USER1);
469         assertEquals(2, groups1.size());
470
471         List<String> groups2 = admin.getGroups(USER2);
472         assertEquals(1, groups2.size());
473     }
474
475     /**
476      * Performance test. Finds a user by name.
477      * 
478      */
479     public void testPerformanceFindUserByName() throws UserMgtException {
480         admin.createGroup(GROUP1);
481         admin.createUser(USER1, PASS1);
482         admin.addUserToGroup(USER1, GROUP1);
483
484         int n = 1000;
485         long time = System.currentTimeMillis();
486
487         for (int i = 0; i < n; i++) {
488             admin.checkUser(USER1);
489         }
490
491         LOGGER.info("Looked up a user " + n + " times in " +
492             ((float) (System.currentTimeMillis() - time) / 1000.0));
493     }
494 }