import "copyrightAndOthers.stg"
import "primitiveLiteral.stg"

skipBoolean() ::= "true"

isTest() ::= "true"

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

fileName(primitive) ::= "AbstractImmutable<primitive.name>HashSetTestCase"

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

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

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

import java.util.NoSuchElementException;

import org.eclipse.collections.api.Lazy<name>Iterable;
import org.eclipse.collections.api.iterator.<name>Iterator;
import org.eclipse.collections.api.set.MutableSet;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.api.set.primitive.Immutable<name>Set;
import org.eclipse.collections.api.set.primitive.Mutable<name>Set;
import org.eclipse.collections.impl.bag.mutable.primitive.<name>HashBag;
import org.eclipse.collections.impl.block.factory.primitive.<name>Predicates;
import org.eclipse.collections.impl.collection.immutable.primitive.AbstractImmutable<name>CollectionTestCase;
import org.eclipse.collections.impl.list.mutable.primitive.<name>ArrayList;
import org.eclipse.collections.impl.set.mutable.UnifiedSet;
import org.eclipse.collections.impl.test.Verify;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
import org.eclipse.collections.api.tuple.primitive.<name><name>Pair;
import org.eclipse.collections.impl.factory.Sets;
import org.junit.Assert;
import org.junit.Test;

/**
 * Abstract JUnit test for {@link Immutable<name>Set}.
 * This file was automatically generated from template file abstractImmutablePrimitiveSetTestCase.stg.
 */
public abstract class AbstractImmutable<name>HashSetTestCase extends AbstractImmutable<name>CollectionTestCase
{
    @Override
    protected abstract Immutable<name>Set classUnderTest();

    @Override
    protected abstract Immutable<name>Set newWith(<type>... elements);

    @Override
    protected Mutable<name>Set newMutableCollectionWith(<type>... elements)
    {
        return <name>HashSet.newSetWith(elements);
    }

    @Override
    protected MutableSet\<<wrapperName>\> newObjectCollectionWith(<wrapperName>... elements)
    {
        return UnifiedSet.newSetWith(elements);
    }

    protected static <name>ArrayList generateCollisions()
    {
        <name>ArrayList collisions = new <name>ArrayList();
        <name>HashSet set = new <name>HashSet();
        for (<type> i = <(literal.(type))("32")>; collisions.size() \<= 10; i++)
        {
            if (set.spreadAndMask(i) == set.spreadAndMask(<(literal.(type))("32")>))
            {
                collisions.add(i);
            }
        }
        return collisions;
    }

    @Override
    @Test
    public void size()
    {
        super.size();
        Verify.assertSize(5, this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1)));
    }

    @Override
    @Test
    public void isEmpty()
    {
        super.isEmpty();
        Assert.assertFalse(this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1)).isEmpty());
    }

    @Override
    @Test
    public void notEmpty()
    {
        Assert.assertTrue(this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1)).notEmpty());
    }

    @Test
    public void freeze()
    {
        Immutable<name>Set immutable<name>Set = this.classUnderTest();
        Assert.assertSame(immutable<name>Set, immutable<name>Set.freeze());
    }

    @Test
    public void toImmutable()
    {
        Immutable<name>Set immutable<name>Set = this.classUnderTest();
        Assert.assertSame(immutable<name>Set, immutable<name>Set.toImmutable());
    }

    @Override
    @Test
    public void <type>Iterator()
    {
        MutableSet\<<wrapperName>\> expected = UnifiedSet.newSetWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        MutableSet\<<wrapperName>\> actual = UnifiedSet.newSet();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        <name>Iterator iterator = set.<type>Iterator();
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertFalse(iterator.hasNext());
        Assert.assertEquals(expected, actual);
        Assert.assertThrows(NoSuchElementException.class, iterator::next);
    }

    @Override
    @Test(expected = NoSuchElementException.class)
    public void <type>Iterator_throws()
    {
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        <name>Iterator iterator = set.<type>Iterator();
        while (iterator.hasNext())
        {
            iterator.next();
        }

        iterator.next();
    }

    @Override
    @Test
    public void forEach()
    {
        super.forEach();
        <wideType.(type)>[] sum = new <wideType.(type)>[1];
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        set.forEach((<type> each) -> sum[0] += each);

        Assert.assertEquals(32L + AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst() + AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1), sum[0]<(delta.(type))>);
    }

    @Override
    @Test
    public void count()
    {
        super.count();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Assert.assertEquals(4L, set.count(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
        Assert.assertEquals(3L, set.count(<name>Predicates.lessThan(<(literal.(type))("32")>)));
        Assert.assertEquals(1L, set.count(<name>Predicates.greaterThan(<(literal.(type))("32")>)));
    }

    @Override
    @Test
    public void select()
    {
        super.select();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Verify.assertSize(3, set.select(<name>Predicates.lessThan(<(literal.(type))("32")>)));
        Verify.assertSize(4, set.select(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
    }

    @Override
    @Test
    public void reject()
    {
        super.reject();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Verify.assertSize(1, set.reject(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
        Verify.assertSize(2, set.reject(<name>Predicates.lessThan(<(literal.(type))("32")>)));
    }

    @Override
    @Test
    public void detectIfNone()
    {
        super.detectIfNone();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Assert.assertEquals(<(literal.(type))("0")>, set.detectIfNone(<name>Predicates.lessThan(<(literal.(type))("1")>), <(literal.(type))("9")>)<(delta.(type))>);
        Assert.assertEquals(AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1), set.detectIfNone(<name>Predicates.greaterThan(AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst()), <(literal.(type))("9")>)<(delta.(type))>);
        Assert.assertEquals(<(literal.(type))("9")>, set.detectIfNone(<name>Predicates.greaterThan(AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1)), <(literal.(type))("9")>)<(delta.(type))>);
    }

    @Override
    @Test
    public void collect()
    {
        super.collect();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Assert.assertEquals(UnifiedSet.newSetWith(<["-1", "0", "30"]:(literal.(type))(); separator=", ">, <(castIntToNarrowTypeWithParens.(type))({AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst() - 1})>, <(castIntToNarrowTypeWithParens.(type))({AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1) - 1})>),
                set.collect(byteParameter -> <(castIntToNarrowTypeWithParens.(type))("byteParameter - 1")>));
    }

    @Override
    @Test
    public void toSortedArray()
    {
        super.toSortedArray();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Assert.assertArrayEquals(new <type>[]{<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1)}, set.toSortedArray()<(delta.(type))>);
    }

    @Override
    @Test
    public void testEquals()
    {
        super.testEquals();
        Immutable<name>Set set1 = this.newWith(<["1", "31", "32"]:(literal.(type))(); separator=", ">);
        Immutable<name>Set set2 = this.newWith(<["32", "31", "1"]:(literal.(type))(); separator=", ">);
        Immutable<name>Set set3 = this.newWith(<["32", "32", "31", "1"]:(literal.(type))(); separator=", ">);
        Immutable<name>Set set4 = this.newWith(<["32", "32", "31", "1", "1"]:(literal.(type))(); separator=", ">);
        Verify.assertEqualsAndHashCode(set1, set2);
        Verify.assertEqualsAndHashCode(set1, set3);
        Verify.assertEqualsAndHashCode(set1, set4);
        Verify.assertEqualsAndHashCode(set2, set3);
        Verify.assertEqualsAndHashCode(set2, set4);
    }

    @Override
    @Test
    public void testHashCode()
    {
        super.testHashCode();
        Immutable<name>Set set1 = this.newWith(<["1", "31", "32"]:(literal.(type))(); separator=", ">);
        Immutable<name>Set set2 = this.newWith(<["32", "31", "1"]:(literal.(type))(); separator=", ">);
        Assert.assertEquals(set1.hashCode(), set2.hashCode());
    }

    @Override
    @Test
    public void toBag()
    {
        Assert.assertEquals(<name>HashBag.newBagWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">), this.classUnderTest().toBag());
        Assert.assertEquals(<name>HashBag.newBagWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">), this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">).toBag());
        Assert.assertEquals(<name>HashBag.newBagWith(<["0", "1", "31", "32"]:(literal.(type))(); separator=", ">), this.newWith(<["0", "1", "31", "32"]:(literal.(type))(); separator=", ">).toBag());
    }

    @Override
    @Test
    public void asLazy()
    {
        super.asLazy();
        Immutable<name>Set set = this.newWith(<["0", "1", "31"]:(literal.(type))(); separator=", ">, AbstractImmutable<name>HashSetTestCase.generateCollisions().getFirst(), AbstractImmutable<name>HashSetTestCase.generateCollisions().get(1));
        Assert.assertEquals(set.toSet(), set.asLazy().toSet());
        Verify.assertInstanceOf(Lazy<name>Iterable.class, set.asLazy());
    }

    @Test
    public void union()
    {
        this.assertUnion(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3", "4", "5"]:(literal.(type))(); separator=", ">));

        this.assertUnion(
                this.newWith(<["1", "2", "3", "6"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3", "4", "5", "6"]:(literal.(type))(); separator=", ">));

        this.assertUnion(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5" , "6"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3", "4", "5", "6"]:(literal.(type))(); separator=", ">));

        this.assertUnion(
                this.newWith(),
                this.newWith(),
                this.newWith());

        this.assertUnion(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">));

        this.assertUnion(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">));
    }

    private void assertUnion(Immutable<name>Set set1, Immutable<name>Set set2, Immutable<name>Set expected)
    {
        Immutable<name>Set actual = set1.union(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void intersect()
    {
        this.assertIntersect(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3"]:(literal.(type))(); separator=", ">));

        this.assertIntersect(
                this.newWith(<["1", "2", "3", "6"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3"]:(literal.(type))(); separator=", ">));

        this.assertIntersect(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5" , "6"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3"]:(literal.(type))(); separator=", ">));

        this.assertIntersect(
                this.newWith(),
                this.newWith(),
                this.newWith());

        this.assertIntersect(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith());

        this.assertIntersect(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                this.newWith());
    }

    private void assertIntersect(Immutable<name>Set set1, Immutable<name>Set set2, Immutable<name>Set expected)
    {
        Immutable<name>Set actual = set1.intersect(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void difference()
    {
        this.assertDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">));

        this.assertDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith());

        this.assertDifference(
                this.newWith(),
                this.newWith(),
                this.newWith());

        this.assertDifference(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith());

        this.assertDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">));
    }

    private void assertDifference(Immutable<name>Set set1, Immutable<name>Set set2, Immutable<name>Set expected)
    {
        Immutable<name>Set actual = set1.difference(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void symmetricDifference()
    {
        this.assertSymmetricDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["2", "3", "4"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "4"]:(literal.(type))(); separator=", ">));

        this.assertSymmetricDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith());

        this.assertSymmetricDifference(
                this.newWith(),
                this.newWith(),
                this.newWith());

        this.assertSymmetricDifference(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">));

        this.assertSymmetricDifference(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">));
    }

    private void assertSymmetricDifference(Immutable<name>Set set1, Immutable<name>Set set2, Immutable<name>Set expected)
    {
        Immutable<name>Set actual = set1.symmetricDifference(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void isSubsetOf()
    {
        this.assertIsSubsetOf(
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                true);

        this.assertIsSubsetOf(
                this.newWith(<["1", "4"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                false);

        this.assertIsSubsetOf(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                true);

        this.assertIsSubsetOf(
                this.newWith(),
                this.newWith(),
                true);

        this.assertIsSubsetOf(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                true);

        this.assertIsSubsetOf(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                false);
    }

    private void assertIsSubsetOf(Immutable<name>Set set1, Immutable<name>Set set2, boolean expected)
    {
        boolean actual = set1.isSubsetOf(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void isProperSubsetOf()
    {
        this.assertIsProperSubsetOf(
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                true);

        this.assertIsProperSubsetOf(
                this.newWith(<["1", "4"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                false);

        this.assertIsProperSubsetOf(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                false);

        this.assertIsProperSubsetOf(
                this.newWith(),
                this.newWith(),
                false);

        this.assertIsProperSubsetOf(
                this.newWith(),
                this.newWith(<["3", "4", "5"]:(literal.(type))(); separator=", ">),
                true);

        this.assertIsProperSubsetOf(
                this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                false);
    }

    private void assertIsProperSubsetOf(Immutable<name>Set set1, Immutable<name>Set set2, boolean expected)
    {
        boolean actual = set1.isProperSubsetOf(set2);
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void cartesianProduct()
    {
        this.assertCartesianProduct(
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                this.newWith(<["3", "4"]:(literal.(type))(); separator=", ">),
                Sets.immutable.with(
                        PrimitiveTuples.pair(<(literal.(type))("1")>, <(literal.(type))("3")>),
                        PrimitiveTuples.pair(<(literal.(type))("1")>, <(literal.(type))("4")>),
                        PrimitiveTuples.pair(<(literal.(type))("2")>, <(literal.(type))("3")>),
                        PrimitiveTuples.pair(<(literal.(type))("2")>, <(literal.(type))("4")>)));

        this.assertCartesianProduct(
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                Sets.immutable.with(
                        PrimitiveTuples.pair(<(literal.(type))("1")>, <(literal.(type))("1")>),
                        PrimitiveTuples.pair(<(literal.(type))("1")>, <(literal.(type))("2")>),
                        PrimitiveTuples.pair(<(literal.(type))("2")>, <(literal.(type))("1")>),
                        PrimitiveTuples.pair(<(literal.(type))("2")>, <(literal.(type))("2")>)));

        this.assertCartesianProduct(
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                this.newWith(),
                Sets.immutable.empty());

        this.assertCartesianProduct(
                this.newWith(),
                this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">),
                Sets.immutable.empty());
    }

    private void assertCartesianProduct(Immutable<name>Set set1, Immutable<name>Set set2, ImmutableSet\<<name><name>Pair> expected)
    {
        ImmutableSet\<<name><name>Pair> actual = set1.cartesianProduct(set2).toSet().toImmutable();
        Assert.assertEquals(expected, actual);
    }
}

>>
