11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.MapMakerInternalMap.Strength.SOFT; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.MapMakerInternalMap.Strength.STRONG; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.MapMakerInternalMap.Strength.WEAK; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.testing.IteratorFeature.SUPPORTS_REMOVE; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.testing.SerializableTester.reserializeAndAssert; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.Arrays.asList; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static org.easymock.EasyMock.eq; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static org.easymock.EasyMock.expect; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static org.easymock.EasyMock.isA; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalences; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.MapMaker.RemovalListener; 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.MapMaker.RemovalNotification; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Multiset.Entry; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.IteratorTester; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport org.easymock.EasyMock; 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator; 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentMap; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit; 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicInteger; 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Test case for {@link ConcurrentHashMultiset}. 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Cliff L. Biffle 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author mike nonemacher 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class ConcurrentHashMultisetTest extends TestCase { 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final String KEY = "puppies"; 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentMap<String, AtomicInteger> backingMap; 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset; 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void setUp() { 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert backingMap = EasyMock.createMock(ConcurrentMap.class); 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.isEmpty()).andReturn(true); 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = new ConcurrentHashMultiset<String>(backingMap); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reset(); 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCount_elementPresent() { 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int COUNT = 12; 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(new AtomicInteger(COUNT)); 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(COUNT, multiset.count(KEY)); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCount_elementAbsent() { 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.count(KEY)); 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAdd_zero() { 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int INITIAL_COUNT = 32; 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(new AtomicInteger(INITIAL_COUNT)); 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(INITIAL_COUNT, multiset.add(KEY, 0)); 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAdd_firstFewWithSuccess() { 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int COUNT = 400; 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.putIfAbsent(eq(KEY), isA(AtomicInteger.class))).andReturn(null); 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.add(KEY, COUNT)); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAdd_laterFewWithSuccess() { 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int INITIAL_COUNT = 32; 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int COUNT_TO_ADD = 400; 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger initial = new AtomicInteger(INITIAL_COUNT); 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(initial); 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(INITIAL_COUNT, multiset.add(KEY, COUNT_TO_ADD)); 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(INITIAL_COUNT + COUNT_TO_ADD, initial.get()); 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAdd_laterFewWithOverflow() { 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int INITIAL_COUNT = 92384930; 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int COUNT_TO_ADD = Integer.MAX_VALUE - INITIAL_COUNT + 1; 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(new AtomicInteger(INITIAL_COUNT)); 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(KEY, COUNT_TO_ADD); 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("Must reject arguments that would cause counter overflow."); 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IllegalArgumentException e) { 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Expected. 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Simulate some of the races that can happen on add. We can't easily simulate the race that 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * happens when an {@link AtomicInteger#compareAndSet} fails, but we can simulate the case where 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the putIfAbsent returns a non-null value, and the case where the replace() of an observed 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * zero fails. 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAdd_withFailures() { 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger existing = new AtomicInteger(12); 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger existingZero = new AtomicInteger(0); 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // initial map.get() 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // since get returned null, try a putIfAbsent; that fails due to a simulated race 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.putIfAbsent(eq(KEY), isA(AtomicInteger.class))).andReturn(existingZero); 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // since the putIfAbsent returned a zero, we'll try to replace... 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.replace(eq(KEY), eq(existingZero), isA(AtomicInteger.class))) 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .andReturn(false); 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // ...and then putIfAbsent. Simulate failure on both 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.putIfAbsent(eq(KEY), isA(AtomicInteger.class))).andReturn(existing); 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // next map.get() 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(existingZero); 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // since get returned zero, try a replace; that fails due to a simulated race 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.replace(eq(KEY), eq(existingZero), isA(AtomicInteger.class))) 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .andReturn(false); 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.putIfAbsent(eq(KEY), isA(AtomicInteger.class))).andReturn(existing); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // another map.get() 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(existing); 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // we shouldn't see any more map operations; CHM will now just update the AtomicInteger 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(multiset.add(KEY, 3), 12); 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(15, existing.get()); 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRemove_zeroFromSome() { 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int INITIAL_COUNT = 14; 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(new AtomicInteger(INITIAL_COUNT)); 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(INITIAL_COUNT, multiset.remove(KEY, 0)); 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRemove_zeroFromNone() { 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.remove(KEY, 0)); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRemove_nonePresent() { 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.remove(KEY, 400)); 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRemove_someRemaining() { 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int countToRemove = 30; 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int countRemaining = 1; 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger current = new AtomicInteger(countToRemove + countRemaining); 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(current); 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countToRemove + countRemaining, multiset.remove(KEY, countToRemove)); 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countRemaining, current.get()); 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRemove_noneRemaining() { 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int countToRemove = 30; 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger current = new AtomicInteger(countToRemove); 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(current); 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // it's ok if removal fails: another thread may have done the remove 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.remove(KEY, current)).andReturn(false); 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countToRemove, multiset.remove(KEY, countToRemove)); 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, current.get()); 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIteratorRemove_actualMap() { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Override to avoid using mocks. 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(); 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(KEY); 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(KEY + "_2"); 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(KEY); 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int mutations = 0; 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Iterator<String> it = multiset.iterator(); it.hasNext(); ) { 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert it.next(); 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert it.remove(); 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert mutations++; 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.isEmpty()); 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, mutations); 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIterator() { 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // multiset.iterator 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<String> expected = asList("a", "a", "b", "b", "b"); 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new IteratorTester<String>( 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5, asList(SUPPORTS_REMOVE), expected, IteratorTester.KnownOrder.UNKNOWN_ORDER) { 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset; 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Iterator<String> newTargetIterator() { 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(); 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("a", 2); 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("b", 3); 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return multiset.iterator(); 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void verify(List<String> elements) { 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super.verify(elements); 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ImmutableMultiset.copyOf(elements), multiset); 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }.test(); 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testEntryIterator() { 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // multiset.entryIterator 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<Entry<String>> expected = asList( 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Multisets.immutableEntry("a", 1), 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Multisets.immutableEntry("b", 2), 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Multisets.immutableEntry("c", 3), 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Multisets.immutableEntry("d", 4), 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Multisets.immutableEntry("e", 5)); 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new IteratorTester<Entry<String>>( 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5, asList(SUPPORTS_REMOVE), expected, IteratorTester.KnownOrder.UNKNOWN_ORDER) { 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset; 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Iterator<Entry<String>> newTargetIterator() { 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(); 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("a", 1); 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("b", 2); 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("c", 3); 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("d", 4); 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("e", 5); 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return multiset.entryIterator(); 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void verify(List<Entry<String>> elements) { 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super.verify(elements); 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ImmutableSet.copyOf(elements), ImmutableSet.copyOf(multiset.entryIterator())); 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }.test(); 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSetCount_basic() { 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int initialCount = 20; 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int countToSet = 40; 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger current = new AtomicInteger(initialCount); 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(current); 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(initialCount, multiset.setCount(KEY, countToSet)); 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countToSet, current.get()); 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSetCount_asRemove() { 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int countToRemove = 40; 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger current = new AtomicInteger(countToRemove); 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(current); 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.remove(KEY, current)).andReturn(true); 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countToRemove, multiset.setCount(KEY, 0)); 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, current.get()); 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSetCount_0_nonePresent() { 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expect(backingMap.get(KEY)).andReturn(null); 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert replay(); 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.setCount(KEY, 0)); 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(); 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCreate() { 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<Integer> multiset = ConcurrentHashMultiset.create(); 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.isEmpty()); 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reserializeAndAssert(multiset); 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCreateFromIterable() { 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterable<Integer> iterable = asList(1, 2, 2, 3, 4); 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<Integer> multiset 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = ConcurrentHashMultiset.create(iterable); 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(2, multiset.count(2)); 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reserializeAndAssert(multiset); 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIdentityKeyEquality_strongKeys() { 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testIdentityKeyEquality(STRONG); 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIdentityKeyEquality_softKeys() { 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testIdentityKeyEquality(SOFT); 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIdentityKeyEquality_weakKeys() { 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testIdentityKeyEquality(WEAK); 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void testIdentityKeyEquality( 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMakerInternalMap.Strength keyStrength) { 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker() 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .setKeyStrength(keyStrength) 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .keyEquivalence(Equivalences.identity()); 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset = 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset.create(mapMaker); 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s1 = new String("a"); 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s2 = new String("a"); 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(s1, s2); // Stating the obvious. 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(s1 != s2); // Stating the obvious. 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s1); 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains(s1)); 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(multiset.contains(s2)); 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, multiset.count(s1)); 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.count(s2)); 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s1); 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s2, 3); 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(2, multiset.count(s1)); 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, multiset.count(s2)); 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.remove(s1); 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, multiset.count(s1)); 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, multiset.count(s2)); 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testLogicalKeyEquality_strongKeys() { 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testLogicalKeyEquality(STRONG); 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testLogicalKeyEquality_softKeys() { 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testLogicalKeyEquality(SOFT); 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testLogicalKeyEquality_weakKeys() { 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testLogicalKeyEquality(WEAK); 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void testLogicalKeyEquality( 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMakerInternalMap.Strength keyStrength) { 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker() 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .setKeyStrength(keyStrength) 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .keyEquivalence(Equivalences.equals()); 4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset = 4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset.create(mapMaker); 4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s1 = new String("a"); 4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s2 = new String("a"); 4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(s1, s2); // Stating the obvious. 4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s1); 4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains(s1)); 4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains(s2)); 4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, multiset.count(s1)); 4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, multiset.count(s2)); 4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s2, 3); 4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(4, multiset.count(s1)); 4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(4, multiset.count(s2)); 4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.remove(s1); 4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, multiset.count(s1)); 4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, multiset.count(s2)); 4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSerializationWithMapMaker1() { 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker(); 4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(mapMaker); 4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reserializeAndAssert(multiset); 4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSerializationWithMapMaker2() { 4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker(); 4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(mapMaker); 4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.addAll(ImmutableList.of("a", "a", "b", "c", "d", "b")); 4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reserializeAndAssert(multiset); 4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSerializationWithMapMaker3() { 4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker().expireAfterWrite(1, TimeUnit.SECONDS); 4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = ConcurrentHashMultiset.create(mapMaker); 4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.addAll(ImmutableList.of("a", "a", "b", "c", "d", "b")); 4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert reserializeAndAssert(multiset); 4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSerializationWithMapMaker_preservesIdentityKeyEquivalence() { 4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker = new MapMaker() 4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .keyEquivalence(Equivalences.identity()); 4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset = 4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset.create(mapMaker); 4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset = reserializeAndAssert(multiset); 4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s1 = new String("a"); 4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String s2 = new String("a"); 4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(s1, s2); // Stating the obvious. 4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(s1 != s2); // Stating the obvious. 4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add(s1); 4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains(s1)); 4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(multiset.contains(s2)); 4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, multiset.count(s1)); 4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, multiset.count(s2)); 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// @Suppress(owner = "bmanes", detail = "Does not call the eviction listener") 4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// public void testWithMapMakerEvictionListener_BROKEN1() 4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// throws InterruptedException { 4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// MapEvictionListener<String, Number> evictionListener = 4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// mockEvictionListener(); 4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// evictionListener.onEviction("a", 5); 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// EasyMock.replay(evictionListener); 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// GenericMapMaker<String, Number> mapMaker = new MapMaker() 4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// .expireAfterWrite(100, TimeUnit.MILLISECONDS) 4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// .evictionListener(evictionListener); 4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// ConcurrentHashMultiset<String> multiset = 4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// ConcurrentHashMultiset.create(mapMaker); 4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// multiset.add("a", 5); 4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// assertTrue(multiset.contains("a")); 4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// assertEquals(5, multiset.count("a")); 4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Thread.sleep(2000); 4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// EasyMock.verify(evictionListener); 4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// } 4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// @Suppress(owner = "bmanes", detail = "Does not call the eviction listener") 4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// public void testWithMapMakerEvictionListener_BROKEN2() 4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// throws InterruptedException { 4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// MapEvictionListener<String, Number> evictionListener = 4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// mockEvictionListener(); 4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// evictionListener.onEviction("a", 5); 4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// EasyMock.replay(evictionListener); 4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// GenericMapMaker<String, Number> mapMaker = new MapMaker() 5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// .expireAfterWrite(100, TimeUnit.MILLISECONDS) 5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// .evictionListener(evictionListener); 5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// ConcurrentHashMultiset<String> multiset = 5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// ConcurrentHashMultiset.create(mapMaker); 5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// multiset.add("a", 5); 5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// assertTrue(multiset.contains("a")); 5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// assertEquals(5, multiset.count("a")); 5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Thread.sleep(2000); 5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// // This call should have the side-effect of calling the 5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// // eviction listener, but it does not. 5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// assertFalse(multiset.contains("a")); 5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// EasyMock.verify(evictionListener); 5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// } 5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testWithMapMakerEvictionListener() { 5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final List<RemovalNotification<String, Number>> notificationQueue = Lists.newArrayList(); 5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RemovalListener<String, Number> removalListener = 5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new RemovalListener<String, Number>() { 5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void onRemoval(RemovalNotification<String, Number> notification) { 5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert notificationQueue.add(notification); 5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("deprecation") // TODO(kevinb): what to do? 5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GenericMapMaker<String, Number> mapMaker = new MapMaker() 5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .concurrencyLevel(1) 5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .maximumSize(1) 5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .removalListener(removalListener); 5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ConcurrentHashMultiset<String> multiset = ConcurrentHashMultiset.create(mapMaker); 5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("a", 5); 5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains("a")); 5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(5, multiset.count("a")); 5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiset.add("b", 3); 5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(multiset.contains("a")); 5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(multiset.contains("b")); 5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(3, multiset.count("b")); 5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RemovalNotification<String, Number> notification = Iterables.getOnlyElement(notificationQueue); 5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("a", notification.getKey()); 5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // The map evicted this entry, so CHM didn't have a chance to zero it. 5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(5, notification.getValue().intValue()); 5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void replay() { 5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EasyMock.replay(backingMap); 5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void verify() { 5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EasyMock.verify(backingMap); 5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void reset() { 5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EasyMock.reset(backingMap); 5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 565