--- jsr166/src/test/tck/ConcurrentHashMap8Test.java 2013/08/08 18:37:05 1.15 +++ jsr166/src/test/tck/ConcurrentHashMap8Test.java 2017/03/18 20:42:20 1.34 @@ -4,17 +4,30 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import junit.framework.*; -import java.util.*; -import static java.util.Spliterator.*; -import java.util.function.*; -import java.util.concurrent.atomic.LongAdder; +import static java.util.Spliterator.CONCURRENT; +import static java.util.Spliterator.DISTINCT; +import static java.util.Spliterator.NONNULL; + +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Spliterator; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentHashMap.KeySetView; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.BiFunction; + +import junit.framework.Test; +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); @@ -50,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)); } @@ -59,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")); } /** @@ -67,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)); } @@ -151,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; } @@ -161,18 +174,18 @@ 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; } - /* + /** * replaceAll replaces all matching values. */ public void testReplaceAll() { ConcurrentHashMap map = map5(); - map.replaceAll((x, y) -> {return x > 3 ? "Z" : y;}); + map.replaceAll((x, y) -> { return x > 3 ? "Z" : y; }); assertEquals("A", map.get(one)); assertEquals("B", map.get(two)); assertEquals("C", map.get(three)); @@ -197,8 +210,8 @@ public class ConcurrentHashMap8Test exte Set set1 = map.keySet(); Set set2 = map.keySet(true); set2.add(six); - assertTrue(((KeySetView)set2).getMap() == map); - assertTrue(((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)); @@ -210,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()); } @@ -230,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()); } @@ -243,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()); } @@ -252,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)); } @@ -265,7 +276,7 @@ public class ConcurrentHashMap8Test exte try { full.add(three); shouldThrow(); - } catch (UnsupportedOperationException e){} + } catch (UnsupportedOperationException success) {} } /** @@ -277,7 +288,7 @@ public class ConcurrentHashMap8Test exte try { full.add(null); shouldThrow(); - } catch (NullPointerException e){} + } catch (NullPointerException success) {} } /** @@ -289,15 +300,15 @@ public class ConcurrentHashMap8Test exte try { map.keySet(null); shouldThrow(); - } catch (NullPointerException e) {} - 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); + } catch (NullPointerException success) {} + ConcurrentHashMap.KeySetView set = map.keySet(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, @@ -305,7 +316,7 @@ public class ConcurrentHashMap8Test exte assertEquals(requiredCharacteristics, requiredCharacteristics & sp.characteristics()); } - + /** * KeySetView.spliterator returns spliterator over the elements in this set */ @@ -364,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()); } /** @@ -399,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(); @@ -407,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()); } /** @@ -445,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()); } @@ -484,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()))); @@ -504,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]); @@ -514,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); @@ -539,8 +552,6 @@ public class ConcurrentHashMap8Test exte assertNotSame(x, y); assertEquals(x.size(), y.size()); - assertEquals(x.toString(), y.toString()); - assertTrue(Arrays.equals(x.toArray(), y.toArray())); assertEquals(x, y); assertEquals(y, x); } @@ -992,9 +1003,11 @@ public class ConcurrentHashMap8Test exte public void testSearchValuesSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchValues(Long.MAX_VALUE, (Long x) -> x.longValue() == (long)(SIZE/2)? x : null); + r = m.searchValues(Long.MAX_VALUE, + (Long x) -> (x.longValue() == (long)(SIZE/2)) ? x : null); assertEquals((long)r, (long)(SIZE/2)); - r = m.searchValues(Long.MAX_VALUE, (Long x) -> x.longValue() < 0L ? x : null); + r = m.searchValues(Long.MAX_VALUE, + (Long x) -> (x.longValue() < 0L) ? x : null); assertNull(r); } @@ -1076,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); + } + } + }