/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.api.db;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openmrs.User;
import org.openmrs.api.UserService;
import org.openmrs.api.context.Context;
import org.openmrs.api.context.ContextAuthenticationException;
import org.openmrs.api.db.hibernate.HibernateContextDAO;
import org.openmrs.test.BaseContextSensitiveTest;
import org.openmrs.test.Verifies;
/**
* This class tests the {@link ContextDAO} linked to from the Context. Currently that file is the
* {@link HibernateContextDAO}.<br/>
* <br/>
* So far we have thoroughly analyzed:
* <ul>
* <li>public User authenticate(String, String) on 21/Aug/2008</li>
* </ul>
*/
public class ContextDAOTest extends BaseContextSensitiveTest {
private ContextDAO dao = null;
/**
* Run this before each unit test in this class. The "@Before" method in
* {@link BaseContextSensitiveTest} is run right before this method.
*
* @throws Exception
*/
@Before
@Verifies(value = "should ", method = "authenticate(String,String)")
public void runExtraSetup() throws Exception {
executeDataSet("org/openmrs/api/db/include/contextDAOTest.xml");
if (dao == null) {
// fetch the dao from the spring application context
// this bean name matches the name in /metadata/spring/applicationContext-service.xml
dao = (ContextDAO) applicationContext.getBean("contextDAO");
}
}
/**
* Methods in this class might authenticate with a different user, so log that user out after
* this whole junit class is done.
*/
@AfterClass
public static void logOutAfterThisTest() {
Context.logout();
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should authenticateGivenUsernameAndPassword", method = "authenticate(String,String)")
public void authenticate_shouldAuthenticateGivenUsernameAndPassword() throws Exception {
User u = dao.authenticate("admin", "test");
Assert.assertEquals("Should be the admin user", "admin", u.getUsername());
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should authenticateGivenSystemIdAndPassword", method = "authenticate(String,String)")
public void authenticate_shouldAuthenticateGivenSystemIdAndPassword() throws Exception {
User u = dao.authenticate("1-8", "test");
Assert.assertEquals("Should be the 1-8 user", "1-8", u.getSystemId());
}
/**
* Fixed bug #982
*
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should authenticateGivenSystemIdWithoutHyphenAndPassword", method = "authenticate(String,String)")
public void authenticate_shouldAuthenticateGivenSystemIdWithoutHyphenAndPassword() throws Exception {
User u = dao.authenticate("18", "test");
Assert.assertEquals("Should be the 1-8 user", "1-8", u.getSystemId());
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenUsernameAndIncorrectPassword", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenUsernameAndIncorrectPassword() throws Exception {
dao.authenticate("admin", "wrong");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenSystemIdAndIncorrectPassword", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenSystemIdAndIncorrectPassword() throws Exception {
dao.authenticate("1-8", "wrong");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenIncorrectUsername", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenIncorrectUsername() throws Exception {
dao.authenticate("administrator", "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenIncorrectSystemId", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenIncorrectSystemId() throws Exception {
dao.authenticate("1-9", "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenNullLogin", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenNullLogin() throws Exception {
dao.authenticate(null, "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenEmptyLogin", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenEmptyLogin() throws Exception {
dao.authenticate("", "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateWhenPasswordInDatabaseIsNull", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateWhenPasswordInDatabaseIsNull() throws Exception {
dao.authenticate("admin", null);
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenNonNullPasswordWhenPasswordInDatabaseIsNull", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenNonNullPasswordWhenPasswordInDatabaseIsNull() throws Exception {
dao.authenticate("nullpassword", "password");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateGivenNullPasswordWhenPasswordInDatabaseIsNull", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateGivenNullPasswordWhenPasswordInDatabaseIsNull() throws Exception {
dao.authenticate("nullpassword", null);
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should notAuthenticateWhenPasswordInDatabaseIsEmpty", method = "authenticate(String,String)")
public void authenticate_shouldNotAuthenticateWhenPasswordInDatabaseIsEmpty() throws Exception {
dao.authenticate("emptypassword", "");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test()
@Verifies(value = "should giveIdenticalErrorMessagesBetweenUsernameAndPasswordMismatch", method = "authenticate(String,String)")
public void authenticate_shouldGiveIdenticalErrorMessagesBetweenUsernameAndPasswordMismatch() throws Exception {
User user = dao.authenticate("admin", "test");
Assert.assertNotNull("This test depends on there being an admin:test user", user);
String invalidUsernameErrorMessage = null;
String invalidPasswordErrorMessage = null;
try {
dao.authenticate("some invalid username", "and an invalid password");
}
catch (ContextAuthenticationException authException) {
invalidUsernameErrorMessage = authException.getMessage();
invalidUsernameErrorMessage = invalidUsernameErrorMessage.replace("some invalid username", "");
}
try {
// a valid username but an invalid password for that user
dao.authenticate("admin", "and an invalid password");
}
catch (ContextAuthenticationException authException) {
invalidPasswordErrorMessage = authException.getMessage();
invalidPasswordErrorMessage = invalidPasswordErrorMessage.replace("admin", "");
}
Assert.assertEquals(invalidUsernameErrorMessage, invalidPasswordErrorMessage);
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should lockout user after eight failed attempts", method = "authenticate(String,String)")
public void authenticate_shouldLockoutUserAfterEightFailedAttempts() throws Exception {
// logout after the base setup
Context.logout();
// we rely on being able to log in as admin/test in this unittest
// we must do the "improper" try/catch block here because the whole
// test is expected to throw and exception at the end
try {
dao.authenticate("admin", "test");
}
catch (ContextAuthenticationException authException) {
Assert.fail("There must be an admin:test user for this test to run properly");
}
Context.logout();
for (int x = 1; x <= 7; x++) {
// try to authenticate with a proper
try {
dao.authenticate("admin", "not the right password");
Assert.fail("Not sure why this username/password combo worked");
}
catch (ContextAuthenticationException authException) {
// pass
}
}
// those were the first seven, now the eigth request
// (with the same user and right pw) should fail
dao.authenticate("admin", "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should authenticateWithCorrectHashedPassword", method = "authenticate(String,String)")
public void authenticate_shouldAuthenticateWithCorrectHashedPassword() throws Exception {
dao.authenticate("correct", "test");
}
/**
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test
@Verifies(value = "should authenticateWithIncorrectHashedPassword", method = "authenticate(String,String)")
public void authenticate_shouldAuthenticateWithIncorrectHashedPassword() throws Exception {
dao.authenticate("incorrect", "test");
}
/**
* #1580: If you type your password wrong, then log in correctly, the API will not lock you out
* after multiple login attempts in the future
*
* @see {@link ContextDAO#authenticate(String,String)}
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should pass regression test for 1580", method = "authenticate(String,String)")
public void authenticate_shouldPassRegressionTestFor1580() throws Exception {
// logout after the base setup
Context.logout();
// first we fail a login attempt
try {
dao.authenticate("admin", "not the right password");
Assert.fail("Not sure why this username/password combo worked");
}
catch (ContextAuthenticationException authException) {
// pass
}
// next we log in correctly
try {
dao.authenticate("admin", "test");
}
catch (ContextAuthenticationException authException) {
Assert.fail("There must be an admin:test user for this test to run properly");
}
Context.logout();
for (int x = 1; x <= 8; x++) {
// now we fail several login attempts
try {
dao.authenticate("admin", "not the right password");
Assert.fail("Not sure why this username/password combo worked");
}
catch (ContextAuthenticationException authException) {
// pass
}
}
// those were the first eight, now the ninth request
// (with the same user and right pw) should fail
dao.authenticate("admin", "test");
}
/**
* @verifies {@link ContextDAO#authenticate(String,String)} test = should throw a
* ContextAuthenticationException if username is an empty string
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should throw a ContextAuthenticationException if username is an empty string", method = "authenticate(String,String)")
public void authenticate_shouldThrowAContextAuthenticationExceptionIfUsernameIsAnEmptyString() throws Exception {
//update a user with a username that is an empty string for this test
UserService us = Context.getUserService();
User u = us.getUser(1);
u.setUsername("");
u.getPerson().setGender("M");
us.saveUser(u, "Openmr5xy");
dao.authenticate("", "password");
}
/**
* @verifies {@link ContextDAO#authenticate(String,String)} test = should throw a
* ContextAuthenticationException if username is white space
*/
@Test(expected = ContextAuthenticationException.class)
@Verifies(value = "should throw a ContextAuthenticationException if username is white space", method = "authenticate(String,String)")
public void authenticate_shouldThrowAContextAuthenticationExceptionIfUsernameIsWhiteSpace() throws Exception {
//update a user with a username that is an empty string for this test
UserService us = Context.getUserService();
User u = us.getUser(1);
u.setUsername(" ");
u.getPerson().setGender("M");
us.saveUser(u, "Openmr5xy");
dao.authenticate(" ", "password");
}
}