/*
* Copyright 2014 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.concurrent.atomic.AtomicReference;
import com.gs.collections.api.bag.ImmutableBag;
import com.gs.collections.api.bag.MutableBag;
import com.gs.collections.api.block.function.Function;
import com.gs.collections.api.block.function.Function2;
import com.gs.collections.api.partition.PartitionMutableCollection;
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.Procedures;
import com.gs.collections.impl.block.factory.primitive.IntPredicates;
import com.gs.collections.impl.block.function.AddFunction;
import com.gs.collections.impl.block.procedure.CollectionAddProcedure;
import com.gs.collections.impl.factory.Bags;
import com.gs.collections.impl.factory.Sets;
import com.gs.collections.impl.list.Interval;
import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.map.mutable.UnifiedMap;
import com.gs.collections.impl.parallel.ParallelIterate;
import com.gs.collections.impl.set.mutable.MultiReaderMutableCollectionTestCase;
import com.gs.collections.impl.set.mutable.UnifiedSet;
import com.gs.collections.impl.test.SerializeTestHelper;
import com.gs.collections.impl.test.Verify;
import org.junit.Assert;
import org.junit.Test;
/**
* JUnit test for {@link MultiReaderHashBag}.
*/
public class MultiReaderHashBagTest extends MultiReaderMutableCollectionTestCase
{
@Override
protected <T> MultiReaderHashBag<T> newWith(T... littleElements)
{
return MultiReaderHashBag.newBagWith(littleElements);
}
@Override
@Test
public void newEmpty()
{
Verify.assertInstanceOf(MultiReaderHashBag.class, MultiReaderHashBag.newBag().newEmpty());
Verify.assertEmpty(MultiReaderHashBag.<Integer>newBagWith(null, null).newEmpty());
}
@Test
public void hashBagNewWith()
{
Assert.assertEquals(
HashBag.newBagWith("Alice", "Bob", "Bob", "Bob", "Cooper", "Dio"),
HashBag.newBagWith("Alice", "Bob", "Cooper", "Dio", "Bob", "Bob"));
}
@Override
@Test
public void asSynchronized()
{
Verify.assertInstanceOf(SynchronizedBag.class, MultiReaderHashBag.newBag().asSynchronized());
}
@Override
@Test
public void asUnmodifiable()
{
Verify.assertInstanceOf(UnmodifiableBag.class, this.newWith().asUnmodifiable());
}
@Override
@Test
public void toImmutable()
{
Verify.assertInstanceOf(ImmutableBag.class, this.newWith().toImmutable());
}
@Test
public void addOccurrences()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2, 3);
bag.addOccurrences(1, 2);
bag.addOccurrences(4, 2);
bag.addOccurrences(2, 1);
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith(1, 1, 1, 1, 2, 2, 3, 4, 4), bag);
}
@Test(expected = IllegalArgumentException.class)
public void addOccurrences_throws()
{
this.newWith().addOccurrences(new Object(), -1);
}
@Test
public void removeOccurrences()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 1, 1, 2, 2, 3);
Assert.assertFalse(bag.removeOccurrences(4, 2));
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith(1, 1, 1, 1, 2, 2, 3), bag);
bag.removeOccurrences(1, 3);
bag.removeOccurrences(3, 1);
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith(1, 2, 2), bag);
}
@Test
public void setOccurrences()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2);
Assert.assertFalse(bag.setOccurrences(1, 2));
Assert.assertTrue(bag.setOccurrences(3, 3));
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith(1, 1, 2, 3, 3, 3), bag);
Assert.assertTrue(bag.setOccurrences(2, 0));
MutableBagTestCase.assertBagsEqual(HashBag.newBagWith(1, 1, 3, 3, 3), bag);
}
@Test
public void occurrencesOf()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2);
Assert.assertEquals(2, bag.occurrencesOf(1));
Assert.assertEquals(1, bag.occurrencesOf(2));
}
@Test
public void sizeDistinct()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2, 2, 3);
Assert.assertEquals(3, bag.sizeDistinct());
}
@Override
@Test
public void collect()
{
MutableBag<Boolean> bag = MultiReaderHashBag.newBagWith(Boolean.TRUE, Boolean.FALSE, null);
MutableBag<String> newCollection = bag.collect(String::valueOf);
Assert.assertEquals(HashBag.newBagWith("true", "false", "null"), newCollection);
}
@Override
@Test
public void flatCollect()
{
MutableBag<Integer> collection = MultiReaderHashBag.newBagWith(1, 1, 2, 3, 4);
Function<Integer, MutableBag<String>> function = object -> HashBag.newBagWith(String.valueOf(object));
MutableBagTestCase.assertBagsEqual(
HashBag.newBagWith("1", "1", "2", "3", "4"),
collection.flatCollect(function));
}
@Override
@Test
public void collectIf()
{
Assert.assertEquals(
HashBag.newBagWith("1", "1", "2", "3"),
MultiReaderHashBag.newBagWith(1, 1, 2, 3).collectIf(
Integer.class::isInstance,
String::valueOf));
Assert.assertEquals(
HashBag.newBagWith("1", "1"),
MultiReaderHashBag.newBagWith(1, 1, 2, 3).collectIf(
Predicates.lessThan(2),
String::valueOf));
}
@Override
@Test
public void collectWith()
{
Function2<Integer, Integer, Integer> addZeroFunction = (each, parameter) -> each + parameter;
Verify.assertContainsAll(MultiReaderHashBag.newBagWith(1, 1, 2, 3).collectWith(addZeroFunction, 0), 1, 2, 3);
Verify.assertContainsAll(
MultiReaderHashBag.newBagWith(1, 1, 2, 3).collectWith(
addZeroFunction,
0,
HashBag.<Integer>newBag()), 1, 2, 3);
}
@Override
@Test
public void reject()
{
Verify.assertContainsAll(MultiReaderHashBag.newBagWith(1, 1, 2, 3, 4).reject(Predicates.lessThan(3)), 3, 4);
Verify.assertContainsAll(MultiReaderHashBag.newBagWith(1, 2, 3, 3, 4).reject(
Predicates.lessThan(3),
HashBag.<Integer>newBag()), 3, 4);
}
@Override
@Test
public void rejectWith()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 1);
MutableBag<Integer> results = bag.rejectWith(Predicates2.instanceOf(), Integer.class);
Verify.assertEmpty(results);
}
@Override
@Test
public void select()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 2, 3, 4, 5, 5, 1);
MutableBag<Integer> results = bag.select(Integer.valueOf(1)::equals);
MutableBagTestCase.assertBagsEqual(results, MultiReaderHashBag.newBagWith(1, 1));
}
@Override
@Test
public void selectWith()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2, 2);
MutableBag<Integer> results = bag.selectWith(Predicates2.instanceOf(), Integer.class);
Verify.assertSize(4, results);
}
@Test
public void selectByOccurrences()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2, 2, 2, 3);
MutableBag<Integer> results = bag.selectByOccurrences(IntPredicates.isEven());
Verify.assertSize(2, results);
MutableBagTestCase.assertBagsEqual(results, MultiReaderHashBag.newBagWith(1, 1));
}
@Override
@Test
public void selectInstancesOf()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 2, 2, 2, 3);
MutableBagTestCase.assertBagsEqual(bag.selectInstancesOf(Integer.class), MultiReaderHashBag.newBagWith(1, 1, 2, 2, 2, 3));
}
@Override
@Test
public void partition()
{
MutableBag<Integer> integers = MultiReaderHashBag.newBagWith(-3, -2, -1, 0, 1, 2, 2, 2, 3, 3, 4, 5);
PartitionMutableCollection<Integer> result = integers.partition(IntegerPredicates.isEven());
Assert.assertEquals(MultiReaderHashBag.newBagWith(-2, 0, 2, 2, 2, 4), result.getSelected());
Assert.assertEquals(MultiReaderHashBag.newBagWith(-3, -1, 1, 3, 3, 5), result.getRejected());
}
@Override
@Test
public void partitionWith()
{
MutableBag<Integer> integers = MultiReaderHashBag.newBagWith(-3, -2, -1, 0, 1, 2, 2, 2, 3, 3, 4, 5);
PartitionMutableCollection<Integer> result = integers.partitionWith(Predicates2.in(), integers.select(IntegerPredicates.isEven()));
Assert.assertEquals(MultiReaderHashBag.newBagWith(-2, 0, 2, 2, 2, 4), result.getSelected());
Assert.assertEquals(MultiReaderHashBag.newBagWith(-3, -1, 1, 3, 3, 5), result.getRejected());
}
@Override
@Test
public void with()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 3, 3);
MutableBag<Integer> bagWith = bag.with(3);
MutableBagTestCase.assertBagsEqual(MultiReaderHashBag.newBagWith(1, 2, 3, 3, 3), bagWith);
}
@Override
@Test
public void without()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 3, 3);
MutableBag<Integer> bagWithout = bag.without(3);
MutableBagTestCase.assertBagsEqual(MultiReaderHashBag.newBagWith(1, 2, 3), bagWithout);
}
@Override
@Test
public void withAll()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 3, 3);
MutableBag<Integer> bagWith = bag.withAll(FastList.newListWith(2, 4, 4));
MutableBagTestCase.assertBagsEqual(MultiReaderHashBag.newBagWith(1, 2, 2, 3, 3, 4, 4), bagWith);
}
@Override
@Test
public void withoutAll()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 3, 3, 4);
MutableBag<Integer> bagWithout = bag.withoutAll(FastList.newListWith(3, 4));
MutableBagTestCase.assertBagsEqual(MultiReaderHashBag.newBagWith(1, 2), bagWithout);
}
@Test
public void toMapOfItemToCount()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 2, 3, 3, 3);
Assert.assertEquals(UnifiedMap.newWithKeysValues(1, 1, 2, 2, 3, 3), bag.toMapOfItemToCount());
}
@Test
public void toStringOfItemToCount()
{
Assert.assertEquals("{}", MultiReaderHashBag.newBagWith().toStringOfItemToCount());
Assert.assertEquals("{1=3}", MultiReaderHashBag.newBagWith(1, 1, 1).toStringOfItemToCount());
String actual = MultiReaderHashBag.newBagWith(1, 2, 2).toStringOfItemToCount();
Assert.assertTrue("{1=1, 2=2}".equals(actual) || "{2=2, 1=1}".equals(actual));
}
@Test
public void forEachWithOccurrences()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 2, 2, 3, 3, 3);
int[] sum = new int[1];
bag.forEachWithOccurrences((each, occurrences) -> {
if (occurrences > 1)
{
sum[0] += each * occurrences;
}
});
Assert.assertEquals(13, sum[0]);
}
@Test
public void equalsAndHashCose()
{
MutableBag<Integer> integers = MultiReaderHashBag.newBagWith(1, 2, 3);
MutableBag<Integer> integers2 = MultiReaderHashBag.newBagWith(1, 2, 3);
MutableBag<Integer> integers3 = MultiReaderHashBag.newBagWith(1, null, 3, 4, 5);
MutableBag<Integer> integers4 = MultiReaderHashBag.newBagWith(1, null, 3, 4, 5);
MutableBag<Integer> integers5 = MultiReaderHashBag.newBagWith(1, null, 3);
MutableBag<Integer> randomAccessList = Bags.mutable.of(1, 2, 3);
MutableBag<Integer> randomAccessList2 = Bags.mutable.of(2, 3, 4);
Verify.assertEqualsAndHashCode(integers, integers);
Verify.assertPostSerializedEqualsAndHashCode(integers);
Verify.assertEqualsAndHashCode(integers, integers2);
Verify.assertEqualsAndHashCode(integers, randomAccessList);
Assert.assertNotEquals(integers, integers3);
Assert.assertNotEquals(integers, integers5);
Assert.assertNotEquals(integers, randomAccessList2);
Assert.assertNotEquals(integers, Sets.fixedSize.of());
Verify.assertEqualsAndHashCode(integers3, integers4);
Assert.assertEquals(integers, integers2);
Assert.assertNotEquals(integers, integers3);
}
@Override
@Test
public void toSet()
{
super.toSet();
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(3, 3, 3, 2, 2, 1);
Assert.assertEquals(UnifiedSet.newSetWith(1, 2, 3), bag.toSet());
}
@Override
@Test
public void toList()
{
super.toList();
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 1);
Assert.assertEquals(FastList.newListWith(1, 1, 1), bag.toList());
}
@Override
@Test
public void injectInto()
{
MutableBag<Integer> bag = MultiReaderHashBag.newBagWith(1, 1, 3);
Assert.assertEquals(Integer.valueOf(6), bag.injectInto(1, AddFunction.INTEGER));
}
@Override
@Test
public void forEach()
{
MutableBag<Integer> result = HashBag.newBag();
MutableBag<Integer> collection = MultiReaderHashBag.newBagWith(1, 2, 3, 4, 4);
collection.forEach(CollectionAddProcedure.on(result));
Assert.assertEquals(HashBag.newBagWith(1, 2, 3, 4, 4), result);
}
@Override
@Test
public void isEmpty()
{
Verify.assertEmpty(MultiReaderHashBag.newBag());
Verify.assertNotEmpty(MultiReaderHashBag.newBagWith(1, 1));
}
@Test
public void serialization()
{
MutableBag<Integer> collection = MultiReaderHashBag.newBagWith(1, 1, 3, 4, 5);
MutableBag<Integer> deserializedCollection = SerializeTestHelper.serializeDeserialize(collection);
Verify.assertSize(5, deserializedCollection);
Assert.assertEquals(collection, deserializedCollection);
}
private void verifyDelegateIsUnmodifiable(MutableBag<Integer> delegate)
{
Verify.assertThrows(UnsupportedOperationException.class, () -> delegate.add(2));
Verify.assertThrows(UnsupportedOperationException.class, () -> delegate.remove(0));
}
@Test
public void withReadLockAndDelegate()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(1);
Object[] result = new Object[1];
bag.withReadLockAndDelegate(delegate -> {
result[0] = delegate.getFirst();
this.verifyDelegateIsUnmodifiable(delegate);
});
Assert.assertNotNull(result[0]);
}
@Override
@Test
public void makeString()
{
Assert.assertEquals("[1, 1, 2, 3]", MultiReaderHashBag.newBagWith(1, 1, 2, 3).toString());
}
@Override
@Test
public void appendString()
{
Appendable builder = new StringBuilder();
MultiReaderHashBag.newBagWith(1, 1, 2, 3).appendString(builder);
Assert.assertEquals("1, 1, 2, 3", builder.toString());
}
@Override
@Test
public void testToString()
{
Assert.assertEquals("[1, 1, 2, 3]", MultiReaderHashBag.newBagWith(1, 1, 2, 3).toString());
}
@Override
@Test
public void iterator()
{
MultiReaderHashBag<Integer> integers = MultiReaderHashBag.newBagWith(1, 1, 2, 3, 4);
Verify.assertThrows(UnsupportedOperationException.class, (Runnable) integers::iterator);
}
@Test(expected = UnsupportedOperationException.class)
public void listIterator()
{
MultiReaderHashBag<Integer> integers = MultiReaderHashBag.newBagWith(1, 1, 2, 3, 4);
integers.iterator();
}
@Test
public void withWriteLockAndDelegate()
{
MultiReaderHashBag<Integer> bag = MultiReaderHashBag.newBagWith(2);
AtomicReference<MutableBag<?>> delegateList = new AtomicReference<>();
AtomicReference<Iterator<?>> iterator = new AtomicReference<>();
bag.withWriteLockAndDelegate(delegate -> {
delegate.add(1);
delegate.add(2);
delegate.add(3);
delegate.add(4);
delegateList.set(delegate);
iterator.set(delegate.iterator());
});
Assert.assertEquals(HashBag.newBagWith(1, 2, 2, 3, 4), bag);
Verify.assertThrows(NullPointerException.class, () -> iterator.get().hasNext());
Verify.assertThrows(NullPointerException.class, () -> delegateList.get().iterator());
}
@Test
public void concurrentWrite()
{
MultiReaderHashBag<Integer> numbers = this.newWith();
Interval interval = Interval.oneTo(100);
ParallelIterate.forEach(interval, each -> {
numbers.add(each);
Verify.assertSize(1, numbers.select(each::equals));
numbers.add(each);
Assert.assertEquals(2, numbers.count(each::equals));
numbers.add(each);
Integer[] removed = new Integer[1];
numbers.withWriteLockAndDelegate(bag -> {
Iterator<Integer> iterator = bag.iterator();
removed[0] = iterator.next();
bag.remove(removed[0]);
bag.add(removed[0]);
});
numbers.add(each);
Assert.assertEquals(4, numbers.count(each::equals));
}, 1);
interval.forEach(Procedures.cast(each -> Assert.assertEquals(4, numbers.occurrencesOf(each))));
}
@Test
public void parallelCollect()
{
MultiReaderHashBag<String> numbers = this.newWith();
Interval interval = Interval.oneTo(50000);
ParallelIterate.collect(interval, String::valueOf, numbers, true);
Assert.assertEquals(numbers, interval.collect(String::valueOf).toBag());
}
}