/*
* Copyright 2015 Goldman Sachs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gs.collections.impl.bag.mutable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.gs.collections.api.bag.Bag;
import com.gs.collections.api.bag.ImmutableBagIterable;
import com.gs.collections.api.bag.MutableBagIterable;
import com.gs.collections.api.list.MutableList;
import com.gs.collections.api.partition.PartitionMutableCollection;
import com.gs.collections.api.tuple.primitive.ObjectIntPair;
import com.gs.collections.impl.block.factory.IntegerPredicates;
import com.gs.collections.impl.block.factory.Predicates;
import com.gs.collections.impl.block.factory.Predicates2;
import com.gs.collections.impl.block.factory.primitive.IntPredicates;
import com.gs.collections.impl.block.procedure.CollectionAddProcedure;
import com.gs.collections.impl.collection.mutable.AbstractCollectionTestCase;
import com.gs.collections.impl.factory.Bags;
import com.gs.collections.impl.factory.Iterables;
import com.gs.collections.impl.factory.Lists;
import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.map.mutable.UnifiedMap;
import com.gs.collections.impl.math.IntegerSum;
import com.gs.collections.impl.set.mutable.UnifiedSet;
import com.gs.collections.impl.test.Verify;
import com.gs.collections.impl.tuple.primitive.PrimitiveTuples;
import org.junit.Assert;
import org.junit.Test;
public abstract class MutableBagTestCase extends AbstractCollectionTestCase
{
@Override
protected abstract <T> MutableBagIterable<T> newWith(T... littleElements);
protected abstract <T> MutableBagIterable<T> newWithOccurrences(ObjectIntPair<T>... elementsWithOccurrences);
@Test
@Override
public void equalsAndHashCode()
{
super.equalsAndHashCode();
Assert.assertNotEquals(this.newWith(1, 1, 2, 3), this.newWith(1, 2, 2, 3));
Verify.assertEqualsAndHashCode(this.newWith(null, null, 2, 3), this.newWith(null, 2, null, 3));
Assert.assertEquals(this.newWith(1, 1, 2, 3).toMapOfItemToCount().hashCode(), this.newWith(1, 1, 2, 3).hashCode());
Assert.assertEquals(this.newWith(null, null, 2, 3).toMapOfItemToCount().hashCode(), this.newWith(null, null, 2, 3).hashCode());
}
@Test
public void toStringOfItemToCount()
{
Assert.assertEquals("{}", this.newWith().toStringOfItemToCount());
Assert.assertEquals("{1=3}", this.newWith(1, 1, 1).toStringOfItemToCount());
String actual = this.newWith(1, 2, 2).toStringOfItemToCount();
Assert.assertTrue("{1=1, 2=2}".equals(actual) || "{2=2, 1=1}".equals(actual));
}
@Test
public void toMapOfItemToCount()
{
MutableBagIterable<Integer> bag = this.newWith(1, 2, 2, 3, 3, 3);
Assert.assertEquals(UnifiedMap.newWithKeysValues(1, 1, 2, 2, 3, 3), bag.toMapOfItemToCount());
}
@Test
public void add()
{
MutableBagIterable<Integer> bag = this.newWith();
bag.add(1);
bag.add(1);
Verify.assertSize(2, bag);
bag.add(1);
Verify.assertSize(3, bag);
}
@Override
@Test
public void iterator()
{
MutableBagIterable<Integer> bag = this.newWith(1, 1, 2);
MutableList<Integer> validate = Lists.mutable.of();
for (Integer each : bag)
{
validate.add(each);
}
Assert.assertEquals(HashBag.newBagWith(1, 1, 2), HashBag.newBag(validate));
Iterator<Integer> iterator = bag.iterator();
MutableBagIterable<Integer> expected = this.newWith(1, 1, 2);
Verify.assertThrows(IllegalStateException.class, iterator::remove);
this.assertIteratorRemove(bag, iterator, expected);
this.assertIteratorRemove(bag, iterator, expected);
this.assertIteratorRemove(bag, iterator, expected);
Verify.assertEmpty(bag);
Assert.assertFalse(iterator.hasNext());
Verify.assertThrows(NoSuchElementException.class, (Runnable) iterator::next);
}
private void assertIteratorRemove(MutableBagIterable<Integer> bag, Iterator<Integer> iterator, MutableBagIterable<Integer> expected)
{
Assert.assertTrue(iterator.hasNext());
Integer first = iterator.next();
iterator.remove();
expected.remove(first);
Assert.assertEquals(expected, bag);
Verify.assertThrows(IllegalStateException.class, iterator::remove);
}
@Test
public void iteratorRemove()
{
MutableBagIterable<Integer> bag = this.newWith(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4);
Iterator<Integer> iterator = bag.iterator();
iterator.next();
iterator.next();
Integer value = iterator.next();
Integer value2 = iterator.next();
Assert.assertNotEquals(value, value2);
iterator.remove();
Integer value3 = iterator.next();
Assert.assertNotEquals(value, value3);
iterator.remove();
Integer value4 = iterator.next();
Assert.assertNotEquals(value, value4);
iterator.remove();
Integer value5 = iterator.next();
Assert.assertNotEquals(value, value5);
}
@Test
public void iteratorRemove2()
{
MutableBagIterable<Integer> bag = this.newWith(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4);
Iterator<Integer> iterator = bag.iterator();
iterator.next();
iterator.next();
iterator.remove();
iterator.next();
iterator.next();
iterator.remove();
iterator.next();
iterator.remove();
iterator.next();
iterator.next();
iterator.remove();
Assert.assertEquals(4, bag.sizeDistinct());
Assert.assertEquals(8, bag.size());
}
@Override
@Test
public void removeIf()
{
super.removeIf();
MutableBagIterable<Integer> objects = this.newWith(4, 1, 3, 3, 2);
Assert.assertTrue(objects.removeIf(Predicates.equal(2)));
Assert.assertEquals(HashBag.newBagWith(1, 3, 3, 4), objects);
Assert.assertTrue(objects.removeIf(Predicates.equal(3)));
Assert.assertEquals(HashBag.newBagWith(1, 4), objects);
}
@Override
@Test
public void forEach()
{
MutableBagIterable<Integer> bag = this.newWith(1, 1, 2);
MutableList<Integer> validate = Lists.mutable.of();
bag.forEach(CollectionAddProcedure.on(validate));
Assert.assertEquals(HashBag.newBagWith(1, 1, 2), HashBag.newBag(validate));
}
@Test
public void forEachWithOccurrences()
{
MutableBagIterable<Integer> bag = this.newWith();
bag.addOccurrences(1, 3);
bag.addOccurrences(2, 2);
bag.addOccurrences(3, 1);
IntegerSum sum = new IntegerSum(0);
bag.forEachWithOccurrences((each, index) -> sum.add(each * index));
Assert.assertEquals(10, sum.getIntSum());
bag.removeOccurrences(2, 1);
IntegerSum sum2 = new IntegerSum(0);
bag.forEachWithOccurrences((each, index) -> sum2.add(each * index));
Assert.assertEquals(8, sum2.getIntSum());
bag.removeOccurrences(1, 3);
IntegerSum sum3 = new IntegerSum(0);
bag.forEachWithOccurrences((each, index) -> sum3.add(each * index));
Assert.assertEquals(5, sum3.getIntSum());
}
@Override
@Test
public void toImmutable()
{
super.toImmutable();
Verify.assertInstanceOf(MutableBagIterable.class, this.newWith());
Verify.assertInstanceOf(ImmutableBagIterable.class, this.newWith().toImmutable());
Assert.assertFalse(this.newWith().toImmutable() instanceof MutableBagIterable);
}
@Test
@Override
public void getLast()
{
Assert.assertEquals(Integer.valueOf(1), this.newWith(1).getLast());
Assert.assertEquals(Integer.valueOf(3), this.newWith(3).getLast());
}
@Test
public void occurrencesOf()
{
MutableBagIterable<Integer> bag = this.newWith(1, 1, 2);
Assert.assertEquals(2, bag.occurrencesOf(1));
Assert.assertEquals(1, bag.occurrencesOf(2));
}
@Test
public void addOccurrences()
{
MutableBagIterable<Object> bag = this.newWith();
bag.addOccurrences(new Object(), 0);
MutableBagTestCase.assertBagsEqual(HashBag.newBag(), bag);
}
@Test(expected = IllegalArgumentException.class)
public void addOccurrences_throws()
{
this.newWith().addOccurrences(new Object(), -1);
}
@Test
public void removeOccurrences()
{
MutableBagIterable<String> bag = this.newWith("betamax-tape", "betamax-tape");
MutableBagIterable<String> expected = HashBag.newBag(bag);
Assert.assertFalse(bag.removeOccurrences("dvd", 2));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertFalse(bag.removeOccurrences("dvd", 0));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertFalse(bag.removeOccurrences("betamax-tape", 0));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertTrue(bag.removeOccurrences("betamax-tape", 1));
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith("betamax-tape"), bag);
Assert.assertTrue(bag.removeOccurrences("betamax-tape", 10));
MutableBagTestCase.assertBagsEqual(HashBag.<String>newBag(), bag);
}
@Test(expected = IllegalArgumentException.class)
public void removeOccurrences_throws()
{
this.newWith().removeOccurrences(new Object(), -1);
}
@Test
public void setOccurrences()
{
MutableBagIterable<String> bag = this.newWith();
MutableBagIterable<String> expected = this.newWith("betamax-tape", "betamax-tape");
Assert.assertTrue(bag.setOccurrences("betamax-tape", 2));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertFalse(bag.setOccurrences("betamax-tape", 2));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertFalse(bag.setOccurrences("dvd", 0));
MutableBagTestCase.assertBagsEqual(expected, bag);
Assert.assertTrue(bag.setOccurrences("betamax-tape", 3));
MutableBagTestCase.assertBagsEqual(expected.with("betamax-tape"), bag);
Assert.assertTrue(bag.setOccurrences("betamax-tape", 0));
MutableBagTestCase.assertBagsEqual(HashBag.<String>newBag(), bag);
}
@Test(expected = IllegalArgumentException.class)
public void setOccurrences_throws()
{
this.newWith().setOccurrences(new Object(), -1);
}
protected static void assertBagsEqual(Bag<?> expected, Bag<?> actual)
{
Assert.assertEquals(expected.toMapOfItemToCount(), actual.toMapOfItemToCount());
Assert.assertEquals(expected.sizeDistinct(), actual.sizeDistinct());
Assert.assertEquals(expected.size(), actual.size());
Verify.assertEqualsAndHashCode(expected, actual);
}
@Test
public void toSortedListWith()
{
Assert.assertEquals(
FastList.newListWith(1, 2, 2, 3, 3, 3),
this.newWith(3, 3, 3, 2, 2, 1).toSortedList());
}
@Override
@Test
public void toSet()
{
super.toSet();
MutableBagIterable<Integer> bag = this.newWith(3, 3, 3, 2, 2, 1);
Assert.assertEquals(UnifiedSet.newSetWith(1, 2, 3), bag.toSet());
}
@Override
@Test
public void toList()
{
super.toList();
MutableBagIterable<Integer> bag = this.newWith(1, 1, 1);
Assert.assertEquals(FastList.newListWith(1, 1, 1), bag.toList());
}
@Override
@Test
public void removeObject()
{
super.removeObject();
MutableBagIterable<String> bag = this.newWith("dakimakura", "dakimakura");
Assert.assertFalse(bag.remove("Mr. T"));
Assert.assertTrue(bag.remove("dakimakura"));
Assert.assertTrue(bag.remove("dakimakura"));
Assert.assertFalse(bag.remove("dakimakura"));
MutableBagTestCase.assertBagsEqual(Bags.mutable.of(), bag);
}
@Override
@Test
public void asSynchronized()
{
Verify.assertInstanceOf(SynchronizedBag.class, this.newWith().asSynchronized());
}
@Override
@Test
public void asUnmodifiable()
{
Verify.assertInstanceOf(UnmodifiableBag.class, this.newWith().asUnmodifiable());
}
@Test
public void serialization()
{
MutableBagIterable<String> bag = this.newWith("One", "Two", "Two", "Three", "Three", "Three");
Verify.assertPostSerializedEqualsAndHashCode(bag);
}
@Override
@Test
public void partition()
{
super.partition();
MutableBagIterable<Integer> integers = this.newWith(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);
PartitionMutableCollection<Integer> result = integers.partition(IntegerPredicates.isEven());
Assert.assertEquals(Iterables.iBag(2, 2, 4, 4, 4, 4), result.getSelected());
Assert.assertEquals(Iterables.iBag(1, 3, 3, 3), result.getRejected());
}
@Override
@Test
public void partitionWith()
{
super.partitionWith();
MutableBagIterable<Integer> integers = this.newWith(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);
PartitionMutableCollection<Integer> result = integers.partitionWith(Predicates2.in(), integers.select(IntegerPredicates.isEven()));
Assert.assertEquals(Iterables.iBag(2, 2, 4, 4, 4, 4), result.getSelected());
Assert.assertEquals(Iterables.iBag(1, 3, 3, 3), result.getRejected());
}
@Test
public void selectByOccurrences()
{
MutableBagIterable<Integer> integers = this.newWith(1, 1, 1, 1, 2, 2, 2, 3, 3, 4);
Assert.assertEquals(Iterables.iBag(1, 1, 1, 1, 3, 3), integers.selectByOccurrences(IntPredicates.isEven()));
}
@Test
public void topOccurrences()
{
MutableBagIterable<String> strings = this.newWithOccurrences(
PrimitiveTuples.pair("one", 1),
PrimitiveTuples.pair("two", 2),
PrimitiveTuples.pair("three", 3),
PrimitiveTuples.pair("four", 4),
PrimitiveTuples.pair("five", 5),
PrimitiveTuples.pair("six", 6),
PrimitiveTuples.pair("seven", 7),
PrimitiveTuples.pair("eight", 8),
PrimitiveTuples.pair("nine", 9),
PrimitiveTuples.pair("ten", 10));
MutableList<ObjectIntPair<String>> top5 = strings.topOccurrences(5);
Verify.assertSize(5, top5);
Assert.assertEquals("ten", top5.getFirst().getOne());
Assert.assertEquals(10, top5.getFirst().getTwo());
Assert.assertEquals("six", top5.getLast().getOne());
Assert.assertEquals(6, top5.getLast().getTwo());
Verify.assertSize(0, this.newWith("one").topOccurrences(0));
Verify.assertSize(0, this.newWith().topOccurrences(5));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(5));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(1));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(2));
Verify.assertSize(3, this.newWith("one", "one", "two", "three").topOccurrences(2));
Verify.assertSize(2, this.newWith("one", "one", "two", "two", "three").topOccurrences(1));
Verify.assertSize(3, this.newWith(null, "one", "two").topOccurrences(5));
Verify.assertSize(3, this.newWith(null, "one", "two").topOccurrences(1));
Verify.assertSize(3, this.newWith("one", "one", "two", "two", "three", "three").topOccurrences(1));
Verify.assertSize(0, this.newWith().topOccurrences(0));
Verify.assertSize(0, this.newWith("one").topOccurrences(0));
Verify.assertThrows(IllegalArgumentException.class, () -> this.newWith().topOccurrences(-1));
}
@Test
public void bottomOccurrences()
{
MutableBagIterable<String> strings = this.newWithOccurrences(
PrimitiveTuples.pair("one", 1),
PrimitiveTuples.pair("two", 2),
PrimitiveTuples.pair("three", 3),
PrimitiveTuples.pair("four", 4),
PrimitiveTuples.pair("five", 5),
PrimitiveTuples.pair("six", 6),
PrimitiveTuples.pair("seven", 7),
PrimitiveTuples.pair("eight", 8),
PrimitiveTuples.pair("nine", 9),
PrimitiveTuples.pair("ten", 10));
MutableList<ObjectIntPair<String>> bottom5 = strings.bottomOccurrences(5);
Verify.assertSize(5, bottom5);
Assert.assertEquals("one", bottom5.getFirst().getOne());
Assert.assertEquals(1, bottom5.getFirst().getTwo());
Assert.assertEquals("five", bottom5.getLast().getOne());
Assert.assertEquals(5, bottom5.getLast().getTwo());
Verify.assertSize(0, this.newWith("one").bottomOccurrences(0));
Verify.assertSize(0, this.newWith().bottomOccurrences(5));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(5));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(1));
Verify.assertSize(3, this.newWith("one", "two", "three").topOccurrences(2));
Verify.assertSize(3, this.newWith("one", "one", "two", "three").topOccurrences(2));
Verify.assertSize(2, this.newWith("one", "one", "two", "two", "three").topOccurrences(1));
Verify.assertSize(3, this.newWith(null, "one", "two").topOccurrences(5));
Verify.assertSize(3, this.newWith(null, "one", "two").topOccurrences(1));
Verify.assertSize(3, this.newWith("one", "one", "two", "two", "three", "three").bottomOccurrences(1));
Verify.assertSize(0, this.newWith().bottomOccurrences(0));
Verify.assertSize(0, this.newWith("one").bottomOccurrences(0));
Verify.assertThrows(IllegalArgumentException.class, () -> this.newWith().bottomOccurrences(-1));
}
}