// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.collections; import org.junit.Test; import org.mockito.Mockito; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Simon Thoresen Hult */ public class LazySetTest { @Test public void requireThatInitialDelegateIsEmpty() { LazySet set = newLazySet(new HashSet()); assertEquals(LazySet.EmptySet.class, set.getDelegate().getClass()); } @Test public void requireThatEmptySetAddUpgradesToSingletonSet() { LazySet set = newLazySet(new HashSet()); assertTrue(set.add("foo")); assertEquals(LazySet.SingletonSet.class, set.getDelegate().getClass()); set = newLazySet(new HashSet()); assertTrue(set.addAll(Arrays.asList("foo"))); assertEquals(LazySet.SingletonSet.class, set.getDelegate().getClass()); } @Test public void requireThatEmptySetAddAllEmptySetDoesNotUpgradeToSingletonSet() { LazySet set = newLazySet(new HashSet()); assertFalse(set.addAll(Collections.emptySet())); assertEquals(LazySet.EmptySet.class, set.getDelegate().getClass()); } @Test public void requireThatEmptySetAddAllUpgradesToFinalSet() { Set delegate = new HashSet<>(); LazySet set = newLazySet(delegate); assertTrue(set.addAll(Arrays.asList("foo", "bar"))); assertSame(delegate, set.getDelegate()); assertEquals(2, delegate.size()); assertTrue(delegate.contains("foo")); assertTrue(delegate.contains("bar")); } @Test public void requireThatSingletonSetRemoveEntryDowngradesToEmptySet() { LazySet set = newSingletonSet("foo"); assertTrue(set.remove("foo")); assertEquals(LazySet.EmptySet.class, set.getDelegate().getClass()); } @Test public void requireThatSingletonSetRemoveUnknownDoesNotDowngradesToEmptySet() { LazySet set = newSingletonSet("foo"); assertFalse(set.remove("bar")); assertEquals(LazySet.SingletonSet.class, set.getDelegate().getClass()); } @Test public void requireThatSingletonSetAddAllEmptySetDoesNotUpgradeToFinalSet() { LazySet set = newSingletonSet("foo"); assertFalse(set.addAll(Collections.emptySet())); assertEquals(LazySet.SingletonSet.class, set.getDelegate().getClass()); } @Test public void requireThatSingletonSetAddKnownDoesNotUpgradeToFinalSet() { LazySet set = newSingletonSet("foo"); assertFalse(set.add("foo")); assertEquals(LazySet.SingletonSet.class, set.getDelegate().getClass()); } @Test public void requireThatSingletonSetAddUpgradesToFinalSet() { Set delegate = new HashSet<>(); LazySet set = newSingletonSet(delegate, "foo"); assertTrue(set.add("bar")); assertSame(delegate, set.getDelegate()); assertEquals(2, delegate.size()); assertTrue(delegate.contains("foo")); assertTrue(delegate.contains("bar")); } @Test public void requireThatSingletonSetAddAllUpgradesToFinalSet() { Set delegate = new HashSet<>(); LazySet set = newSingletonSet(delegate, "foo"); assertTrue(set.addAll(Arrays.asList("bar"))); assertSame(delegate, set.getDelegate()); assertEquals(2, delegate.size()); assertTrue(delegate.contains("foo")); assertTrue(delegate.contains("bar")); delegate = new HashSet<>(); set = newSingletonSet(delegate, "foo"); assertTrue(set.addAll(Arrays.asList("bar", "baz"))); assertSame(delegate, set.getDelegate()); assertEquals(3, delegate.size()); assertTrue(delegate.contains("foo")); assertTrue(delegate.contains("bar")); assertTrue(delegate.contains("baz")); } @Test public void requireThatSingletonIteratorNextThrowsIfInvokedMoreThanOnce() { LazySet set = newSingletonSet("foo"); Iterator it = set.iterator(); it.next(); try { it.next(); fail(); } catch (NoSuchElementException e) { } try { it.next(); fail(); } catch (NoSuchElementException e) { } } @Test public void requireThatSingletonIteratorRemoveDowngradesToEmptySet() { LazySet set = newSingletonSet("foo"); Iterator it = set.iterator(); it.next(); it.remove(); assertEquals(LazySet.EmptySet.class, set.getDelegate().getClass()); } @Test public void requireThatSingletonIteratorRemoveThrowsIfInvokedBeforeNext() { LazySet set = newSingletonSet("foo"); Iterator it = set.iterator(); try { it.remove(); fail(); } catch (IllegalStateException e) { } } @SuppressWarnings("unchecked") private static Set makeMockSet() { return Mockito.mock(Set.class); } @Test public void requireThatSetDelegates() { Set delegate = makeMockSet(); Set set = newLazySet(delegate); set.add("foo"); set.add("bar"); // trigger the assignment of the delegate Mockito.verify(delegate).add("foo"); Mockito.verify(delegate).add("bar"); Set addAllArg = Collections.singleton("foo"); set.addAll(addAllArg); Mockito.verify(delegate).addAll(addAllArg); assertEquals(0, set.size()); Mockito.verify(delegate).size(); assertFalse(set.isEmpty()); Mockito.verify(delegate).isEmpty(); assertFalse(set.contains("foo")); Mockito.verify(delegate).contains("foo"); assertNull(set.iterator()); Mockito.verify(delegate).iterator(); assertNull(set.toArray()); Mockito.verify(delegate).toArray(); String[] toArrayArg = new String[69]; assertNull(set.toArray(toArrayArg)); Mockito.verify(delegate).toArray(toArrayArg); assertFalse(set.remove("foo")); Mockito.verify(delegate).remove("foo"); Collection containsAllArg = Collections.singletonList("foo"); assertFalse(set.containsAll(containsAllArg)); Mockito.verify(delegate).containsAll(containsAllArg); Collection retainAllArg = Collections.singletonList("foo"); assertFalse(set.retainAll(retainAllArg)); Mockito.verify(delegate).retainAll(retainAllArg); Collection removeAllArg = Collections.singletonList("foo"); assertFalse(set.removeAll(removeAllArg)); Mockito.verify(delegate).removeAll(removeAllArg); set.clear(); Mockito.verify(delegate).clear(); } @Test public void requireThatHashCodeIsImplemented() { assertEquals(newLazySet(null).hashCode(), newLazySet(null).hashCode()); } @Test public void requireThatEqualsIsImplemented() { Set lhs = newLazySet(new HashSet<>()); Set rhs = newLazySet(new HashSet<>()); assertEquals(lhs, lhs); assertEquals(lhs, rhs); Object obj = new Object(); lhs.add(obj); assertEquals(lhs, lhs); assertFalse(lhs.equals(rhs)); rhs.add(obj); assertEquals(lhs, rhs); } @Test public void requireThatHashSetFactoryDelegatesToAHashSet() { LazySet set = LazySet.newHashSet(); set.add(6); set.add(9); assertEquals(HashSet.class, set.getDelegate().getClass()); } private static LazySet newSingletonSet(E element) { return newSingletonSet(new HashSet(), element); } private static LazySet newSingletonSet(Set delegate, E element) { LazySet set = newLazySet(delegate); set.add(element); return set; } private static LazySet newLazySet(final Set delegate) { return new LazySet() { @Override protected Set newDelegate() { return delegate; } }; } }