--- jsr166/src/test/tck/ConcurrentHashMap8Test.java 2014/12/31 21:39:07 1.20 +++ jsr166/src/test/tck/ConcurrentHashMap8Test.java 2018/01/07 23:31:01 1.36 @@ -11,13 +11,13 @@ import static java.util.Spliterator.NONN import java.util.AbstractMap; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.Spliterator; -import java.util.Vector; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.LongAdder; import java.util.function.BiFunction; @@ -27,7 +27,7 @@ import junit.framework.TestSuite; public class ConcurrentHashMap8Test extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } public static Test suite() { return new TestSuite(ConcurrentHashMap8Test.class); @@ -63,7 +63,7 @@ public class ConcurrentHashMap8Test exte */ public void testComputeIfAbsent() { ConcurrentHashMap map = map5(); - map.computeIfAbsent(six, (x) -> "Z"); + map.computeIfAbsent(six, x -> "Z"); assertTrue(map.containsKey(six)); } @@ -72,7 +72,7 @@ public class ConcurrentHashMap8Test exte */ public void testComputeIfAbsent2() { ConcurrentHashMap map = map5(); - assertEquals("A", map.computeIfAbsent(one, (x) -> "Z")); + assertEquals("A", map.computeIfAbsent(one, x -> "Z")); } /** @@ -80,7 +80,7 @@ public class ConcurrentHashMap8Test exte */ public void testComputeIfAbsent3() { ConcurrentHashMap map = map5(); - map.computeIfAbsent(six, (x) -> null); + map.computeIfAbsent(six, x -> null); assertFalse(map.containsKey(six)); } @@ -164,8 +164,8 @@ public class ConcurrentHashMap8Test exte Set a = ConcurrentHashMap.newKeySet(); assertTrue(a.isEmpty()); for (int i = 0; i < n; i++) - a.add(i); - assertFalse(a.isEmpty()); + assertTrue(a.add(i)); + assertEquals(n == 0, a.isEmpty()); assertEquals(n, a.size()); return a; } @@ -174,7 +174,7 @@ public class ConcurrentHashMap8Test exte Set a = ConcurrentHashMap.newKeySet(); assertTrue(a.isEmpty()); for (int i = 0; i < elements.length; i++) - a.add(elements[i]); + assertTrue(a.add(elements[i])); assertFalse(a.isEmpty()); assertEquals(elements.length, a.size()); return a; @@ -185,7 +185,7 @@ public class ConcurrentHashMap8Test exte */ public void testReplaceAll() { ConcurrentHashMap map = map5(); - map.replaceAll((x, y) -> { return x > 3 ? "Z" : y; }); + map.replaceAll((x, y) -> (x > 3) ? "Z" : y); assertEquals("A", map.get(one)); assertEquals("B", map.get(two)); assertEquals("C", map.get(three)); @@ -210,8 +210,8 @@ public class ConcurrentHashMap8Test exte Set set1 = map.keySet(); Set set2 = map.keySet(true); set2.add(six); - assertTrue(((ConcurrentHashMap.KeySetView)set2).getMap() == map); - assertTrue(((ConcurrentHashMap.KeySetView)set1).getMap() == map); + assertSame(map, ((ConcurrentHashMap.KeySetView)set2).getMap()); + assertSame(map, ((ConcurrentHashMap.KeySetView)set1).getMap()); assertEquals(set2.size(), map.size()); assertEquals(set1.size(), map.size()); assertTrue((Boolean)map.get(six)); @@ -223,17 +223,14 @@ public class ConcurrentHashMap8Test exte assertFalse(set2.contains(six)); } - /** * keySet.addAll adds each element from the given collection */ public void testAddAll() { Set full = populatedSet(3); - Vector v = new Vector(); - v.add(three); - v.add(four); - v.add(five); - full.addAll(v); + assertTrue(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, five))); assertEquals(6, full.size()); } @@ -243,11 +240,10 @@ public class ConcurrentHashMap8Test exte */ public void testAddAll2() { Set full = populatedSet(3); - Vector v = new Vector(); - v.add(three); - v.add(four); - v.add(one); // will not add this element - full.addAll(v); + // "one" is duplicate and will not be added + assertTrue(full.addAll(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, one))); assertEquals(5, full.size()); } @@ -256,7 +252,7 @@ public class ConcurrentHashMap8Test exte */ public void testAdd2() { Set full = populatedSet(3); - full.add(one); + assertFalse(full.add(one)); assertEquals(3, full.size()); } @@ -265,7 +261,9 @@ public class ConcurrentHashMap8Test exte */ public void testAdd3() { Set full = populatedSet(3); - full.add(three); + assertTrue(full.add(three)); + assertTrue(full.contains(three)); + assertFalse(full.add(three)); assertTrue(full.contains(three)); } @@ -278,7 +276,7 @@ public class ConcurrentHashMap8Test exte try { full.add(three); shouldThrow(); - } catch (UnsupportedOperationException e){} + } catch (UnsupportedOperationException success) {} } /** @@ -290,7 +288,7 @@ public class ConcurrentHashMap8Test exte try { full.add(null); shouldThrow(); - } catch (NullPointerException e){} + } catch (NullPointerException success) {} } /** @@ -302,15 +300,15 @@ public class ConcurrentHashMap8Test exte try { map.keySet(null); shouldThrow(); - } catch (NullPointerException e) {} + } catch (NullPointerException success) {} ConcurrentHashMap.KeySetView set = map.keySet(one); - set.add(one); - set.add(six); - set.add(seven); - assertTrue(set.getMappedValue() == one); - assertTrue(map.get(one) != one); - assertTrue(map.get(six) == one); - assertTrue(map.get(seven) == one); + assertFalse(set.add(one)); + assertTrue(set.add(six)); + assertTrue(set.add(seven)); + assertSame(one, set.getMappedValue()); + assertNotSame(one, map.get(one)); + assertSame(one, map.get(six)); + assertSame(one, map.get(seven)); } void checkSpliteratorCharacteristics(Spliterator sp, @@ -377,23 +375,20 @@ public class ConcurrentHashMap8Test exte * KeySet.containsAll returns true for collections with subset of elements */ public void testContainsAll() { - Set full = populatedSet(3); - Vector v = new Vector(); - v.add(one); - v.add(two); - assertTrue(full.containsAll(v)); - v.add(six); - assertFalse(full.containsAll(v)); + Collection full = populatedSet(3); + assertTrue(full.containsAll(Arrays.asList())); + assertTrue(full.containsAll(Arrays.asList(one))); + assertTrue(full.containsAll(Arrays.asList(one, two))); + assertFalse(full.containsAll(Arrays.asList(one, two, six))); + assertFalse(full.containsAll(Arrays.asList(six))); } /** * KeySet.isEmpty is true when empty, else false */ public void testIsEmpty() { - Set empty = ConcurrentHashMap.newKeySet(); - Set full = populatedSet(3); - assertTrue(empty.isEmpty()); - assertFalse(full.isEmpty()); + assertTrue(populatedSet(0).isEmpty()); + assertFalse(populatedSet(3).isEmpty()); } /** @@ -412,7 +407,7 @@ public class ConcurrentHashMap8Test exte Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Iterator it = full.iterator(); @@ -420,11 +415,17 @@ public class ConcurrentHashMap8Test exte assertTrue(it.hasNext()); it.next(); } - assertFalse(it.hasNext()); - try { - it.next(); - shouldThrow(); - } catch (NoSuchElementException success) {} + assertIteratorExhausted(it); + } + + /** + * iterator of empty collections has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(ConcurrentHashMap.newKeySet().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().entrySet().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().values().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().keySet().iterator()); } /** @@ -458,10 +459,9 @@ public class ConcurrentHashMap8Test exte */ public void testRemoveAll() { Set full = populatedSet(3); - Vector v = new Vector(); - v.add(one); - v.add(two); - full.removeAll(v); + assertTrue(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + assertFalse(full.removeAll(Arrays.asList(one, two))); assertEquals(1, full.size()); } @@ -497,7 +497,7 @@ public class ConcurrentHashMap8Test exte Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray()))); @@ -517,7 +517,7 @@ public class ConcurrentHashMap8Test exte a = new Integer[0]; assertSame(a, empty.toArray(a)); - a = new Integer[size/2]; + a = new Integer[size / 2]; Arrays.fill(a, 42); assertSame(a, empty.toArray(a)); assertNull(a[0]); @@ -527,7 +527,7 @@ public class ConcurrentHashMap8Test exte Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Arrays.fill(a, 42); @@ -543,7 +543,7 @@ public class ConcurrentHashMap8Test exte } /** - * A deserialized serialized set is equal + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { int size = 20; @@ -1089,4 +1089,30 @@ public class ConcurrentHashMap8Test exte assertNull(r); } + /** + * 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); + } + } + }