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

isTest() ::= "true"

skipBoolean() ::="true"

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

fileName(primitive) ::= "Abstract<primitive.name>StackTestCase"

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

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

package org.eclipse.collections.impl.stack.primitive;

import org.eclipse.collections.api.<name>Iterable;
import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.iterator.<name>Iterator;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.list.primitive.Mutable<name>List;
import org.eclipse.collections.api.stack.StackIterable;
import org.eclipse.collections.api.stack.primitive.<name>Stack;
import org.eclipse.collections.api.stack.primitive.Immutable<name>Stack;
import org.eclipse.collections.api.tuple.primitive.<name>IntPair;
import org.eclipse.collections.impl.block.factory.primitive.<name>Predicates;
import org.eclipse.collections.impl.collection.mutable.primitive.Abstract<name>IterableTestCase;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.primitive.<name>Stacks;
<if(!primitive.intPrimitive)>import org.eclipse.collections.impl.factory.primitive.<name>Lists;<endif>
import org.eclipse.collections.impl.factory.primitive.IntLists;
<if(!primitive.intPrimitive)>import org.eclipse.collections.impl.factory.primitive.<name>Sets;<endif>
import org.eclipse.collections.impl.factory.primitive.IntSets;
import org.eclipse.collections.impl.list.mutable.primitive.<name>ArrayList;
import org.eclipse.collections.impl.stack.mutable.ArrayStack;
import org.eclipse.collections.impl.stack.mutable.primitive.<name>ArrayStack;
import org.eclipse.collections.impl.test.Verify;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
import org.junit.Assert;
import org.junit.Test;

/**
 * Abstract JUnit test for {@link <name>Stack}.
 * This file was automatically generated from template file abstractPrimitiveStackTestCase.stg.
 */
public abstract class Abstract<name>StackTestCase extends Abstract<name>IterableTestCase
{
    @Override
    protected abstract <name>Stack classUnderTest();

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

    @Override
    protected <name>Stack newMutableCollectionWith(<type>... elements)
    {
        return <name>ArrayStack.newStackWith(elements);
    }

    @Override
    protected RichIterable\<<wrapperName>\> newObjectCollectionWith(<wrapperName>... elements)
    {
        return ArrayStack.newStackWith(elements);
    }

    protected abstract <name>Stack newWithTopToBottom(<type>... elements);

    @Override
    @Test
    public void <type>Iterator()
    {
        <name>Iterator iterator = this.classUnderTest().<type>Iterator();
        int size = this.classUnderTest().size();
        for (int i = 0; i \< size; i++)
        {
            Assert.assertTrue(iterator.hasNext());
            Assert.assertEquals(<(castIntToNarrowTypeWithParens.(type))("size - i")>, iterator.next()<wideDelta.(type)>);
        }
        Assert.assertFalse(iterator.hasNext());
        Assert.assertEquals(size, this.classUnderTest().<type>Iterator().next()<wideDelta.(type)>);
    }

    @Test
    public void peek()
    {
        Assert.assertEquals(this.classUnderTest().size(), this.classUnderTest().peek()<wideDelta.(type)>);
        Assert.assertEquals(<name>ArrayList.newListWith(), this.classUnderTest().peek(0));
        Assert.assertEquals(<name>ArrayList.newListWith(<(castIntToNarrowType.(type))("this.classUnderTest().size()")>, <(castIntToNarrowTypeWithParens.(type))("this.classUnderTest().size() - 1")>),
                this.classUnderTest().peek(2));
    }

    @Test
    public void peekAtIndex()
    {
        int size = this.classUnderTest().size();
        for (int i = 0; i \< size; i++)
        {
            Assert.assertEquals(<(castIntToNarrowTypeWithParens.(type))("size - i")>, this.classUnderTest().peekAt(i)<wideDelta.(type)>);
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void peek_at_index_less_than_zero_throws_exception()
    {
        this.classUnderTest().peekAt(-1);
    }

    @Test(expected = IllegalArgumentException.class)
    public void peek_at_index_greater_than_size_throws_exception()
    {
        this.classUnderTest().peekAt(this.classUnderTest().size() + 1);
    }

    @Test(expected = IllegalArgumentException.class)
    public void peek_at_index_equal_to_size_throws_exception()
    {
        this.classUnderTest().peekAt(this.classUnderTest().size());
    }

    @Override
    @Test
    public void testToString()
    {
        super.testToString();
        Assert.assertEquals(this.createExpectedString("[", ", ", "]"), this.classUnderTest().toString());
    }

    @Override
    @Test
    public void toList()
    {
        super.toList();
        <name>ArrayList list = new <name>ArrayList();
        int size = this.classUnderTest().size();
        for (int i = 0; i \< size; i++)
        {
            list.add(<(castIntToNarrowTypeWithParens.(type))("size - i")>);
        }
        Assert.assertEquals(list, this.classUnderTest().toList());
    }

    @Override
    @Test
    public void makeString()
    {
        super.makeString();
        Assert.assertEquals(this.createExpectedString("", ", ", ""), this.classUnderTest().makeString());
        Assert.assertEquals(this.createExpectedString("", "|", ""), this.classUnderTest().makeString("|"));
        Assert.assertEquals(this.createExpectedString("{", "|", "}"), this.classUnderTest().makeString("{", "|", "}"));
    }

    protected String createExpectedString(String start, String sep, String end)
    {
        StringBuilder expectedString = new StringBuilder(start);
        int size = this.classUnderTest().size();
        for (<type> each = 0; each \< size; each++)
        {
            expectedString.append(<(castFromIntWithParens.(type))("size - each")>);
            expectedString.append(<(castRealTypeToInt.(type))("each")> == size - 1 ? "" : sep);
        }
        expectedString.append(end);
        return expectedString.toString();
    }

    @Override
    @Test
    public void detectIfNone()
    {
        <name>Iterable iterable = this.classUnderTest();
        int size = iterable.size();
        Assert.assertEquals(size >= 4 ? <(wideLiteral.(type))("4")> : <(wideLiteral.(type))("0")>, iterable.detectIfNone(<name>Predicates.equal(<(literal.(type))("4")>), <(literal.(type))("0")>)<wideDelta.(type)>);
        Assert.assertEquals(size >= 2 ? <(wideLiteral.(type))("2")> : <(wideLiteral.(type))("0")>, iterable.detectIfNone(<name>Predicates.equal(<(literal.(type))("2")>), <(literal.(type))("0")>)<wideDelta.(type)>);
        Assert.assertEquals(size > 0 ? <(wideLiteral.(type))("3")> : <(wideLiteral.(type))("0")>, iterable.detectIfNone(<name>Predicates.lessThan(<(literal.(type))("4")>), <(literal.(type))("0")>)<wideDelta.(type)>);
        Assert.assertEquals(size > 3 ? <(wideLiteral.(type))("4")> : <(wideLiteral.(type))("0")>, iterable.detectIfNone(<name>Predicates.greaterThan(<(literal.(type))("3")>), <(literal.(type))("0")>)<wideDelta.(type)>);

        <name>Iterable iterable1 = this.newWith(<["0", "1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        Assert.assertEquals(<(wideLiteral.(type))("0")>, iterable1.detectIfNone(<name>Predicates.lessThan(<(literal.(type))("1")>), <(literal.(type))("4")>)<wideDelta.(type)>);
        Assert.assertEquals(<(wideLiteral.(type))("3")>, iterable1.detectIfNone(<name>Predicates.greaterThan(<(literal.(type))("2")>), <(literal.(type))("4")>)<wideDelta.(type)>);
        Assert.assertEquals(<(wideLiteral.(type))("4")>, iterable1.detectIfNone(<name>Predicates.greaterThan(<(literal.(type))("4")>), <(literal.(type))("4")>)<wideDelta.(type)>);
    }

    @Override
    @Test
    public void appendString()
    {
        super.appendString();
        StringBuilder appendable1 = new StringBuilder();
        this.classUnderTest().appendString(appendable1);
        Assert.assertEquals(this.createExpectedString("", ", ", ""), appendable1.toString());

        StringBuilder appendable2 = new StringBuilder();
        this.classUnderTest().appendString(appendable2, "|");
        Assert.assertEquals(this.createExpectedString("", "|", ""), appendable2.toString());

        StringBuilder appendable3 = new StringBuilder();
        this.classUnderTest().appendString(appendable3, "{", "|", "}");
        Assert.assertEquals(this.createExpectedString("{", "|", "}"), appendable3.toString());
    }

    @Test
    public void toImmutable()
    {
        Assert.assertEquals(this.classUnderTest(), this.classUnderTest().toImmutable());
        Verify.assertInstanceOf(Immutable<name>Stack.class, this.classUnderTest().toImmutable());
    }

    /**
     * @since 11.1.
     */
    @Test
    public void selectWithIndex()
    {
        <name>Stack stack = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">);
        <name>Stack selected = stack.selectWithIndex((value, i) -> i % 2 == 0);

        Assert.assertEquals(<name>Stacks.immutable.with(<["1", "7"]:(literal.(type))(); separator=", ">), selected);
    }

    /**
     * @since 11.1.
     */
    @Test
    public void selectWithIndexWithTarget()
    {
        <name>Stack stack = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">);
        Mutable<name>List selected = stack.selectWithIndex((value, i) -> i % 2 == 0, <name>Lists.mutable.empty());

        Assert.assertEquals(<name>Lists.immutable.with(<["7", "1"]:(literal.(type))(); separator=", ">), selected);
    }

    /**
     * @since 11.1.
     */
    @Test
    public void rejectWithIndex()
    {
        <name>Stack stack = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">);
        <name>Stack rejected = stack.rejectWithIndex((value, i) -> i % 2 == 0);

        Assert.assertEquals(<name>Stacks.mutable.with(<["3", "9"]:(literal.(type))(); separator=", ">), rejected);
    }

    /**
     * @since 11.1.
     */
    @Test
    public void rejectWithIndexWithTarget()
    {
        <name>Stack stack = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">);
        Mutable<name>List rejected = stack.rejectWithIndex((value, i) -> i % 2 == 0, <name>Lists.mutable.empty());

        Assert.assertEquals(<name>Lists.immutable.with(<["9", "3"]:(literal.(type))(); separator=", ">), rejected);
    }

    /**
     * @since 9.1.
     */
    @Test
    public void collectWithIndex()
    {
        StackIterable\<<name>IntPair> pairs = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">)
                .collectWithIndex(PrimitiveTuples::pair);
        Assert.assertEquals(
                IntLists.mutable.with(0, 1, 2, 3),
                pairs.collectInt(<name>IntPair::getTwo, IntLists.mutable.empty()));
        Assert.assertEquals(
                <name>Lists.mutable.with(<["7", "9", "1", "3"]:(literal.(type))(); separator=", ">),
                pairs.collect<name>(<name>IntPair::getOne, <name>Lists.mutable.empty()));
    }

    /**
     * @since 9.1.
     */
    @Test
    public void collectWithIndexWithTarget()
    {
        MutableList\<<name>IntPair> pairs = this.newWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">)
                .collectWithIndex(PrimitiveTuples::pair, Lists.mutable.empty());
        Assert.assertEquals(
                IntLists.mutable.with(0, 1, 2, 3),
                pairs.collectInt(<name>IntPair::getTwo, IntLists.mutable.empty()));
        Assert.assertEquals(
                <name>Lists.mutable.with(<["7", "9", "1", "3"]:(literal.(type))(); separator=", ">),
                pairs.collect<name>(<name>IntPair::getOne, <name>Lists.mutable.empty()));

        Assert.assertEquals(
                IntSets.mutable.with(0, 1, 2, 3),
                pairs.collectInt(<name>IntPair::getTwo, IntSets.mutable.empty()));
        Assert.assertEquals(
                <name>Sets.mutable.with(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">),
                pairs.collect<name>(<name>IntPair::getOne, <name>Sets.mutable.empty()));
    }

    @Test
    public void chunk()
    {
        <name>Iterable iterable = this.newWith(<["5", "4", "3", "2", "1", "0"]:(literal.(type))(); separator=", ">);
        Verify.assertIterablesEqual(
                Lists.mutable.with(
                        <name>Lists.mutable.with(<["0"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["1"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["2"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["3"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["4"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(1).toSet());
        Verify.assertIterablesEqual(
                Lists.mutable.with(
                        <name>Lists.mutable.with(<["0", "1"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["2", "3"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["4", "5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(2).toSet());
        Verify.assertIterablesEqual(
                Lists.mutable.with(
                        <name>Lists.mutable.with(<["0", "1", "2"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["3", "4", "5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(3).toSet());
        Verify.assertIterablesEqual(
                Lists.mutable.with(
                        <name>Lists.mutable.with(<["0", "1", "2", "3"]:(literal.(type))(); separator=", ">),
                        <name>Lists.mutable.with(<["4", "5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(4).toSet());
        Verify.assertIterablesEqual(
                Lists.mutable.with(<name>Lists.mutable.with(<["0", "1", "2", "3", "4", "5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(6).toSet());
        Verify.assertIterablesEqual(
                Lists.mutable.with(<name>Lists.mutable.with(<["0", "1", "2", "3", "4", "5"]:(literal.(type))(); separator=", ">)).toSet(),
                iterable.chunk(7).toSet());
        Verify.assertIterablesEqual(Lists.mutable.with(), this.newWith().chunk(1));

        if (this.newWith() instanceof Immutable<name>Stack)
        {
            Verify.assertIterablesEqual(Lists.mutable.with(<name>Stacks.immutable.with(<["0"]:(literal.(type))(); separator=", ">)), this.newWith(<["0"]:(literal.(type))(); separator=", ">).chunk(1));
        }
        else
        {
            Verify.assertIterablesEqual(Lists.mutable.with(<name>Lists.mutable.with(<["0"]:(literal.(type))(); separator=", ">)), this.newWith(<["0"]:(literal.(type))(); separator=", ">).chunk(1));
        }

        Verify.assertIterablesEqual(Lists.mutable.with(), this.newWith().chunk(1));

        Assert.assertThrows(IllegalArgumentException.class, () -> iterable.chunk(0));
        Assert.assertThrows(IllegalArgumentException.class, () -> iterable.chunk(-1));
        Assert.assertThrows(IllegalArgumentException.class, () -> this.newWith(<["0"]:(literal.(type))(); separator=", ">).chunk(-1));
    }

    @Test(expected = UnsupportedOperationException.class)
    public void getFirst()
    {
        this.classUnderTest().getFirst();
    }

    @Test(expected = UnsupportedOperationException.class)
    public void indexOf()
    {
        this.classUnderTest().indexOf(<["0"]:(literal.(type))(); separator=", ">);
    }

    @Test(expected = UnsupportedOperationException.class)
    public void injectIntoWithIndex()
    {
        this.classUnderTest().injectIntoWithIndex(null, null);
    }

    @Test(expected = UnsupportedOperationException.class)
    public void forEachWithIndex()
    {
        this.classUnderTest().forEachWithIndex(null);
    }
}

>>
