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

isTest() ::= "true"

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

fileName(primitive) ::= "Reverse<primitive.name>IterableTest"

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

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

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

import java.util.NoSuchElementException;

import org.eclipse.collections.api.<name>Iterable;
import org.eclipse.collections.api.iterator.<name>Iterator;
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.list.mutable.FastList;
<if(primitive.floatingPoint)>import org.eclipse.collections.impl.list.Interval;<endif>
import org.eclipse.collections.impl.list.mutable.primitive.<name>ArrayList;
import org.eclipse.collections.impl.set.mutable.primitive.<name>HashSet;
import org.eclipse.collections.impl.test.Verify;
import org.junit.Assert;
import org.junit.Test;

/**
 * JUnit test for {@link Reverse<name>Iterable}.
 * This file was automatically generated from template file reversePrimitiveIterableTest.stg.
 */
public class Reverse<name>IterableTest
{
    @Test
    public void isEmpty()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Verify.assertEmpty(new <name>ArrayList().asReversed());
        Verify.assertNotEmpty(iterable);
    }

    @Test
    public void contains()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertFalse(iterable.contains(<(literal.(type))("0")>));
        Assert.assertTrue(iterable.contains(<(literal.(type))("1")>));
    }

    @Test
    public void containsAllArray()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertTrue(iterable.containsAll(<(literal.(type))("1")>));
        Assert.assertTrue(iterable.containsAll(<["1", "2", "3"]:(literal.(type))(); separator=", ">));
        Assert.assertFalse(iterable.containsAll(<["1", "2", "3", "4"]:(literal.(type))(); separator=", ">));
    }

    @Test
    public void containsAllIterable()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertTrue(iterable.containsAll(<name>ArrayList.newListWith(<(literal.(type))("1")>)));
        Assert.assertTrue(iterable.containsAll(<name>ArrayList.newListWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">)));
        Assert.assertFalse(iterable.containsAll(<name>ArrayList.newListWith(<["1", "2", "3", "4"]:(literal.(type))(); separator=", ">)));
    }

    @Test
    public void iterator()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        <name>Iterator iterator = iterable.<type>Iterator();
        Assert.assertTrue(iterator.hasNext());
        Assert.assertEquals(<(wideLiteral.(type))("1")>, iterator.next()<(wideDelta.(type))>);
        Assert.assertTrue(iterator.hasNext());
        Assert.assertEquals(<(wideLiteral.(type))("2")>, iterator.next()<(wideDelta.(type))>);
        Assert.assertTrue(iterator.hasNext());
        Assert.assertEquals(<(wideLiteral.(type))("3")>, iterator.next()<(wideDelta.(type))>);
        Assert.assertFalse(iterator.hasNext());
    }

    @Test(expected = NoSuchElementException.class)
    public void iterator_throws()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        <name>Iterator iterator = iterable.<type>Iterator();
        while (iterator.hasNext())
        {
            iterator.next();
        }

        iterator.next();
    }

    @Test
    public void forEach()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        <wideType.(type)>[] sum = new <wideType.(type)>[1];
        iterable.forEach((<type> each) -> sum[0] += each);

        Assert.assertEquals(<(wideLiteral.(type))("6")>, sum[0]<(wideDelta.(type))>);
    }

    @Test
    public void size()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Verify.assertSize(0, new <name>ArrayList().asReversed());
        Verify.assertSize(3, iterable);
    }

    @Test
    public void empty()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertTrue(iterable.notEmpty());
        Verify.assertNotEmpty(iterable);
    }

    @Test
    public void count()
    {
        Assert.assertEquals(2L, <name>ArrayList.newListWith(<["1", "0", "2"]:(literal.(type))(); separator=", ">).asReversed().count(<name>Predicates.greaterThan(<zero.(type)>)));
    }

    @Test
    public void anySatisfy()
    {
        Assert.assertTrue(<name>ArrayList.newListWith(<["1", "-1", "2"]:(literal.(type))(); separator=", ">).asReversed().anySatisfy(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
        Assert.assertFalse(<name>ArrayList.newListWith(<["1", "-1", "2"]:(literal.(type))(); separator=", ">).asReversed().anySatisfy(<name>Predicates.equal(<(literal.(type))("0")>)));
    }

    @Test
    public void allSatisfy()
    {
        Assert.assertFalse(<name>ArrayList.newListWith(<["1", "0", "2"]:(literal.(type))(); separator=", ">).asReversed().allSatisfy(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
        Assert.assertTrue(<name>ArrayList.newListWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).asReversed().allSatisfy(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
    }

    @Test
    public void noneSatisfy()
    {
        Assert.assertFalse(<name>ArrayList.newListWith(<["1", "0", "2"]:(literal.(type))(); separator=", ">).asReversed().noneSatisfy(<name>Predicates.greaterThan(<(literal.(type))("0")>)));
        Assert.assertTrue(<name>ArrayList.newListWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).asReversed().noneSatisfy(<name>Predicates.greaterThan(<(literal.(type))("3")>)));
    }

    @Test
    public void select()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Verify.assertSize(3, iterable.select(<name>Predicates.lessThan(<(literal.(type))("4")>)));
        Verify.assertSize(2, iterable.select(<name>Predicates.lessThan(<(literal.(type))("3")>)));
    }

    @Test
    public void reject()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Verify.assertSize(0, iterable.reject(<name>Predicates.lessThan(<(literal.(type))("4")>)));
        Verify.assertSize(1, iterable.reject(<name>Predicates.lessThan(<(literal.(type))("3")>)));
    }

    @Test
    public void detectIfNone()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertEquals(<(wideLiteral.(type))("1")>, iterable.detectIfNone(<name>Predicates.lessThan(<(literal.(type))("4")>), <(literal.(type))("0")>)<(wideDelta.(type))>);
        Assert.assertEquals(<(wideLiteral.(type))("0")>, iterable.detectIfNone(<name>Predicates.greaterThan(<(literal.(type))("3")>), <(literal.(type))("0")>)<(wideDelta.(type))>);
    }

    @Test
    public void collect()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Verify.assertIterablesEqual(FastList.newListWith(<["0", "1", "2"]:(literal.(type))(); separator=", ">), iterable.collect((<type> parameter) -> <(castIntToNarrowTypeWithParens.(type))("parameter - 1")>));
    }

    @Test
    public void max()
    {
        Assert.assertEquals(<(wideLiteral.(type))("9")>, <name>ArrayList.newListWith(<["1", "0", "9", "7"]:(literal.(type))(); separator=", ">).asReversed().max()<(wideDelta.(type))>);
    }

    @Test(expected = NoSuchElementException.class)
    public void max_throws_emptyList()
    {
        new <name>ArrayList().asReversed().max();
    }

    @Test
    public void min()
    {
        Assert.assertEquals(<(wideLiteral.(type))("0")>, <name>ArrayList.newListWith(<["1", "0", "9", "7"]:(literal.(type))(); separator=", ">).asReversed().min()<(wideDelta.(type))>);
    }

    @Test(expected = NoSuchElementException.class)
    public void min_throws_emptyList()
    {
        new <name>ArrayList().asReversed().min();
    }

    @Test
    public void minIfEmpty()
    {
        Assert.assertEquals(<(wideLiteral.(type))("5")>, new <name>ArrayList().asReversed().minIfEmpty(<(literal.(type))("5")>)<(wideDelta.(type))>);
        Assert.assertEquals(<(wideLiteral.(type))("0")>, new <name>ArrayList().asReversed().minIfEmpty(<(literal.(type))("0")>)<(wideDelta.(type))>);
        Assert.assertEquals(<(wideLiteral.(type))("0")>, <name>ArrayList.newListWith(<["1", "0", "9", "7"]:(literal.(type))(); separator=", ">).asReversed().minIfEmpty(<(literal.(type))("5")>)<(wideDelta.(type))>);
    }

    @Test
    public void maxIfEmpty()
    {
        Assert.assertEquals(<(wideLiteral.(type))("5")>, new <name>ArrayList().asReversed().maxIfEmpty(<(literal.(type))("5")>)<(wideDelta.(type))>);
        Assert.assertEquals(<(wideLiteral.(type))("0")>, new <name>ArrayList().asReversed().maxIfEmpty(<(literal.(type))("0")>)<(wideDelta.(type))>);
        Assert.assertEquals(<(wideLiteral.(type))("9")>, <name>ArrayList.newListWith(<["1", "0", "9", "7"]:(literal.(type))(); separator=", ">).asReversed().maxIfEmpty(<(literal.(type))("5")>)<(wideDelta.(type))>);
    }

    @Test
    public void sum()
    {
        Assert.assertEquals(<(wideLiteral.(type))("10")>, <name>ArrayList.newListWith(<["1", "2", "3", "4"]:(literal.(type))(); separator=", ">).asReversed().sum()<(wideDelta.(type))>);
    }

    <if(primitive.floatPrimitive)>@Test
public void sumConsistentRounding()
{
    <name>Iterable iterable = <name>ArrayList.newListWith(Interval.oneTo(100_000)
            .toList()
            .shuffleThis()
            .collect<name>(i -> 1.0f / (i.floatValue() * i.floatValue() * i.floatValue() * i.floatValue()))
            .asReversed()
            .toArray());

    // The test only ensures the consistency/stability of rounding. This is not meant to test the "correctness" of the float calculation result.
    // Indeed the lower bits of this calculation result are always incorrect due to the information loss of original float values.
    Assert.assertEquals(
            1.082323233761663,
            iterable.sum(),
            1.0e-15);
}

    <elseif(primitive.doublePrimitive)>@Test
public void sumConsistentRounding()
{
    <name>Iterable iterable = <name>ArrayList.newListWith(Interval.oneTo(100_000)
            .toList()
            .shuffleThis()
            .collect<name>(i -> <["1.0"]:(decimalLiteral.(type))()> / (i.<type>Value() * i.<type>Value() * i.<type>Value() * i.<type>Value()))
            .asReversed()
            .toArray());

    Assert.assertEquals(
            1.082323233711138,
            iterable.sum(),
            1.0e-15);
}

    <endif>
    @Test
    public void average()
    {
        Assert.assertEquals(2.5, <name>ArrayList.newListWith(<["1", "2", "3", "4"]:(literal.(type))(); separator=", ">).asReversed().average(), 0.0);
    }

    @Test
    public void median()
    {
        Assert.assertEquals(2.5, <name>ArrayList.newListWith(<["1", "2", "3", "4"]:(literal.(type))(); separator=", ">).asReversed().median(), 0.0);
        Assert.assertEquals(3.0, <name>ArrayList.newListWith(<["1", "2", "3", "4", "5"]:(literal.(type))(); separator=", ">).asReversed().median(), 0.0);
    }

    @Test
    public void toArray()
    {
        Assert.assertArrayEquals(new <type>[]{<["3", "4", "2", "1"]:(literal.(type))(); separator=", ">}, <name>ArrayList.newListWith(<["1", "2", "4", "3"]:(literal.(type))(); separator=", ">).asReversed().toArray()<(delta.(type))>);
    }

    @Test
    public void toSortedArray()
    {
        Assert.assertArrayEquals(new <type>[]{<["1", "3", "7", "9"]:(literal.(type))(); separator=", ">}, <name>ArrayList.newListWith(<["3", "1", "9", "7"]:(literal.(type))(); separator=", ">).asReversed().toSortedArray()<(delta.(type))>);
    }

    @Test
    public void testToString()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertEquals("[<["1", "2", "3"]:(toStringLiteral.(type))(); separator=", ">]", iterable.toString());
        Assert.assertEquals("[]", new <name>ArrayList().asReversed().toString());
    }

    @Test
    public void makeString()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        Assert.assertEquals("<["1", "2", "3"]:(toStringLiteral.(type))(); separator=", ">", iterable.makeString());
        Assert.assertEquals("<(toStringLiteral.(type))("1")>", <name>ArrayList.newListWith(<(literal.(type))("1")>).makeString("/"));
        Assert.assertEquals("<["1", "2", "3"]:(toStringLiteral.(type))(); separator="/">", iterable.makeString("/"));
        Assert.assertEquals(iterable.toString(), iterable.makeString("[", ", ", "]"));
        Assert.assertEquals("", new <name>ArrayList().asReversed().makeString());
    }

    @Test
    public void appendString()
    {
        <name>Iterable iterable = <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed();
        StringBuilder appendable = new StringBuilder();
        new <name>ArrayList().asReversed().appendString(appendable);
        Assert.assertEquals("", appendable.toString());
        StringBuilder appendable2 = new StringBuilder();
        iterable.appendString(appendable2);
        Assert.assertEquals("<["1", "2", "3"]:(toStringLiteral.(type))(); separator=", ">", appendable2.toString());
        StringBuilder appendable3 = new StringBuilder();
        iterable.appendString(appendable3, "/");
        Assert.assertEquals("<["1", "2", "3"]:(toStringLiteral.(type))(); separator="/">", appendable3.toString());
        StringBuilder appendable4 = new StringBuilder();
        iterable.appendString(appendable4, "[", ", ", "]");
        Assert.assertEquals(iterable.toString(), appendable4.toString());
    }

    @Test
    public void toList()
    {
        Assert.assertEquals(<name>ArrayList.newListWith(<["2", "1"]:(literal.(type))(); separator=", ">), <name>ArrayList.newListWith(<["1", "2"]:(literal.(type))(); separator=", ">).asReversed().toList());
    }

    @Test
    public void toSet()
    {
        Assert.assertEquals(<name>HashSet.newSetWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">), <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed().toSet());
    }

    @Test
    public void toBag()
    {
        Assert.assertEquals(<name>HashBag.newBagWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">), <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed().toBag());
    }

    @Test
    public void asLazy()
    {
        Assert.assertEquals(<name>ArrayList.newListWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">), <name>ArrayList.newListWith(<["3", "2", "1"]:(literal.(type))(); separator=", ">).asReversed().asLazy().toList());
    }

    @Test
    public void toSortedList()
    {
        Assert.assertEquals(<name>ArrayList.newListWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">), <name>ArrayList.newListWith(<["2", "3", "1"]:(literal.(type))(); separator=", ">).asReversed().toSortedList());
    }
}

>>
