/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.directory.shared.ldap.codec.message;


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Collection;
import java.util.Collections;

import org.apache.directory.junit.tools.Concurrent;
import org.apache.directory.junit.tools.ConcurrentJunitRunner;
import org.apache.directory.shared.ldap.message.Referral;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * Tests the ReferralImpl class.
 * 
 * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
 *         $Rev: 946251 $
 */
@RunWith(ConcurrentJunitRunner.class)
@Concurrent()
public class ReferralImplTest
{
    /**
     * Tests to make sure the equals method works for the same exact object.
     */
    @Test
    public void testEqualsSameObject()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        assertTrue( "equals method should work for the same object", refs.equals( refs ) );
    }


    /**
     * Tests to make sure the equals method works for two objects that are the
     * same exact copy of one another.
     */
    @Test
    public void testEqualsExactCopy()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        refs1.addLdapUrl( "ldap://blah2" );
        assertTrue( "exact copies of Referrals should be equal", refs0.equals( refs1 ) );
        assertTrue( "exact copies of Referrals should be equal", refs1.equals( refs0 ) );
    }


    /**
     * Tests to make sure the equals method works for two objects that are the
     * same exact copy of one another but there are redundant entries.
     */
    @Test
    public void testEqualsExactCopyWithRedundancy()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        refs0.addLdapUrl( "ldap://blah2" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        refs1.addLdapUrl( "ldap://blah2" );
        refs1.addLdapUrl( "ldap://blah2" );
        assertTrue( "exact copies of Referrals should be equal", refs0.equals( refs1 ) );
        assertTrue( "exact copies of Referrals should be equal", refs1.equals( refs0 ) );
    }


    /**
     * Tests to make sure to get equal hashCode for the same exact object.
     */
    @Test
    public void testHashCodeSameObject()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        assertTrue( refs.hashCode() == refs.hashCode() );
    }


    /**
     * Tests to make sure to get equal hashCode for two objects that are the
     * same exact copy of one another.
     */
    @Test
    public void testHashCodeExactCopy()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        refs1.addLdapUrl( "ldap://blah2" );
        assertTrue( refs0.hashCode() == refs1.hashCode() );
    }


    /**
     * Tests to make sure to get equal hashCode for two objects that are the
     * same exact copy of one another but there are redundant entries.
     */
    @Test
    public void testHashCodeExactCopyWithRedundancy()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        refs0.addLdapUrl( "ldap://blah2" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        refs1.addLdapUrl( "ldap://blah2" );
        refs1.addLdapUrl( "ldap://blah2" );
        assertTrue( refs0.hashCode() == refs1.hashCode() );
    }


    /**
     * Tests to make sure the equals method works for two objects that are the
     * not exact copies of one another but have the same number of URLs.
     */
    @Test
    public void testEqualsSameNumberButDifferentUrls()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        refs0.addLdapUrl( "ldap://blah3" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        refs1.addLdapUrl( "ldap://blah2" );
        refs1.addLdapUrl( "ldap://blah4" );
        assertFalse( "Referrals should not be equal", refs0.equals( refs1 ) );
        assertFalse( "Referrals should not be equal", refs1.equals( refs0 ) );
    }


    /**
     * Tests to make sure the equals method works for two objects that are the
     * not exact copies of one another and one has a subset of the urls of the
     * other.
     */
    @Test
    public void testEqualsSubset()
    {
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs0 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs0.addLdapUrl( "ldap://blah0" );
        refs0.addLdapUrl( "ldap://blah1" );
        refs0.addLdapUrl( "ldap://blah2" );
        refs0.addLdapUrl( "ldap://blah3" );
        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();
        refs1.addLdapUrl( "ldap://blah0" );
        refs1.addLdapUrl( "ldap://blah1" );
        assertFalse( "Referrals should not be equal", refs0.equals( refs1 ) );
        assertFalse( "Referrals should not be equal", refs1.equals( refs0 ) );
    }


    @Test
    public void testEqualsDifferentImpls()
    {
        Referral refs0 = new Referral()
        {
            public Collection<String> getLdapUrls()
            {
                return Collections.EMPTY_LIST;
            }


            public void addLdapUrl( String url )
            {
            }


            public void removeLdapUrl( String url )
            {
            }


            public void addLdapUrlBytes( byte[] urlBytes )
            {
            }


            public Collection<byte[]> getLdapUrlsBytes()
            {
                return null;
            }


            public int getReferralLength()
            {
                return 0;
            }


            public void setReferralLength( int referralLength )
            {
            }
        };

        org.apache.directory.shared.ldap.codec.message.ReferralImpl refs1 = new org.apache.directory.shared.ldap.codec.message.ReferralImpl();

        assertFalse( "Object.equals() in effect because we did not redefine " + " equals for the new impl above", refs0
            .equals( refs1 ) );
        assertTrue( "Empty Referrals should be equal even if they are different" + " implementation classes", refs1
            .equals( refs0 ) );
    }
}
