import "copyright.stg"
import "primitiveHashCode.stg"
import "primitiveLiteral.stg"
import "primitiveEquals.stg"

isTest() ::= "true"

skipBoolean() ::= "true"

targetPath() ::= "org/eclipse/collections/impl/map/mutable/primitive"

fileName(primitive) ::= "Object<primitive.name>HashMapWithHashingStrategyTest"

class(primitive) ::= <<
<body(primitive.type, primitive.name, primitive.wrapperName)>
>>

body(type, name, wrapperName) ::= <<
<copyright()>

package org.eclipse.collections.impl.map.mutable.primitive;

import org.eclipse.collections.api.block.HashingStrategy;
import org.eclipse.collections.api.block.function.primitive.<name>ToObjectFunction;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.map.primitive.MutableObject<name>Map;
import org.eclipse.collections.api.map.primitive.Object<name>Map;
import org.eclipse.collections.impl.block.factory.HashingStrategies;
import org.eclipse.collections.impl.factory.primitive.Object<name>Maps;
import org.eclipse.collections.impl.list.mutable.FastList;
import org.eclipse.collections.impl.test.Verify;
import org.eclipse.collections.impl.test.domain.Person;
import org.junit.Assert;
import org.junit.Test;

/**
 * JUnit test for {@link Object<name>HashMapWithHashingStrategy}.
 * This file was automatically generated from template file objectPrimitiveHashMapWithHashingStrategyTest.stg.
 */
public class Object<name>HashMapWithHashingStrategyTest extends Object<name>HashMapTestCase
{
    private static final HashingStrategy\<String> STRING_HASHING_STRATEGY = HashingStrategies.nullSafeHashingStrategy(new HashingStrategy\<String>()
    {
        public int computeHashCode(String object)
        {
            return object.hashCode();
        }

        public boolean equals(String object1, String object2)
        {
            return object1.equals(object2);
        }
    });

    private static final HashingStrategy\<Integer> INTEGER_HASHING_STRATEGY = HashingStrategies.nullSafeHashingStrategy(new HashingStrategy\<Integer>()
    {
        public int computeHashCode(Integer object)
        {
            return object.hashCode();
        }

        public boolean equals(Integer object1, Integer object2)
        {
            return object1.equals(object2);
        }
    });

    private static final HashingStrategy\<Person> FIRST_NAME_HASHING_STRATEGY = HashingStrategies.fromFunction(Person.TO_FIRST);
    private static final HashingStrategy\<Person> LAST_NAME_HASHING_STRATEGY = HashingStrategies.fromFunction(Person.TO_LAST);
    private static final HashingStrategy\<Person> CONSTANT_HASHCODE_STRATEGY = new HashingStrategy\<Person>()
    {
        @Override
        public int computeHashCode(Person object)
        {
            return 0;
        }

        @Override
        public boolean equals(Person person1, Person person2)
        {
            return person1.getLastName().equals(person2.getLastName());
        }
    };

    private static final Person JOHNSMITH = new Person("John", "Smith");
    private static final Person JANESMITH = new Person("Jane", "Smith");
    private static final Person JOHNDOE = new Person("John", "Doe");
    private static final Person JANEDOE = new Person("Jane", "Doe");

    private final Object<name>HashMapWithHashingStrategy\<String> map = this.classUnderTest();

    @Override
    protected Object<name>HashMapWithHashingStrategy\<String> classUnderTest()
    {
        return Object<name>HashMapWithHashingStrategy.newWithKeysValues(STRING_HASHING_STRATEGY, <["0", "1", "2"]:keyValue(); separator=", ">);
    }

    @Override
    protected \<T> Object<name>HashMapWithHashingStrategy\<T> newWithKeysValues(T key1, <type> value1)
    {
        return Object<name>HashMapWithHashingStrategy.newWithKeysValues(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.\<T>defaultStrategy()), key1, value1);
    }

    @Override
    protected \<T> Object<name>HashMapWithHashingStrategy\<T> newWithKeysValues(T key1, <type> value1, T key2, <type> value2)
    {
        return Object<name>HashMapWithHashingStrategy.newWithKeysValues(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.\<T>defaultStrategy()), key1, value1, key2, value2);
    }

    @Override
    protected \<T> Object<name>HashMapWithHashingStrategy\<T> newWithKeysValues(T key1, <type> value1, T key2, <type> value2, T key3, <type> value3)
    {
        return Object<name>HashMapWithHashingStrategy.newWithKeysValues(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.\<T>defaultStrategy()), key1, value1, key2, value2, key3, value3);
    }

    @Override
    protected \<T> Object<name>HashMapWithHashingStrategy\<T> newWithKeysValues(T key1, <type> value1, T key2, <type> value2, T key3, <type> value3, T key4, <type> value4)
    {
        return Object<name>HashMapWithHashingStrategy.newWithKeysValues(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.\<T>defaultStrategy()), key1, value1, key2, value2, key3, value3, key4, value4);
    }

    @Override
    protected \<T> Object<name>HashMapWithHashingStrategy\<T> getEmptyMap()
    {
        return new Object<name>HashMapWithHashingStrategy\<>(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.defaultStrategy()));
    }

    @Override
    protected MutableObject<name>Map newMapWithInitialCapacity(int size)
    {
        return new Object<name>HashMapWithHashingStrategy(HashingStrategies.nullSafeHashingStrategy(HashingStrategies.defaultStrategy()), size);
    }

    @Override
    protected Class getTargetClass()
    {
        return Object<name>HashMapWithHashingStrategy.class;
    }

    @Override
    @Test
    public void select()
    {
        super.select();

        Object<name>HashMapWithHashingStrategy\<Person> map = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);
        Assert.assertEquals(Object<name>HashMap.newWithKeysValues(JOHNDOE, <(literal.(type))("2")>), map.select((argument1, argument2) -> "Doe".equals(argument1.getLastName())));
    }

    @Override
    @Test
    public void reject()
    {
        super.reject();

        Object<name>HashMapWithHashingStrategy\<Person> map = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);
        Assert.assertEquals(Object<name>HashMap.newWithKeysValues(JOHNDOE, <(literal.(type))("2")>), map.reject((argument1, argument2) -> "Smith".equals(argument1.getLastName())));
    }

    @Override
    @Test
    public void collect()
    {
        super.collect();

        Object<name>HashMapWithHashingStrategy\<Person> map = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);
        <name>ToObjectFunction f = argument1 -> (int) argument1 * 2;
        Assert.assertEquals(FastList.newListWith(4, 8), map.collect(f));
    }

    @Test
    public void contains_with_hashing_strategy()
    {
        Object<name>HashMapWithHashingStrategy\<Person> map = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);
        Assert.assertTrue(map.containsKey(JOHNDOE));
        Assert.assertTrue(map.containsValue(<(literal.(type))("2")>));
        Assert.assertTrue(map.containsKey(JOHNSMITH));
        Assert.assertTrue(map.containsValue(<(literal.(type))("4")>));
        Assert.assertTrue(map.containsKey(JANEDOE));
        Assert.assertTrue(map.containsKey(JANESMITH));

        Assert.assertFalse(map.containsValue(<(literal.(type))("1")>));
        Assert.assertFalse(map.containsValue(<(literal.(type))("3")>));
    }

    @Test
    public void remove_with_hashing_strategy()
    {
        Object<name>HashMapWithHashingStrategy\<Person> map = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);

        map.remove(JANEDOE);
        Assert.assertEquals(Object<name>HashMapWithHashingStrategy.newWithKeysValues(LAST_NAME_HASHING_STRATEGY, JOHNSMITH, <(literal.(type))("4")>), map);
        map.remove(JOHNSMITH);

        Verify.assertEmpty(map);

        MutableList\<String> collidingKeys = generateCollisions();
        Object<name>HashMapWithHashingStrategy\<String> map2 = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                STRING_HASHING_STRATEGY, collidingKeys.get(0), <(literal.(type))("0")>, collidingKeys.get(1), <(literal.(type))("1")>, collidingKeys.get(2), <(literal.(type))("2")>, collidingKeys.get(3), <(literal.(type))("3")>);
        map2.remove(collidingKeys.get(3));
        Assert.assertEquals(Object<name>HashMapWithHashingStrategy.newWithKeysValues(STRING_HASHING_STRATEGY, collidingKeys.get(0), <(literal.(type))("0")>, collidingKeys.get(1), <(literal.(type))("1")>, collidingKeys.get(2), <(literal.(type))("2")>), map2);
        map2.remove(collidingKeys.get(0));
        Assert.assertEquals(Object<name>HashMapWithHashingStrategy.newWithKeysValues(STRING_HASHING_STRATEGY, collidingKeys.get(1), <(literal.(type))("1")>, collidingKeys.get(2), <(literal.(type))("2")>), map2);
        Verify.assertSize(2, map2);

        Object<name>HashMapWithHashingStrategy\<Integer> map3 = Object<name>HashMapWithHashingStrategy.newWithKeysValues(INTEGER_HASHING_STRATEGY, 1, <(literal.(type))("1")>, null, <(literal.(type))("2")>, 3, <(literal.(type))("3")>);
        map3.remove(null);
        Assert.assertEquals(Object<name>HashMapWithHashingStrategy.newWithKeysValues(INTEGER_HASHING_STRATEGY, 1, <(literal.(type))("1")>, 3, <(literal.(type))("3")>), map3);
    }

    @Test
    public void equals_with_hashing_strategy()
    {
        Object<name>HashMapWithHashingStrategy\<Person> map1 = Object<name>HashMapWithHashingStrategy.newWithKeysValues(LAST_NAME_HASHING_STRATEGY, JOHNDOE, <(literal.(type))("1")>, JANEDOE, <(literal.(type))("1")>, JOHNSMITH, <(literal.(type))("1")>, JANESMITH, <(literal.(type))("1")>);
        Object<name>HashMapWithHashingStrategy\<Person> map2 = Object<name>HashMapWithHashingStrategy.newWithKeysValues(FIRST_NAME_HASHING_STRATEGY, JOHNDOE, <(literal.(type))("1")>, JANEDOE, <(literal.(type))("1")>, JOHNSMITH, <(literal.(type))("1")>, JANESMITH, <(literal.(type))("1")>);
        Object<name>HashMapWithHashingStrategy\<Person> mapWithConstantHashCodeStrategy = Object<name>HashMapWithHashingStrategy.newWithKeysValues(CONSTANT_HASHCODE_STRATEGY, JOHNDOE, <(literal.(type))("1")>, JANEDOE, <(literal.(type))("1")>, JOHNSMITH, <(literal.(type))("1")>, JANESMITH, <(literal.(type))("1")>);

        Assert.assertEquals(map1, map2);
        Assert.assertEquals(map2, map1);
        Assert.assertEquals(mapWithConstantHashCodeStrategy, map2);
        Assert.assertEquals(map2, mapWithConstantHashCodeStrategy);
        Assert.assertNotEquals(map1.hashCode(), map2.hashCode());
        Assert.assertNotEquals(map1.hashCode(), mapWithConstantHashCodeStrategy.hashCode());
        Assert.assertNotEquals(map2.hashCode(), mapWithConstantHashCodeStrategy.hashCode());

        Object<name>HashMapWithHashingStrategy\<Person> map3 = Object<name>HashMapWithHashingStrategy.newWithKeysValues(
                LAST_NAME_HASHING_STRATEGY,
                <allPeople()>);

        Object<name>HashMapWithHashingStrategy\<Person> map4 = Object<name>HashMapWithHashingStrategy.newMap(map3);
        Object<name>Map hashMap = Object<name>Maps.mutable.withAll(map3);

        Verify.assertEqualsAndHashCode(map3, map4);
        Assert.assertTrue(map3.equals(hashMap) && hashMap.equals(map3) && map3.hashCode() != hashMap.hashCode());

        Object<name>HashMap\<Person> objectMap = Object<name>HashMap.newWithKeysValues(
                <allPeople()>);
        Object<name>HashMapWithHashingStrategy\<Person> map5 = Object<name>HashMapWithHashingStrategy.newMap(LAST_NAME_HASHING_STRATEGY, objectMap);
        Assert.assertNotEquals(map5, objectMap);
    }

    @Test
    public void put_get_with_hashing_strategy()
    {
        Object<name>HashMapWithHashingStrategy\<String> map = this.classUnderTest();
        map.put(null, <(literal.(type))("5")>);

        //Testing getting values from no chains
        Assert.assertEquals(<(literal.(type))("1")>, map.get("1")<(wideDelta.(type))>);
        Assert.assertEquals(<(literal.(type))("2")>, map.get("2")<(wideDelta.(type))>);
        Assert.assertEquals(<(literal.(type))("5")>, map.get(null)<(wideDelta.(type))>);

        Object<name>HashMapWithHashingStrategy\<Person> map2 = Object<name>HashMapWithHashingStrategy.newMap(LAST_NAME_HASHING_STRATEGY);
        map2.put(JOHNSMITH, <(literal.(type))("1")>);
        Assert.assertEquals(<(literal.(type))("1")>, map2.get(JOHNSMITH)<(wideDelta.(type))>);
        map2.put(JANESMITH, <(literal.(type))("2")>);
        Assert.assertEquals(<(literal.(type))("2")>, map2.get(JOHNSMITH)<(wideDelta.(type))>);
    }
}

>>

keyValue(value) ::= <<
"<value>", <(literal.(type))(value)>
>>

allPeople() ::= <<
JOHNDOE, <(literal.(type))("1")>,
JANEDOE, <(literal.(type))("2")>,
JOHNSMITH, <(literal.(type))("3")>,
JANESMITH, <(literal.(type))("4")>
>>
