--- jsr166/src/test/tck/ConcurrentHashMapTest.java 2015/01/15 18:34:19 1.41 +++ jsr166/src/test/tck/ConcurrentHashMapTest.java 2016/08/22 18:38:28 1.50 @@ -16,13 +16,15 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import junit.framework.Test; import junit.framework.TestSuite; public class ConcurrentHashMapTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } public static Test suite() { return new TestSuite(ConcurrentHashMapTest.class); @@ -45,7 +47,9 @@ public class ConcurrentHashMapTest exten } /** Re-implement Integer.compare for old java versions */ - static int compare(int x, int y) { return x < y ? -1 : x > y ? 1 : 0; } + static int compare(int x, int y) { + return (x < y) ? -1 : (x > y) ? 1 : 0; + } // classes for testing Comparable fallbacks static class BI implements Comparable { @@ -287,6 +291,7 @@ public class ConcurrentHashMapTest exten assertEquals("A", (String)map.get(one)); ConcurrentHashMap empty = new ConcurrentHashMap(); assertNull(map.get("anything")); + assertNull(empty.get("anything")); } /** @@ -328,6 +333,21 @@ public class ConcurrentHashMapTest exten } /** + * Test keySet().removeAll on empty map + */ + public void testKeySet_empty_removeAll() { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + Set set = map.keySet(); + set.removeAll(Collections.emptyList()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + // following is test for JDK-8163353 + set.removeAll(Collections.emptySet()); + assertTrue(map.isEmpty()); + assertTrue(set.isEmpty()); + } + + /** * keySet.toArray returns contains all keys */ public void testKeySetToArray() { @@ -532,17 +552,17 @@ public class ConcurrentHashMapTest exten /** * Constructor (initialCapacity, loadFactor) throws * IllegalArgumentException if either argument is negative - */ + */ public void testConstructor2() { try { new ConcurrentHashMap(-1, .75f); shouldThrow(); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException success) {} try { new ConcurrentHashMap(16, -1); shouldThrow(); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException success) {} } /** @@ -553,17 +573,17 @@ public class ConcurrentHashMapTest exten try { new ConcurrentHashMap(-1, .75f, 1); shouldThrow(); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException success) {} try { new ConcurrentHashMap(16, -1, 1); shouldThrow(); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException success) {} try { new ConcurrentHashMap(16, .75f, -1); shouldThrow(); - } catch (IllegalArgumentException e) {} + } catch (IllegalArgumentException success) {} } /** @@ -574,7 +594,7 @@ public class ConcurrentHashMapTest exten try { new ConcurrentHashMap(null); shouldThrow(); - } catch (NullPointerException e) {} + } catch (NullPointerException success) {} } /** @@ -593,8 +613,8 @@ public class ConcurrentHashMapTest exten * get(null) throws NPE */ public void testGet_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.get(null); shouldThrow(); } catch (NullPointerException success) {} @@ -604,8 +624,8 @@ public class ConcurrentHashMapTest exten * containsKey(null) throws NPE */ public void testContainsKey_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.containsKey(null); shouldThrow(); } catch (NullPointerException success) {} @@ -615,8 +635,8 @@ public class ConcurrentHashMapTest exten * containsValue(null) throws NPE */ public void testContainsValue_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.containsValue(null); shouldThrow(); } catch (NullPointerException success) {} @@ -626,8 +646,8 @@ public class ConcurrentHashMapTest exten * contains(null) throws NPE */ public void testContains_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.contains(null); shouldThrow(); } catch (NullPointerException success) {} @@ -637,8 +657,8 @@ public class ConcurrentHashMapTest exten * put(null,x) throws NPE */ public void testPut1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.put(null, "whatever"); shouldThrow(); } catch (NullPointerException success) {} @@ -648,8 +668,8 @@ public class ConcurrentHashMapTest exten * put(x, null) throws NPE */ public void testPut2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.put("whatever", null); shouldThrow(); } catch (NullPointerException success) {} @@ -659,8 +679,8 @@ public class ConcurrentHashMapTest exten * putIfAbsent(null, x) throws NPE */ public void testPutIfAbsent1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.putIfAbsent(null, "whatever"); shouldThrow(); } catch (NullPointerException success) {} @@ -670,8 +690,8 @@ public class ConcurrentHashMapTest exten * replace(null, x) throws NPE */ public void testReplace_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.replace(null, "whatever"); shouldThrow(); } catch (NullPointerException success) {} @@ -681,8 +701,8 @@ public class ConcurrentHashMapTest exten * replace(null, x, y) throws NPE */ public void testReplaceValue_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.replace(null, one, "whatever"); shouldThrow(); } catch (NullPointerException success) {} @@ -692,8 +712,8 @@ public class ConcurrentHashMapTest exten * putIfAbsent(x, null) throws NPE */ public void testPutIfAbsent2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.putIfAbsent("whatever", null); shouldThrow(); } catch (NullPointerException success) {} @@ -703,8 +723,8 @@ public class ConcurrentHashMapTest exten * replace(x, null) throws NPE */ public void testReplace2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.replace("whatever", null); shouldThrow(); } catch (NullPointerException success) {} @@ -714,8 +734,8 @@ public class ConcurrentHashMapTest exten * replace(x, null, y) throws NPE */ public void testReplaceValue2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.replace("whatever", null, "A"); shouldThrow(); } catch (NullPointerException success) {} @@ -725,8 +745,8 @@ public class ConcurrentHashMapTest exten * replace(x, y, null) throws NPE */ public void testReplaceValue3_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); c.replace("whatever", one, null); shouldThrow(); } catch (NullPointerException success) {} @@ -736,9 +756,9 @@ public class ConcurrentHashMapTest exten * remove(null) throws NPE */ public void testRemove1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + c.put("sadsdf", "asdads"); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); - c.put("sadsdf", "asdads"); c.remove(null); shouldThrow(); } catch (NullPointerException success) {} @@ -748,9 +768,9 @@ public class ConcurrentHashMapTest exten * remove(null, x) throws NPE */ public void testRemove2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + c.put("sadsdf", "asdads"); try { - ConcurrentHashMap c = new ConcurrentHashMap(5); - c.put("sadsdf", "asdads"); c.remove(null, "whatever"); shouldThrow(); } catch (NullPointerException success) {} @@ -800,4 +820,47 @@ public class ConcurrentHashMapTest exten } } + /** + * Tests performance of removeAll when the other collection is much smaller. + * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testRemoveAll_performance -Djsr166.expensiveTests=true tck + */ + public void testRemoveAll_performance() { + final int mapSize = expensiveTests ? 1_000_000 : 100; + final int iterations = expensiveTests ? 500 : 2; + final ConcurrentHashMap map = new ConcurrentHashMap<>(); + for (int i = 0; i < mapSize; i++) + map.put(i, i); + Set keySet = map.keySet(); + Collection removeMe = Arrays.asList(new Integer[] { -99, -86 }); + for (int i = 0; i < iterations; i++) + assertFalse(keySet.removeAll(removeMe)); + assertEquals(mapSize, map.size()); + } + + /** + * Tests performance of computeIfAbsent when the element is present. + * See JDK-8161372 + * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testcomputeIfAbsent_performance -Djsr166.expensiveTests=true tck + */ + public void testcomputeIfAbsent_performance() { + final int mapSize = 20; + final int iterations = expensiveTests ? (1 << 23) : mapSize * 2; + final int threads = expensiveTests ? 10 : 2; + final ConcurrentHashMap map = new ConcurrentHashMap<>(); + for (int i = 0; i < mapSize; i++) + map.put(i, i); + final ExecutorService pool = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(pool)) { + Runnable r = new CheckedRunnable() { + public void realRun() { + int result = 0; + for (int i = 0; i < iterations; i++) + result += map.computeIfAbsent(i % mapSize, (k) -> k + k); + if (result == -42) throw new Error(); + }}; + for (int i = 0; i < threads; i++) + pool.execute(r); + } + } + }