import "copyrightAndOthers.stg"
import "primitiveEquals.stg"
import "primitiveHashCode.stg"
import "primitiveLiteral.stg"

isTest() ::= "true"

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

fileName(primitive) ::= "AbstractMutable<primitive.name>BagTestCase"

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

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

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

import java.util.NoSuchElementException;

import org.eclipse.collections.api.bag.MutableBag;
import org.eclipse.collections.api.bag.primitive.Immutable<name>Bag;
import org.eclipse.collections.api.bag.primitive.Mutable<name>Bag;
import org.eclipse.collections.api.iterator.<name>Iterator;
import org.eclipse.collections.api.iterator.Mutable<name>Iterator;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.tuple.primitive.<name>IntPair;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
import org.eclipse.collections.impl.bag.mutable.HashBag;
import org.eclipse.collections.impl.block.factory.primitive.<name>Predicates;
import org.eclipse.collections.impl.collection.mutable.primitive.AbstractMutable<name>CollectionTestCase;
import org.eclipse.collections.impl.list.mutable.primitive.<name>ArrayList;
import org.eclipse.collections.impl.test.Verify;
import org.junit.Assert;
import org.junit.Test;
import org.eclipse.collections.impl.factory.primitive.<name>Sets;
import org.eclipse.collections.api.set.primitive.Mutable<name>Set;

/**
 * JUnit test for {@link Mutable<name>Bag}.
 * This file was automatically generated from template file abstractMutablePrimitiveBagTestCase.stg.
 */
public abstract class AbstractMutable<name>BagTestCase extends AbstractMutable<name>CollectionTestCase
{
    @Override
    protected abstract Mutable<name>Bag classUnderTest();

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

    @Override
    protected Mutable<name>Bag newMutableCollectionWith(<type>... elements)
    {
        return <name>HashBag.newBagWith(elements);
    }

    @Override
    protected MutableBag\<<wrapperName>\> newObjectCollectionWith(<wrapperName>... elements)
    {
        return HashBag.newBagWith(elements);
    }

    @Test
    public void sizeDistinct()
    {
        Assert.assertEquals(0L, this.newWith().sizeDistinct());
        Assert.assertEquals(3L, this.newWith(<["0", "1", "2"]:(literal.(type))(); separator=", ">).sizeDistinct());
        Assert.assertEquals(3L, this.newWith(<["0", "1", "1", "2", "2", "2"]:(literal.(type))(); separator=", ">).sizeDistinct());
    }

    @Test
    public void selectByOccurrences()
    {
        Mutable<name>Bag bag = this.newWith(<["100", "100", "100", "50", "50"]:(literal.(type))(); separator=", ">);
        Mutable<name>Bag filtered = bag.selectByOccurrences(i -> i > 2);
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100"]:(literal.(type))(); separator=", ">), filtered);
    }

    @Test
    public void selectDuplicates()
    {
        Mutable<name>Bag bag = this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        Assert.assertEquals(<name>HashBag.newBagWith(<["2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">), bag.selectDuplicates());
    }

    @Test
    public void selectUnique()
    {
        Mutable<name>Bag bag = this.newWith(<["1", "2", "2", "3", "3", "3", "3", "4", "5", "5", "6"]:(literal.(type))(); separator=", ">);
        Mutable<name>Set expected = <name>Sets.mutable.with(<["1", "4", "6"]:(literal.(type))(); separator=", ">);
        Mutable<name>Set actual = bag.selectUnique();
        Assert.assertEquals(expected, actual);
    }

    protected Mutable<name>Bag newWithOccurrences(<name>IntPair... elementsWithOccurrences)
    {
        Mutable<name>Bag bag = this.newWith();
        for (int i = 0; i \< elementsWithOccurrences.length; i++)
        {
            <name>IntPair itemToAdd = elementsWithOccurrences[i];
            bag.addOccurrences(itemToAdd.getOne(), itemToAdd.getTwo());
        }
        return bag;
    }

    @Test
    public void topOccurrences()
    {
        Mutable<name>Bag bag = this.newWithOccurrences(
                PrimitiveTuples.pair(<(literal.(type))("1")>, 1),
                PrimitiveTuples.pair(<(literal.(type))("2")>, 2),
                PrimitiveTuples.pair(<(literal.(type))("3")>, 3),
                PrimitiveTuples.pair(<(literal.(type))("4")>, 4),
                PrimitiveTuples.pair(<(literal.(type))("5")>, 5),
                PrimitiveTuples.pair(<(literal.(type))("6")>, 6),
                PrimitiveTuples.pair(<(literal.(type))("7")>, 7),
                PrimitiveTuples.pair(<(literal.(type))("8")>, 8),
                PrimitiveTuples.pair(<(literal.(type))("9")>, 9),
                PrimitiveTuples.pair(<(literal.(type))("10")>, 10));
        MutableList\<<name>IntPair> top5 = bag.topOccurrences(5);
        Verify.assertSize(5, top5);
        Assert.assertEquals(10, top5.getFirst().getTwo());
        Assert.assertEquals(6, top5.getLast().getTwo());
        Verify.assertSize(0, this.newWith(<(literal.(type))("1")>).topOccurrences(0));
        Verify.assertSize(0, this.newWith().topOccurrences(5));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).topOccurrences(5));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).topOccurrences(1));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).topOccurrences(2));
        Verify.assertSize(3, this.newWith(<["1", "1", "2", "3"]:(literal.(type))(); separator=", ">).topOccurrences(2));
        Verify.assertSize(2, this.newWith(<["1", "1", "2", "2", "3"]:(literal.(type))(); separator=", ">).topOccurrences(1));
        Verify.assertSize(3, this.newWith(<["1", "1", "2", "2", "3", "3"]:(literal.(type))(); separator=", ">).topOccurrences(1));
        Verify.assertSize(0, this.newWith().topOccurrences(0));
        Assert.assertThrows(IllegalArgumentException.class, () -> this.newWith().topOccurrences(-1));
    }

    @Test
    public void bottomOccurrences()
    {
        Mutable<name>Bag bag = this.newWithOccurrences(
                PrimitiveTuples.pair(<(literal.(type))("1")>, 1),
                PrimitiveTuples.pair(<(literal.(type))("2")>, 2),
                PrimitiveTuples.pair(<(literal.(type))("3")>, 3),
                PrimitiveTuples.pair(<(literal.(type))("4")>, 4),
                PrimitiveTuples.pair(<(literal.(type))("5")>, 5),
                PrimitiveTuples.pair(<(literal.(type))("6")>, 6),
                PrimitiveTuples.pair(<(literal.(type))("7")>, 7),
                PrimitiveTuples.pair(<(literal.(type))("8")>, 8),
                PrimitiveTuples.pair(<(literal.(type))("9")>, 9),
                PrimitiveTuples.pair(<(literal.(type))("10")>, 10));
        MutableList\<<name>IntPair> bottom5 = bag.bottomOccurrences(5);
        Verify.assertSize(5, bottom5);
        Assert.assertEquals(1, bottom5.getFirst().getTwo());
        Assert.assertEquals(5, bottom5.getLast().getTwo());
        Verify.assertSize(0, this.newWith(<(literal.(type))("1")>).bottomOccurrences(0));
        Verify.assertSize(0, this.newWith().bottomOccurrences(5));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(5));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(1));
        Verify.assertSize(3, this.newWith(<["1", "2", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(2));
        Verify.assertSize(2, this.newWith(<["1", "1", "2", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(2));
        Verify.assertSize(3, this.newWith(<["1", "1", "2", "2", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(2));
        Verify.assertSize(3, this.newWith(<["1", "1", "2", "2", "3", "3"]:(literal.(type))(); separator=", ">).bottomOccurrences(1));
        Verify.assertSize(0, this.newWith().bottomOccurrences(0));
        Assert.assertThrows(IllegalArgumentException.class, () -> this.newWith().bottomOccurrences(-1));
    }

    @Test
    public void addOccurrences()
    {
        Mutable<name>Bag bag = this.newWith();
        bag.addOccurrences(<(literal.(type))("100")>, 3);
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100"]:(literal.(type))(); separator=", ">), bag);
        bag.addOccurrences(<(literal.(type))("100")>, 2);
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100", "100", "100"]:(literal.(type))(); separator=", ">), bag);
        bag.addOccurrences(<(literal.(type))("100")>, 0);
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100", "100", "100"]:(literal.(type))(); separator=", ">), bag);
    }

    @Test(expected = IllegalArgumentException.class)
    public void addOccurrences_throws()
    {
        this.newWith().addOccurrences(<(literal.(type))("100")>, -1);
    }

    @Test
    public void removeOccurrences()
    {
        Mutable<name>Bag bag = this.newWith();
        Assert.assertFalse(bag.removeOccurrences(<(literal.(type))("100")>, 2));
        bag.addOccurrences(<(literal.(type))("100")>, 5);
        Assert.assertTrue(bag.removeOccurrences(<(literal.(type))("100")>, 2));
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100"]:(literal.(type))(); separator=", ">), bag);
        Assert.assertFalse(bag.removeOccurrences(<(literal.(type))("100")>, 0));
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100", "100"]:(literal.(type))(); separator=", ">), bag);
        Assert.assertTrue(bag.removeOccurrences(<(literal.(type))("100")>, 5));
        Assert.assertEquals(new <name>HashBag(), bag);
        Assert.assertFalse(bag.removeOccurrences(<(literal.(type))("100")>, 5));
        Assert.assertEquals(new <name>HashBag(), bag);
    }

    @Test(expected = IllegalArgumentException.class)
    public void removeOccurrences_throws()
    {
        this.newWith().removeOccurrences(<(literal.(type))("100")>, -1);
    }

    @Test
    public void forEachWithOccurrences()
    {
        StringBuilder stringBuilder = new StringBuilder();
        this.newWith(<["1", "1", "2"]:(literal.(type))(); separator=", ">).forEachWithOccurrences((<type> argument1, int argument2) -> stringBuilder.append(argument1).append(argument2));
        String string = stringBuilder.toString();
        Assert.assertTrue("<(toStringLiteral.(type))("1")>2<(toStringLiteral.(type))("2")>1".equals(string)
                || "<(toStringLiteral.(type))("2")>1<(toStringLiteral.(type))("1")>2".equals(string));
    }

    @Test
    @Override
    public void add()
    {
        super.add();
        Mutable<name>Bag bag = this.newWith();
        Assert.assertTrue(bag.add(<(literal.(type))("100")>));
        Assert.assertEquals(<name>HashBag.newBagWith(<(literal.(type))("100")>), bag);
        Assert.assertTrue(bag.add(<(literal.(type))("100")>));
        Assert.assertEquals(<name>HashBag.newBagWith(<["100", "100"]:(literal.(type))(); separator=", ">), bag);
    }

    @Test
    @Override
    public void addAllIterable()
    {
        super.addAllIterable();
        Mutable<name>Bag bag = this.newWith();
        Assert.assertTrue(bag.addAll(<name>ArrayList.newListWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">)));
        Assert.assertFalse(bag.addAll(new <name>ArrayList()));
        Assert.assertEquals(<name>HashBag.newBagWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">), bag);
        Assert.assertTrue(bag.addAll(<name>HashBag.newBagWith(<["4", "4", "4", "4"]:(literal.(type))(); separator=", ">)));
        Assert.assertEquals(<name>HashBag.newBagWith(<["1", "2", "2", "3", "3", "3", "4", "4", "4", "4"]:(literal.(type))(); separator=", ">), bag);
    }

    @Test
    @Override
    public void remove()
    {
        super.remove();
        Mutable<name>Bag bag = this.newWith();
        Assert.assertFalse(bag.remove(<(literal.(type))("100")>));
        Verify.assertSize(0, bag);
        Assert.assertEquals(new <name>HashBag(), bag);
        Assert.assertTrue(bag.add(<(literal.(type))("100")>));
        Verify.assertSize(1, bag);
        Assert.assertTrue(bag.add(<(literal.(type))("100")>));
        Verify.assertSize(2, bag);
        Assert.assertTrue(bag.remove(<(literal.(type))("100")>));
        Verify.assertSize(1, bag);
        Assert.assertEquals(<name>HashBag.newBagWith(<(literal.(type))("100")>), bag);
        Assert.assertTrue(bag.remove(<(literal.(type))("100")>));
        Verify.assertSize(0, bag);
        Assert.assertEquals(new <name>HashBag(), bag);
    }

    @Test
    @Override
    public void <type>Iterator()
    {
        Mutable<name>Bag bag = this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        <name>ArrayList list = <name>ArrayList.newListWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        <name>Iterator iterator = bag.<type>Iterator();
        for (int i = 0; i \< 6; i++)
        {
            Assert.assertTrue(iterator.hasNext());
            Assert.assertTrue(list.remove(iterator.next()));
        }
        Verify.assertEmpty(list);
        Assert.assertFalse(iterator.hasNext());

        Assert.assertThrows(NoSuchElementException.class, iterator::next);
    }

    @Override
    @Test
    public void <type>Iterator_with_remove()
    {
        super.<type>Iterator_with_remove();

        Mutable<name>Bag bag = this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        Mutable<name>Iterator iterator = bag.<type>Iterator();
        for (int i = 0; i \< 6; i++)
        {
            Assert.assertTrue(iterator.hasNext());
            iterator.next();
            iterator.remove();
        }

        Verify.assertEmpty(bag);
        Assert.assertThrows(NoSuchElementException.class, iterator::next);
    }

    @Test
    @Override
    public void forEach()
    {
        super.forEach();
        <wideType.(type)>[] sum = new <wideType.(type)>[1];
        this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">).forEach((<type> each) -> sum[0] += each);

        Assert.assertEquals(14L, sum[0]<(delta.(type))>);
    }

    @Test
    @Override
    public void count()
    {
        super.count();
        Mutable<name>Bag bag = this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">);
        Assert.assertEquals(5L, bag.count(<name>Predicates.greaterThan(<(literal.(type))("1")>)));
        Assert.assertEquals(1L, bag.count(<name>Predicates.lessThan(<(literal.(type))("2")>)));
        Assert.assertEquals(0L, bag.count(<name>Predicates.greaterThan(<(literal.(type))("4")>)));
    }

    @Test
    @Override
    public void sum()
    {
        super.sum();
        Assert.assertEquals(<(wideLiteral.(type))("14")>, this.newWith(<["1", "2", "2", "3", "3", "3"]:(literal.(type))(); separator=", ">).sum()<wideDelta.(type)>);
    }

    @Test
    @Override
    public void testEquals()
    {
        super.testEquals();
        Mutable<name>Bag bag1 = this.newWith(<["0", "1", "1", "2", "2", "2"]:(literal.(type))(); separator=", ">);
        Mutable<name>Bag bag2 = this.newWith(<["0", "2", "1", "2", "1", "2"]:(literal.(type))(); separator=", ">);
        Mutable<name>Bag bag3 = this.newWith(<["0", "1", "2", "2", "2"]:(literal.(type))(); separator=", ">);
        Verify.assertEqualsAndHashCode(bag1, bag2);
        Assert.assertNotEquals(bag1, bag3);
        Assert.assertNotEquals(bag2, bag3);
    }

    @Test
    @Override
    public void testToString()
    {
        super.testToString();
        Assert.assertEquals("[<["1", "1", "1"]:(toStringLiteral.(type))(); separator=", ">]", this.newWith(<["1", "1", "1"]:(literal.(type))(); separator=", ">).toString());
    }

    @Test
    @Override
    public void makeString()
    {
        super.makeString();
        Assert.assertEquals("<["1", "1", "1"]:(toStringLiteral.(type))(); separator=", ">", this.newWith(<["1", "1", "1"]:(literal.(type))(); separator=", ">).makeString());
    }

    @Test
    @Override
    public void appendString()
    {
        super.appendString();
        StringBuilder appendable1 = new StringBuilder();
        this.newWith(<["1", "1", "1"]:(literal.(type))(); separator=", ">).appendString(appendable1);
        Assert.assertEquals("<["1", "1", "1"]:(toStringLiteral.(type))(); separator=", ">", appendable1.toString());
    }

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

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

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

    @Test
    public void toStringOfItemToCount()
    {
        Mutable<name>Bag empty = this.newWith();
        Assert.assertEquals("{}", empty.toStringOfItemToCount());
        Assert.assertEquals("{" + <(literal.(type))("100")> + "=3}", this.newWith(<["100", "100", "100"]:(literal.(type))(); separator=", ">).toStringOfItemToCount());
        String actual = this.newWith(<["100", "101", "101"]:(literal.(type))(); separator=", ">).toStringOfItemToCount();
        Assert.assertTrue(("{" + <(literal.(type))("100")> + "=1, " + <(literal.(type))("101")> + "=2}").equals(actual) || ("{" + <(literal.(type))("101")> + "=2, " + <(literal.(type))("100")> + "=1}").equals(actual));
    }
}

>>
