/* * Copyright 2011 Google Inc. All Rights Reserved. * * 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.googlecode.concurrentlinkedhashmap; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder; import org.mockito.Mock; import org.testng.annotations.Test; import static com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.MAXIMUM_CAPACITY; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static java.util.Collections.singletonMap; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import static org.testng.Assert.fail; /** * A unit-test for the weigher algorithms and that the map keeps track of the * weighted sizes. * * @author ben.manes@gmail.com (Ben Manes) */ @Test(groups = "development") public final class WeigherTest extends AbstractTest { @Mock Iterable<Integer> iterable; @Test(expectedExceptions = AssertionError.class) public void constructor() throws Throwable { try { Constructor<?> constructors[] = Weighers.class.getDeclaredConstructors(); assertThat(constructors.length, is(1)); constructors[0].setAccessible(true); constructors[0].newInstance((Object[]) null); fail("Expected a failure to instantiate"); } catch (InvocationTargetException e) { throw e.getCause(); } } @Test(dataProvider = "collectionWeigher") public void asEntryWeigher(Weigher<Collection<?>> weigher) { EntryWeigher<Collection<?>, Collection<?>> entryWeigher = Weighers.asEntryWeigher(weigher); assertThat(entryWeigher.weightOf(emptyList(), emptyList()), is(0)); assertThat(entryWeigher.weightOf(asList(1), asList(1)), is(1)); assertThat(entryWeigher.weightOf(asList(1, 2, 3), asList(1, 2, 3)), is(3)); } @Test(dataProvider = "singletonEntryWeigher") public void singleton_entry(EntryWeigher<Object, Object> weigher) { assertThat(weigher.weightOf(new Object(), new Object()), is(1)); assertThat(weigher.weightOf(emptyList(), emptyList()), is(1)); assertThat(weigher.weightOf(asList(1, 2, 3), asList(1, 2, 3)), is(1)); } @Test(dataProvider = "singletonWeigher") public void singleton(Weigher<Object> weigher) { assertThat(weigher.weightOf(new Object()), is(1)); assertThat(weigher.weightOf(emptyList()), is(1)); assertThat(weigher.weightOf(asList(1, 2, 3)), is(1)); } @Test(dataProvider = "byteArrayWeigher") public void byteArray(Weigher<byte[]> weigher) { assertThat(weigher.weightOf(new byte[] {}), is(0)); assertThat(weigher.weightOf(new byte[] {1}), is(1)); assertThat(weigher.weightOf(new byte[] {1, 2, 3}), is(3)); } @Test(dataProvider = "iterableWeigher") public void iterable(Weigher<Iterable<?>> weigher) { when(iterable.iterator()) .thenReturn(ImmutableList.<Integer>of().iterator()) .thenReturn(ImmutableList.<Integer>of(1, 2, 3).iterator()); assertThat(weigher.weightOf(emptyList()), is(0)); assertThat(weigher.weightOf(iterable), is(0)); assertThat(weigher.weightOf(asList(1)), is(1)); assertThat(weigher.weightOf(asList(1, 2, 3)), is(3)); assertThat(weigher.weightOf(iterable), is(3)); } @Test(dataProvider = "collectionWeigher") public void collection(Weigher<Collection<?>> weigher) { assertThat(weigher.weightOf(emptyList()), is(0)); assertThat(weigher.weightOf(asList(1)), is(1)); assertThat(weigher.weightOf(asList(1, 2, 3)), is(3)); } @Test(dataProvider = "listWeigher") public void list(Weigher<List<?>> weigher) { assertThat(weigher.weightOf(emptyList()), is(0)); assertThat(weigher.weightOf(asList(1)), is(1)); assertThat(weigher.weightOf(asList(1, 2, 3)), is(3)); } @Test(dataProvider = "setWeigher") public void set(Weigher<Set<?>> weigher) { assertThat(weigher.weightOf(emptySet()), is(0)); assertThat(weigher.weightOf(ImmutableSet.of(1)), is(1)); assertThat(weigher.weightOf(ImmutableSet.of(1, 2, 3)), is(3)); } @Test(dataProvider = "mapWeigher") public void map(Weigher<Map<?, ?>> weigher) { assertThat(weigher.weightOf(emptyMap()), is(0)); assertThat(weigher.weightOf(singletonMap(1, 2)), is(1)); assertThat(weigher.weightOf(ImmutableMap.of(1, 2, 2, 3, 3, 4)), is(3)); } @Test(dataProvider = "builder", expectedExceptions = IllegalArgumentException.class) public void put_withNegativeWeight(Builder<Integer, Integer> builder) { ConcurrentLinkedHashMap<Integer, Integer> map = builder .maximumWeightedCapacity(capacity()) .weigher(weigher).build(); when(weigher.weightOf(anyInt())).thenReturn(-1); map.put(1, 2); } @Test(dataProvider = "builder", expectedExceptions = IllegalArgumentException.class) public void put_withZeroWeight(Builder<Integer, Integer> builder) { ConcurrentLinkedHashMap<Integer, Integer> map = builder .maximumWeightedCapacity(capacity()) .weigher(weigher).build(); doReturn(0).when(weigher).weightOf(anyInt()); map.put(1, 2); } @Test(dataProvider = "builder") public void put_withNoOverflow(Builder<Integer, Integer> builder) { ConcurrentLinkedHashMap<Integer, Integer> map = builder .maximumWeightedCapacity(MAXIMUM_CAPACITY) .weigher(weigher) .build(); doReturn(Integer.MAX_VALUE).when(weigher).weightOf(anyInt()); map.putAll(ImmutableMap.of(1, 1, 2, 2)); map.weightedSize.set(MAXIMUM_CAPACITY); map.put(3, 3); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(MAXIMUM_CAPACITY)); } @Test(dataProvider = "guardedWeightedMap") public void put(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.put("a", asList(1, 2, 3)); assertThat(map.size(), is(1)); assertThat(map.weightedSize(), is(3L)); } @Test(dataProvider = "guardedWeightedMap") public void put_sameWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.put("a", asList(-1, -2, -3)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(4L)); } @Test(dataProvider = "guardedWeightedMap") public void put_changeWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.put("a", asList(-1, -2, -3, -4)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(5L)); } @Test(dataProvider = "guardedWeightedMap") public void replace_sameWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.replace("a", asList(-1, -2, -3)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(4L)); } @Test(dataProvider = "guardedWeightedMap") public void replace_changeWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.replace("a", asList(-1, -2, -3, -4)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(5L)); } @Test(dataProvider = "guardedWeightedMap") public void replaceConditionally_sameWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); assertThat(map.replace("a", asList(1, 2, 3), asList(4, 5, 6)), is(true)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(4L)); } @Test(dataProvider = "guardedWeightedMap") public void replaceConditionally_changeWeight(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.replace("a", asList(1, 2, 3), asList(-1, -2, -3, -4)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(5L)); } @Test(dataProvider = "guardedWeightedMap") public void replaceConditionally_fails(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); assertThat(map.replace("a", asList(1), asList(4, 5)), is(false)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(4L)); } @Test(dataProvider = "guardedWeightedMap") public void remove(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); assertThat(map.remove("a"), is(asList(1, 2, 3))); assertThat(map.size(), is(1)); assertThat(map.weightedSize(), is(1L)); } @Test(dataProvider = "guardedWeightedMap") public void removeConditionally(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); assertThat(map.remove("a", asList(1, 2, 3)), is(true)); assertThat(map.size(), is(1)); assertThat(map.weightedSize(), is(1L)); } @Test(dataProvider = "guardedWeightedMap") public void removeConditionally_fails(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); assertThat(map.remove("a", asList(-1, -2, -3)), is(false)); assertThat(map.size(), is(2)); assertThat(map.weightedSize(), is(4L)); } @Test(dataProvider = "guardedWeightedMap") public void clear(ConcurrentLinkedHashMap<String, List<Integer>> map) { map.putAll(ImmutableMap.of("a", asList(1, 2, 3), "b", asList(1))); map.clear(); assertThat(map.size(), is(0)); assertThat(map.weightedSize(), is(0L)); } }