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