import junit.framework.TestCase;

/**
 * A JUnit test case class.
 * Every method starting with the word "test" will be called when running
 * the test with JUnit.
 */
public class UserAccountTest extends TestCase
{
    /**
     * Test constructor with legal password
     */
    public void testConstructorLegal()
    {
        try
        {
            UserAccount user = new UserAccount("joeUser", "12345678");
        } 
        catch (UserAccountException e)
        {
            fail("Should not throw exception");
        }        
    }
    
    /**
     * Test constructor with illegal password
     */
    public void testConstructorIllegal()
    {
        try
        {
            UserAccount user = new UserAccount("joeUser", "short");
            fail("Should throw exception");
        }
        catch (UserAccountException e)
        {
            // good, this is what we want
        }        
    }
    
    /**
     * Test the isLoggedIn method with a newly created user
     */
    public void testIsLoggedIn()
    {
        UserAccount user = new UserAccount();
        String correctCurPassword = "guestPassWord";
        
        // should be logged out
        assertFalse(user.isLoggedIn());
    }    
    
    /**
     * Test the setLoginID and getLoginID methods
     */
    public void testSetLoginID()
    {
        UserAccount user = new UserAccount();
        String newLoginID = "smith";
        
        // set the loginID
        user.setLoginID(newLoginID);
        
        // loginID should be changed
        assertEquals(newLoginID, user.getLoginID());
    }    
    
    /**
     * Test the logIn method with a newly created user
     */
    public void testLogIn1()
    {
        UserAccount user = new UserAccount();
        String correctCurPassword = "guestPassWord";
        
        try
        {
            // try to log in with the default password
            user.logIn(correctCurPassword);
            
            // should be logged in
            assertTrue(user.isLoggedIn());
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }
    }    
    
    /**
     * Test the logIn method with incorrect password
     */
    public void testLogIn2()
    {
        UserAccount user = new UserAccount();
        String incorrectCurPassword = "wrongPassWord";
        
        try
        {
            // try to log in with wrong password
            user.logIn(incorrectCurPassword);
            fail("Exception should have been thrown");
        }
        catch (UserAccountException e)
        {
            // good, this is what we want
        }
    }
    
    /**
     * Test the logOut method
     */
    public void testLogOut()
    {
        UserAccount user = new UserAccount();
        String correctCurPassword = "guestPassWord";
        
        try
        {
            // try to log in with correct password
            user.logIn(correctCurPassword);
            
            // should be logged in
            assertTrue(user.isLoggedIn());
            
            // log out
            user.logOut();
            
            // should be logged out
            assertFalse(user.isLoggedIn());
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }
    }
    
    /**
     * Test the setPassword method with
     * correct current password and
     * valid new password
     */
    public void testSetPassword1()
    {
        UserAccount user = new UserAccount();
        String newPassword = "abcdefgh";
        
        try
        {
            // reset the password
            user.setPassword("guestPassWord", newPassword);
            
            // log in with new password
            user.logIn(newPassword);
            
            // should be unlocked now
            assertTrue(user.isLoggedIn());
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }        
    }
    
    /**
     * Test the setPassword method with
     * correct current password and
     * invalid new password
     */
    public void testSetPassword2()
    {
        UserAccount user = new UserAccount();
        String invalidPassword = "short";
        
        try
        {
            // reset the password
            user.setPassword("guestPassWord", invalidPassword);
            fail("Exception should be thrown");
        }
        catch (UserAccountException e)
        {
            // good, this is what we want
        }        
        
    }
    
    /**
     * Test the setPassword method with
     * incorrect current password and
     * valid new password
     */
    public void testSetPassword3()
    {
        UserAccount user = new UserAccount();
        String incorrectCurPassword = "wrongPassWord";
        String validNewPassword = "longEnough";
        
        try
        {
            // reset the password
            user.setPassword(incorrectCurPassword, validNewPassword);
            fail("Exception should be thrown");
        }
        catch (UserAccountException e)
        {
            // good, this is what we want
        }        
    }
    
    /**
     * Test the equals method - true
     */
    public void testEqualsTrue1()
    {
        UserAccount user1 = new UserAccount();
        UserAccount user2 = new UserAccount();
        String defaultPassword = "guestPassWord";
        String aLoginID = "smith";
        String aPassword = "validPassword";
        
        try
        {
            // change loginID and password for user1
            user1.setLoginID(aLoginID);
            user1.setPassword(defaultPassword, aPassword);
            
            // change loginID and password for user2 (same as user1)
            user2.setLoginID(aLoginID);
            user2.setPassword(defaultPassword, aPassword);
            
            // they should be equal
            assertTrue(user1.equals(user2));
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }
    }
    
    /**
     * Test the equals method (different loginIDs) - false
     */
    public void testEqualsFalse1()
    {
        UserAccount user1 = new UserAccount();
        UserAccount user2 = new UserAccount();
        String defaultPassword = "guestPassWord";
        String aLoginID = "smith";
        
        // change loginID for user1
        user1.setLoginID(aLoginID);
        
        // they should not be equal
        assertFalse(user1.equals(user2));
    }
    
    /**
     * Test the equals method (different passwords) - false
     */
    public void testEqualsFalse2()
    {
        UserAccount user1 = new UserAccount();
        UserAccount user2 = new UserAccount();
        String defaultPassword = "guestPassWord";
        String aPassword = "validPassword";
        
        try
        {
            // change password for user1
            user1.setPassword(defaultPassword, aPassword);
            
            // they should not be equal
            assertFalse(user1.equals(user2));
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }
    }    
    
    /**
     * Test the setPassword method with
     * incorrect current password and
     * invalid new password
     */
    public void testSetPassword4()
    {
        UserAccount user = new UserAccount();
        String incorrectCurPassword = "wrongPassWord";
        String invalidNewPassword = "short";
        
        try
        {
            // reset the password
            user.setPassword(incorrectCurPassword, invalidNewPassword);
            fail("Exception should be thrown");
        }
        catch (UserAccountException e)
        {
            // good, this is what we want
        }        
    }
    
    /**
     * Test the equals method (one logged in, one logged out) - true
     */
    public void testEqualsTrue2()
    {
        UserAccount user1 = new UserAccount();
        UserAccount user2 = new UserAccount();
        String defaultPassword = "guestPassWord";
        String aLoginID = "smith";
        String aPassword = "validPassword";
        
        try
        {
            // change loginID and password for user1
            user1.setLoginID(aLoginID);
            user1.setPassword(defaultPassword, aPassword);
            
            // change loginID and password for user2 (same as user1)
            user2.setLoginID(aLoginID);
            user2.setPassword(defaultPassword, aPassword);
            
            // log in user1
            user1.logIn(aPassword);
            
            // they should be equal
            assertTrue(user1.equals(user2));
        }
        catch (UserAccountException e)
        {
            fail("Exception should not be thrown");
        }
    }
}
