/*
* 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.multimap;
import com.gs.collections.api.RichIterable;
import com.gs.collections.api.bag.MutableBag;
import com.gs.collections.api.map.MutableMap;
import com.gs.collections.api.multimap.ImmutableMultimap;
import com.gs.collections.api.multimap.Multimap;
import com.gs.collections.api.multimap.MutableMultimap;
import com.gs.collections.api.set.MutableSet;
import com.gs.collections.api.tuple.Pair;
import com.gs.collections.impl.bag.mutable.HashBag;
import com.gs.collections.impl.block.procedure.CollectionAddProcedure;
import com.gs.collections.impl.factory.Bags;
import com.gs.collections.impl.factory.Lists;
import com.gs.collections.impl.map.mutable.UnifiedMap;
import com.gs.collections.impl.set.mutable.UnifiedSet;
import com.gs.collections.impl.test.Verify;
import com.gs.collections.impl.tuple.Tuples;
import org.junit.Assert;
import org.junit.Test;
/**
* Helper class for testing {@link Multimap}s.
*/
public abstract class AbstractMutableMultimapTestCase extends AbstractMultimapTestCase
{
@Override
protected abstract <K, V> MutableMultimap<K, V> newMultimap();
@Override
protected abstract <K, V> MutableMultimap<K, V> newMultimapWithKeyValue(
K key, V value);
@Override
protected abstract <K, V> MutableMultimap<K, V> newMultimapWithKeysValues(
K key1, V value1,
K key2, V value2);
@Override
protected abstract <K, V> MutableMultimap<K, V> newMultimapWithKeysValues(
K key1, V value1,
K key2, V value2,
K key3, V value3);
@Override
protected abstract <K, V> MutableMultimap<K, V> newMultimapWithKeysValues(
K key1, V value1,
K key2, V value2,
K key3, V value3,
K key4, V value4);
@Test
public void testPutAndGrowMultimap()
{
MutableMultimap<Integer, Integer> multimap = this.newMultimap();
multimap.put(1, 1);
multimap.put(2, 2);
Verify.assertContainsEntry(1, 1, multimap);
Verify.assertContainsEntry(2, 2, multimap);
}
@Test
public void testAddAndGrowMultimap()
{
MutableMultimap<Integer, String> multimap = this.newMultimap();
Pair<Integer, String> pair1 = Tuples.pair(1, "One");
Pair<Integer, String> pair2 = Tuples.pair(2, "Two");
Pair<Integer, String> pair3 = Tuples.pair(3, "Three");
Pair<Integer, String> pair4 = Tuples.pair(4, "Four");
Assert.assertTrue(multimap.add(pair1));
Verify.assertContainsEntry(1, "One", multimap);
Assert.assertTrue(multimap.add(pair2));
Verify.assertContainsEntry(2, "Two", multimap);
Assert.assertTrue(multimap.add(pair3));
Verify.assertContainsEntry(3, "Three", multimap);
Assert.assertTrue(multimap.add(pair4));
Verify.assertContainsEntry(4, "Four", multimap);
Verify.assertSetsEqual(UnifiedSet.newSetWith(pair1, pair2, pair3, pair4), multimap.keyValuePairsView().toSet());
}
@Test
public void testClear()
{
MutableMultimap<Integer, Object> multimap =
this.<Integer, Object>newMultimapWithKeysValues(1, "One", 2, "Two", 3, "Three");
Verify.assertNotEmpty(multimap);
multimap.clear();
Verify.assertEmpty(multimap);
}
@Test
public void testRemoveObject()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Three", 3);
multimap.removeAll("Two");
Verify.assertContainsAllEntries(multimap, "One", 1, "Three", 3);
}
@Override
@Test
public void forEachKey()
{
MutableBag<Integer> collection = Bags.mutable.of();
Multimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "1", 2, "2", 3, "3");
multimap.forEachKey(CollectionAddProcedure.on(collection));
Assert.assertEquals(HashBag.newBagWith(1, 2, 3), collection);
}
@Test
public void testPutAll()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "One", 2, "2");
Multimap<Integer, String> toAdd = this.newMultimapWithKeysValues(2, "Two", 3, "Three");
Multimap<Integer, String> toAddImmutable = this.newMultimapWithKeysValues(4, "Four", 5, "Five");
Assert.assertTrue(multimap.putAll(toAdd));
Assert.assertTrue(multimap.putAll(toAddImmutable));
MutableMultimap<Integer, String> expected = this.newMultimapWithKeysValues(1, "One", 2, "2", 2, "Two", 3, "Three");
expected.put(4, "Four");
expected.put(5, "Five");
Assert.assertEquals(expected, multimap);
}
@Test
public void testPutAllFromCollection()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "One", 2, "Two");
Assert.assertTrue(multimap.putAll(1, Lists.fixedSize.of("Three", "Four")));
Assert.assertEquals(this.newMultimapWithKeysValues(1, "One", 2, "Two", 1, "Three", 1, "Four"), multimap);
Assert.assertFalse(multimap.putAll(1, UnifiedSet.<String>newSet()));
Assert.assertEquals(this.newMultimapWithKeysValues(1, "One", 2, "Two", 1, "Three", 1, "Four"), multimap);
}
@Test
public void testPutAllFromIterable()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "One", 2, "Two");
Assert.assertTrue(multimap.putAll(1, Lists.fixedSize.of("Three", "Four").asLazy()));
Assert.assertEquals(this.newMultimapWithKeysValues(1, "One", 2, "Two", 1, "Three", 1, "Four"), multimap);
}
@Test
public void testRemoveKey()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "1", 2, "Two");
Verify.assertSetsEqual(UnifiedSet.newSetWith("1"), UnifiedSet.newSet(multimap.removeAll(1)));
Verify.assertSize(1, multimap);
Assert.assertFalse(multimap.containsKey(1));
Verify.assertIterableEmpty(multimap.removeAll(42));
Verify.assertSize(1, multimap);
Verify.assertSetsEqual(UnifiedSet.newSetWith("Two"), UnifiedSet.newSet(multimap.removeAll(2)));
Verify.assertEmpty(multimap);
}
@Test
public void testContainsValue()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "One", 2, "Two");
Assert.assertTrue(multimap.containsValue("Two"));
Assert.assertFalse(multimap.containsValue("Three"));
}
@Test
public void testGetIfAbsentPut()
{
MutableMultimap<Integer, String> multimap = this.newMultimapWithKeysValues(1, "1", 2, "2", 3, "3");
Verify.assertIterableEmpty(multimap.get(4));
Assert.assertTrue(multimap.put(4, "4"));
Verify.assertContainsEntry(4, "4", multimap);
}
@Test
public void testRemove()
{
MutableMultimap<Integer, Integer> map = this.newMultimapWithKeysValues(1, 1, 1, 2, 3, 3, 4, 5);
Assert.assertFalse(map.remove(4, 4));
Assert.assertEquals(this.newMultimapWithKeysValues(1, 1, 1, 2, 3, 3, 4, 5), map);
Assert.assertTrue(map.remove(4, 5));
Assert.assertEquals(this.newMultimapWithKeysValues(1, 1, 1, 2, 3, 3), map);
Assert.assertTrue(map.remove(1, 2));
Assert.assertEquals(this.newMultimapWithKeysValues(1, 1, 3, 3), map);
}
@Test
public void testReplaceValues()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Three", 3);
RichIterable<Integer> oldValues2 = multimap.replaceValues("Two", UnifiedSet.newSetWith(4));
Assert.assertEquals(Bags.mutable.of(2), oldValues2.toBag());
Verify.assertEqualsAndHashCode(this.newMultimapWithKeysValues("One", 1, "Two", 4, "Three", 3), multimap);
RichIterable<Integer> oldValues3 = multimap.replaceValues("Three", UnifiedSet.<Integer>newSet());
Assert.assertEquals(Bags.mutable.of(3), oldValues3.toBag());
Verify.assertEqualsAndHashCode(this.newMultimapWithKeysValues("One", 1, "Two", 4), multimap);
}
@Test
public void testReplaceValues_absent_key()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Three", 3);
RichIterable<Integer> oldValues = multimap.replaceValues("Four", UnifiedSet.newSetWith(4));
Assert.assertEquals(HashBag.<Integer>newBag(), oldValues.toBag());
Verify.assertEqualsAndHashCode(this.newMultimapWithKeysValues("One", 1, "Two", 2, "Three", 3, "Four", 4), multimap);
}
@Test
public void toMap()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Two", 2);
UnifiedMap<String, RichIterable<Integer>> expected = UnifiedMap.newMap();
expected.put("One", this.createCollection(1));
expected.put("Two", this.createCollection(2, 2));
MutableMap<String, RichIterable<Integer>> toMap = multimap.toMap();
Assert.assertEquals(expected, toMap);
MutableMap<String, RichIterable<Integer>> newToMap = multimap.toMap();
Assert.assertEquals(toMap.get("One"), newToMap.get("One"));
Assert.assertNotSame(toMap.get("One"), newToMap.get("One"));
}
@Test
public void toImmutable()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Two", 2);
ImmutableMultimap<String, Integer> actual = multimap.toImmutable();
Assert.assertNotNull(actual);
Assert.assertEquals(multimap, actual);
}
@Test
public void toMapWithTarget()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Two", 2);
MutableMap<String, RichIterable<Integer>> expected = UnifiedMap.newMap();
expected.put("One", UnifiedSet.newSetWith(1));
expected.put("Two", UnifiedSet.newSetWith(2, 2));
MutableMap<String, MutableSet<Integer>> map = multimap.toMap(UnifiedSet::new);
Assert.assertEquals(expected, map);
}
@Test
public void toMutable()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2, "Two", 2);
MutableMultimap<String, Integer> mutableCopy = multimap.toMutable();
Assert.assertNotSame(multimap, mutableCopy);
Assert.assertEquals(multimap, mutableCopy);
}
@Test
public void testToString()
{
MutableMultimap<String, Integer> multimap =
this.newMultimapWithKeysValues("One", 1, "Two", 2);
Assert.assertTrue(
"{One=[1], Two=[2]}".equals(multimap.toString())
|| "{Two=[2], One=[1]}".equals(multimap.toString()));
}
}