/* * 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.set.fixed; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import com.gs.collections.api.LazyIterable; import com.gs.collections.api.RichIterable; import com.gs.collections.api.bag.MutableBag; import com.gs.collections.api.block.function.Function; import com.gs.collections.api.list.MutableList; import com.gs.collections.api.map.MutableMap; import com.gs.collections.api.multimap.Multimap; import com.gs.collections.api.multimap.MutableMultimap; import com.gs.collections.api.multimap.set.MutableSetMultimap; import com.gs.collections.api.set.FixedSizeSet; import com.gs.collections.api.set.ImmutableSet; import com.gs.collections.api.set.MutableSet; import com.gs.collections.api.set.UnsortedSetIterable; import com.gs.collections.api.tuple.Pair; import com.gs.collections.impl.block.factory.Comparators; import com.gs.collections.impl.block.factory.IntegerPredicates; import com.gs.collections.impl.block.factory.Predicates; import com.gs.collections.impl.block.factory.Procedures; import com.gs.collections.impl.block.function.NegativeIntervalFunction; import com.gs.collections.impl.factory.Bags; import com.gs.collections.impl.factory.Lists; import com.gs.collections.impl.list.Interval; import com.gs.collections.impl.list.mutable.FastList; import com.gs.collections.impl.multimap.set.UnifiedSetMultimap; import com.gs.collections.impl.set.mutable.SynchronizedMutableSet; import com.gs.collections.impl.set.mutable.UnifiedSet; import com.gs.collections.impl.set.mutable.UnmodifiableMutableSet; import com.gs.collections.impl.test.Verify; import com.gs.collections.impl.utility.Iterate; import org.junit.Assert; import org.junit.Test; import static com.gs.collections.impl.factory.Iterables.*; /** * JUnit test for {@link AbstractMemoryEfficientMutableSet}. */ public abstract class AbstractMemoryEfficientMutableSetTestCase { protected abstract MutableSet<String> classUnderTest(); @Test public void asSynchronized() { Verify.assertInstanceOf(SynchronizedMutableSet.class, this.classUnderTest().asSynchronized()); } @Test(expected = UnsupportedOperationException.class) public void remove_throws() { MutableSet<String> set = this.classUnderTest(); set.remove("1"); } @Test(expected = UnsupportedOperationException.class) public void addAll_throws() { MutableSet<String> set = this.classUnderTest(); set.addAll(null); } @Test(expected = UnsupportedOperationException.class) public void addAllIterable_throws() { MutableSet<String> set = this.classUnderTest(); set.addAllIterable(null); } @Test(expected = UnsupportedOperationException.class) public void add_duplicate_throws() { MutableSet<String> set = this.classUnderTest(); set.add("1"); } @Test(expected = UnsupportedOperationException.class) public void add_throws() { MutableSet<String> set = this.classUnderTest(); set.add(null); } @Test(expected = UnsupportedOperationException.class) public void removeAll_throws() { MutableSet<String> set = this.classUnderTest(); set.removeAll(mList("1", "2")); } @Test(expected = UnsupportedOperationException.class) public void removeAllIterable_throws() { MutableSet<String> set = this.classUnderTest(); set.removeAllIterable(mList("1", "2")); } @Test(expected = UnsupportedOperationException.class) public void retainAll_throws() { MutableSet<String> set = this.classUnderTest(); set.retainAll(mList("1", "2")); } @Test(expected = UnsupportedOperationException.class) public void retainAllIterable_throws() { MutableSet<String> set = this.classUnderTest(); set.retainAllIterable(mList("1", "2")); } @Test(expected = UnsupportedOperationException.class) public void clear_throws() { MutableSet<String> set = this.classUnderTest(); set.clear(); } @Test(expected = UnsupportedOperationException.class) public void removeIf_throws() { MutableSet<String> set = this.classUnderTest(); set.removeIf(Predicates.equal("1")); } @Test(expected = UnsupportedOperationException.class) public void removeIfWith_throws() { MutableSet<String> set = this.classUnderTest(); set.removeIfWith(Object::equals, "1"); } @Test public void iterator() { MutableSet<String> set = this.classUnderTest(); int size = set.size(); Iterator<String> iterator = set.iterator(); for (int i = size; i-- > 0; ) { String integerString = iterator.next(); Assert.assertEquals(size, Integer.parseInt(integerString) + i); } Verify.assertThrows(NoSuchElementException.class, (Runnable) iterator::next); } @Test(expected = UnsupportedOperationException.class) public void iteratorRemove_throws() { MutableSet<String> set = this.classUnderTest(); set.iterator().remove(); } @Test(expected = NullPointerException.class) public void min_null_throws() { this.classUnderTestWithNull().min(String::compareTo); } @Test(expected = NullPointerException.class) public void max_null_throws() { this.classUnderTestWithNull().max(String::compareTo); } @Test(expected = NullPointerException.class) public void min_null_throws_without_comparator() { this.classUnderTestWithNull().min(); } @Test(expected = NullPointerException.class) public void max_null_throws_without_comparator() { this.classUnderTestWithNull().max(); } protected abstract MutableSet<String> classUnderTestWithNull(); @Test public void iterationWithIterator() { Iterator<String> iterator = this.classUnderTest().iterator(); while (iterator.hasNext()) { this.classUnderTest().contains(iterator.next()); } } @Test(expected = NoSuchElementException.class) public void iteratorWillGetUpsetIfYouPushItTooFar() { Iterator<String> iterator = this.classUnderTest().iterator(); for (int i = 0; i < this.classUnderTest().size() + 1; i++) { iterator.next(); } } @Test public void equalsAndHashCode() { Verify.assertEqualsAndHashCode(UnifiedSet.newSet(this.classUnderTest()), this.classUnderTest()); } @Test public void groupBy() { MutableSet<String> set = this.classUnderTest(); MutableSetMultimap<Boolean, String> multimap = set.groupBy(object -> IntegerPredicates.isOdd().accept(Integer.parseInt(object))); MutableMap<Boolean, RichIterable<String>> actualMap = multimap.toMap(); int halfSize = this.classUnderTest().size() / 2; boolean odd = this.classUnderTest().size() % 2 != 0; Assert.assertEquals(halfSize, Iterate.sizeOf(actualMap.getIfAbsent(false, FastList::new))); Assert.assertEquals(halfSize + (odd ? 1 : 0), Iterate.sizeOf(actualMap.get(true))); } @Test public void groupByEach() { MutableSet<Integer> set = this.classUnderTest().collect(Integer::valueOf); MutableMultimap<Integer, Integer> expected = UnifiedSetMultimap.newMultimap(); set.forEach(Procedures.cast(value -> expected.putAll(-value, Interval.fromTo(value, set.size())))); Multimap<Integer, Integer> actual = set.groupByEach(new NegativeIntervalFunction()); Assert.assertEquals(expected, actual); Multimap<Integer, Integer> actualWithTarget = set.groupByEach(new NegativeIntervalFunction(), UnifiedSetMultimap.<Integer, Integer>newMultimap()); Assert.assertEquals(expected, actualWithTarget); } @Test public void zip() { MutableSet<String> set = this.classUnderTest(); List<Object> nulls = Collections.nCopies(set.size(), null); List<Object> nullsPlusOne = Collections.nCopies(set.size() + 1, null); List<Object> nullsMinusOne = Collections.nCopies(set.size() - 1, null); MutableSet<Pair<String, Object>> pairs = set.zip(nulls); Assert.assertEquals(set, pairs.collect((Function<Pair<String, ?>, String>) Pair::getOne)); Assert.assertEquals(nulls, pairs.collect((Function<Pair<?, Object>, Object>) Pair::getTwo, Lists.mutable.of())); MutableSet<Pair<String, Object>> pairsPlusOne = set.zip(nullsPlusOne); Assert.assertEquals(set, pairsPlusOne.collect((Function<Pair<String, ?>, String>) Pair::getOne)); Assert.assertEquals(nulls, pairsPlusOne.collect((Function<Pair<?, Object>, Object>) Pair::getTwo, Lists.mutable.of())); MutableSet<Pair<String, Object>> pairsMinusOne = set.zip(nullsMinusOne); Assert.assertEquals(set.size() - 1, pairsMinusOne.size()); Assert.assertTrue(set.containsAll(pairsMinusOne.collect((Function<Pair<String, ?>, String>) Pair::getOne))); Assert.assertEquals( set.zip(nulls), set.zip(nulls, UnifiedSet.<Pair<String, Object>>newSet())); } @Test public void zipWithIndex() { MutableSet<String> set = this.classUnderTest(); MutableSet<Pair<String, Integer>> pairs = set.zipWithIndex(); Assert.assertEquals( set, pairs.collect((Function<Pair<String, ?>, String>) Pair::getOne)); Assert.assertEquals( Interval.zeroTo(set.size() - 1).toSet(), pairs.collect((Function<Pair<?, Integer>, Integer>) Pair::getTwo)); Assert.assertEquals( set.zipWithIndex(), set.zipWithIndex(UnifiedSet.<Pair<String, Integer>>newSet())); } @Test public void testClone() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> clone = set.clone(); Assert.assertNotSame(clone, set); Verify.assertEqualsAndHashCode(clone, set); } @Test public void asUnmodifiable() { Verify.assertInstanceOf(UnmodifiableMutableSet.class, this.classUnderTest().asUnmodifiable()); } @Test public void toImmutable() { Verify.assertInstanceOf(ImmutableSet.class, this.classUnderTest().toImmutable()); } @Test public void min() { Assert.assertEquals("1", this.classUnderTest().min(String::compareTo)); } @Test public void max() { Assert.assertEquals("1", this.classUnderTest().max(Comparators.reverse(String::compareTo))); } @Test public void min_without_comparator() { Assert.assertEquals("1", this.classUnderTest().min()); } @Test public void max_without_comparator() { Assert.assertEquals(String.valueOf(this.classUnderTest().size()), this.classUnderTest().max()); } @Test public void minBy() { Assert.assertEquals("1", this.classUnderTest().minBy(String::valueOf)); } @Test public void maxBy() { Assert.assertEquals(String.valueOf(this.classUnderTest().size()), this.classUnderTest().maxBy(String::valueOf)); } @Test public void chunk() { MutableSet<String> set = this.classUnderTest(); RichIterable<RichIterable<String>> chunks = set.chunk(2); MutableList<Integer> sizes = chunks.collect(RichIterable::size, FastList.<Integer>newList()); MutableBag<Integer> hashBag = Bags.mutable.of(); hashBag.addOccurrences(2, this.classUnderTest().size() / 2); if (this.classUnderTest().size() % 2 != 0) { hashBag.add(1); } Assert.assertEquals(hashBag, sizes.toBag()); } @Test(expected = IllegalArgumentException.class) public void chunk_zero_throws() { this.classUnderTest().chunk(0); } @Test public void chunk_large_size() { MutableSet<String> set = this.classUnderTest(); Assert.assertEquals(set, set.chunk(10).getFirst()); } @Test public void union() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> union = set.union(UnifiedSet.newSetWith("a", "b", "c", "1")); Verify.assertSize(set.size() + 3, union); Assert.assertTrue(union.containsAllIterable(Interval.oneTo(set.size()).collect(String::valueOf))); Verify.assertContainsAll(union, "a", "b", "c"); Assert.assertEquals(set, set.union(UnifiedSet.newSetWith("1"))); } @Test public void unionInto() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> union = set.unionInto(UnifiedSet.newSetWith("a", "b", "c", "1"), UnifiedSet.<String>newSet()); Verify.assertSize(set.size() + 3, union); Assert.assertTrue(union.containsAllIterable(Interval.oneTo(set.size()).collect(String::valueOf))); Verify.assertContainsAll(union, "a", "b", "c"); Assert.assertEquals(set, set.unionInto(UnifiedSet.newSetWith("1"), UnifiedSet.<String>newSet())); } @Test public void intersect() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> intersect = set.intersect(UnifiedSet.newSetWith("a", "b", "c", "1")); Verify.assertSize(1, intersect); Assert.assertEquals(UnifiedSet.newSetWith("1"), intersect); Verify.assertEmpty(set.intersect(UnifiedSet.newSetWith("not present"))); } @Test public void intersectInto() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> intersect = set.intersectInto(UnifiedSet.newSetWith("a", "b", "c", "1"), UnifiedSet.<String>newSet()); Verify.assertSize(1, intersect); Assert.assertEquals(UnifiedSet.newSetWith("1"), intersect); Verify.assertEmpty(set.intersectInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet())); } @Test public void difference() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> difference = set.difference(UnifiedSet.newSetWith("2", "3", "4", "not present")); Assert.assertEquals(UnifiedSet.newSetWith("1"), difference); Assert.assertEquals(set, set.difference(UnifiedSet.newSetWith("not present"))); } @Test public void differenceInto() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> difference = set.differenceInto(UnifiedSet.newSetWith("2", "3", "4", "not present"), UnifiedSet.<String>newSet()); Assert.assertEquals(UnifiedSet.newSetWith("1"), difference); Assert.assertEquals(set, set.differenceInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet())); } @Test public void symmetricDifference() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> difference = set.symmetricDifference(UnifiedSet.newSetWith("2", "3", "4", "5", "not present")); Verify.assertContains("1", difference); Assert.assertTrue(difference.containsAllIterable(Interval.fromTo(set.size() + 1, 5).collect(String::valueOf))); for (int i = 2; i <= set.size(); i++) { Verify.assertNotContains(String.valueOf(i), difference); } Verify.assertSize(set.size() + 1, set.symmetricDifference(UnifiedSet.newSetWith("not present"))); } @Test public void symmetricDifferenceInto() { MutableSet<String> set = this.classUnderTest(); MutableSet<String> difference = set.symmetricDifferenceInto( UnifiedSet.newSetWith("2", "3", "4", "5", "not present"), UnifiedSet.<String>newSet()); Verify.assertContains("1", difference); Assert.assertTrue(difference.containsAllIterable(Interval.fromTo(set.size() + 1, 5).collect(String::valueOf))); for (int i = 2; i <= set.size(); i++) { Verify.assertNotContains(String.valueOf(i), difference); } Verify.assertSize( set.size() + 1, set.symmetricDifferenceInto(UnifiedSet.newSetWith("not present"), UnifiedSet.<String>newSet())); } @Test public void isSubsetOf() { MutableSet<String> set = this.classUnderTest(); Assert.assertTrue(set.isSubsetOf(UnifiedSet.newSetWith("1", "2", "3", "4", "5"))); } @Test public void isProperSubsetOf() { MutableSet<String> set = this.classUnderTest(); Assert.assertTrue(set.isProperSubsetOf(UnifiedSet.newSetWith("1", "2", "3", "4", "5"))); Assert.assertFalse(set.isProperSubsetOf(set)); } @Test public void powerSet() { MutableSet<String> set = this.classUnderTest(); MutableSet<UnsortedSetIterable<String>> powerSet = set.powerSet(); Verify.assertSize((int) StrictMath.pow(2, set.size()), powerSet); Verify.assertContains(UnifiedSet.<String>newSet(), powerSet); Verify.assertContains(set, powerSet); } @Test public void cartesianProduct() { MutableSet<String> set = this.classUnderTest(); LazyIterable<Pair<String, String>> cartesianProduct = set.cartesianProduct(UnifiedSet.newSetWith("One", "Two")); Verify.assertIterableSize(set.size() * 2, cartesianProduct); Assert.assertEquals( set, cartesianProduct .select(Predicates.attributeEqual((Function<Pair<?, String>, String>) Pair::getTwo, "One")) .collect((Function<Pair<String, ?>, String>) Pair::getOne).toSet()); } @Test public void with() { MutableSet<String> set = this.classUnderTest(); Assert.assertFalse(set.contains("11")); MutableSet<String> setWith = set.with("11"); Assert.assertTrue(setWith.containsAll(set)); Assert.assertTrue(setWith.contains("11")); Assert.assertSame(setWith, setWith.with("11")); assertSetType(set, setWith); } @Test public void withAll() { MutableSet<String> set = this.classUnderTest(); Verify.assertContainsNone(set, "11", "12"); MutableSet<String> setWith = set.withAll(FastList.newListWith("11", "12")); Assert.assertTrue(setWith.containsAll(set)); Verify.assertContainsAll(setWith, "11", "12"); assertSetType(set, setWith); Assert.assertSame(setWith, setWith.withAll(FastList.<String>newList())); } @Test public void without() { MutableSet<String> set = this.classUnderTest(); Assert.assertSame(set, set.without("11")); MutableList<String> list = set.toList(); list.forEach(Procedures.cast(each -> { MutableSet<String> setWithout = set.without(each); Assert.assertFalse(setWithout.contains(each)); assertSetType(set, setWithout); })); } @Test public void withoutAll() { MutableSet<String> set = this.classUnderTest().with("11").with("12"); MutableSet<String> setWithout = set.withoutAll(FastList.newListWith("11", "12")); Assert.assertTrue(setWithout.containsAll(this.classUnderTest())); Verify.assertContainsNone(setWithout, "11", "12"); assertSetType(set, setWithout); Assert.assertSame(setWithout, setWithout.withoutAll(FastList.<String>newList())); } protected static void assertSetType(MutableSet<?> original, MutableSet<?> modified) { if (original instanceof FixedSizeSet && modified.size() < 5) { Verify.assertInstanceOf(FixedSizeSet.class, modified); } else { Verify.assertInstanceOf(UnifiedSet.class, modified); } } }