Update JSR166 tck tests.
The following tests have been omitted because they are
unsupported :
- Atomic8Test.java
- CompletableFutureTest.java
- ConcurrentHashMap8Test.java
- DoubleAccumulatorTest.java
- DoubleAdderTest.java
- ForkJoinPool8Test.java
- ForkJoinTask8Test.java
- LongAccumulatorTest.java
- LongAdderTest.java
- SplittableRandomTest.java
- StampedLockTest.java
- ThreadLocalRandom8Test.java
- ThreadPoolExecutor9Test.java
A package declaration has been added to all files (package jsr166;)
and the base-class JSR166Test has been changed not to rely on features
that aren't available on android / junit in the android environment.
We also avoid using junit4 style TestSuite declarations. While the CTS
test runner handles them properly usually, it trips over itself when it
encounters a failure and tries to run each test in an invidual process
and fails each test for no good reason (needs investigation on the CTS
side of things)
bug: 20628776
(cherry picked from commit 5da8b2b3cac51f0f592a5e1941bd84eade9648cd)
Change-Id: If35be0881ad8da4c604ce6683149b15c1a85f289
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
index 5d9e2ac..4650f41 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
@@ -8,17 +8,36 @@
package jsr166;
-import junit.framework.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
public class ConcurrentHashMapTest extends JSR166TestCase {
+ // android-note: Removed because the CTS runner does a bad job of
+ // retrying tests that have suite() declarations.
+ //
+ // public static void main(String[] args) {
+ // main(suite(), args);
+ // }
+ // public static Test suite() {
+ // return new TestSuite(...);
+ // }
/**
* Returns a new map from Integers 1-5 to Strings "A"-"E".
*/
- private static ConcurrentHashMap map5() {
- ConcurrentHashMap map = new ConcurrentHashMap(5);
+ private static ConcurrentHashMap<Integer, String> map5() {
+ ConcurrentHashMap map = new ConcurrentHashMap<Integer, String>(5);
assertTrue(map.isEmpty());
map.put(one, "A");
map.put(two, "B");
@@ -30,12 +49,15 @@
return map;
}
+ /** Re-implement Integer.compare for old java versions */
+ 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<BI> {
private final int value;
BI(int value) { this.value = value; }
public int compareTo(BI other) {
- return Integer.compare(value, other.value);
+ return compare(value, other.value);
}
public boolean equals(Object x) {
return (x instanceof BI) && ((BI)x).value == value;
@@ -59,12 +81,9 @@
static class LexicographicList<E extends Comparable<E>> extends ArrayList<E>
implements Comparable<LexicographicList<E>> {
- static long total;
- static long n;
LexicographicList(Collection<E> c) { super(c); }
LexicographicList(E e) { super(Collections.singleton(e)); }
public int compareTo(LexicographicList<E> other) {
- long start = System.currentTimeMillis();
int common = Math.min(size(), other.size());
int r = 0;
for (int i = 0; i < common; i++) {
@@ -72,25 +91,40 @@
break;
}
if (r == 0)
- r = Integer.compare(size(), other.size());
- total += System.currentTimeMillis() - start;
- n++;
+ r = compare(size(), other.size());
return r;
}
private static final long serialVersionUID = 0;
}
+ static class CollidingObject {
+ final String value;
+ CollidingObject(final String value) { this.value = value; }
+ public int hashCode() { return this.value.hashCode() & 1; }
+ public boolean equals(final Object obj) {
+ return (obj instanceof CollidingObject) && ((CollidingObject)obj).value.equals(value);
+ }
+ }
+
+ static class ComparableCollidingObject extends CollidingObject implements Comparable<ComparableCollidingObject> {
+ ComparableCollidingObject(final String value) { super(value); }
+ public int compareTo(final ComparableCollidingObject o) {
+ return value.compareTo(o.value);
+ }
+ }
+
/**
* Inserted elements that are subclasses of the same Comparable
* class are found.
*/
public void testComparableFamily() {
+ int size = 500; // makes measured test run time -> 60ms
ConcurrentHashMap<BI, Boolean> m =
new ConcurrentHashMap<BI, Boolean>();
- for (int i = 0; i < 1000; i++) {
+ for (int i = 0; i < size; i++) {
assertTrue(m.put(new CI(i), true) == null);
}
- for (int i = 0; i < 1000; i++) {
+ for (int i = 0; i < size; i++) {
assertTrue(m.containsKey(new CI(i)));
assertTrue(m.containsKey(new DI(i)));
}
@@ -100,24 +134,25 @@
* Elements of classes with erased generic type parameters based
* on Comparable can be inserted and found.
*/
- public void testGenericComparable() {
- ConcurrentHashMap<Object, Boolean> m =
- new ConcurrentHashMap<Object, Boolean>();
- for (int i = 0; i < 1000; i++) {
- BI bi = new BI(i);
- BS bs = new BS(String.valueOf(i));
- LexicographicList<BI> bis = new LexicographicList<BI>(bi);
- LexicographicList<BS> bss = new LexicographicList<BS>(bs);
- assertTrue(m.putIfAbsent(bis, true) == null);
- assertTrue(m.containsKey(bis));
- if (m.putIfAbsent(bss, true) == null)
- assertTrue(m.containsKey(bss));
- assertTrue(m.containsKey(bis));
- }
- for (int i = 0; i < 1000; i++) {
- assertTrue(m.containsKey(new ArrayList(Collections.singleton(new BI(i)))));
- }
- }
+ public void testGenericComparable() {
+ int size = 120; // makes measured test run time -> 60ms
+ ConcurrentHashMap<Object, Boolean> m =
+ new ConcurrentHashMap<Object, Boolean>();
+ for (int i = 0; i < size; i++) {
+ BI bi = new BI(i);
+ BS bs = new BS(String.valueOf(i));
+ LexicographicList<BI> bis = new LexicographicList<BI>(bi);
+ LexicographicList<BS> bss = new LexicographicList<BS>(bs);
+ assertTrue(m.putIfAbsent(bis, true) == null);
+ assertTrue(m.containsKey(bis));
+ if (m.putIfAbsent(bss, true) == null)
+ assertTrue(m.containsKey(bss));
+ assertTrue(m.containsKey(bis));
+ }
+ for (int i = 0; i < size; i++) {
+ assertTrue(m.containsKey(Collections.singletonList(new BI(i))));
+ }
+ }
/**
* Elements of non-comparable classes equal to those of classes
@@ -125,19 +160,55 @@
* inserted and found.
*/
public void testGenericComparable2() {
+ int size = 500; // makes measured test run time -> 60ms
ConcurrentHashMap<Object, Boolean> m =
new ConcurrentHashMap<Object, Boolean>();
- for (int i = 0; i < 1000; i++) {
- m.put(new ArrayList(Collections.singleton(new BI(i))), true);
+ for (int i = 0; i < size; i++) {
+ m.put(Collections.singletonList(new BI(i)), true);
}
- for (int i = 0; i < 1000; i++) {
+ for (int i = 0; i < size; i++) {
LexicographicList<BI> bis = new LexicographicList<BI>(new BI(i));
assertTrue(m.containsKey(bis));
}
}
/**
+ * Mixtures of instances of comparable and non-comparable classes
+ * can be inserted and found.
+ */
+ public void testMixedComparable() {
+ int size = 1200; // makes measured test run time -> 35ms
+ ConcurrentHashMap<Object, Object> map =
+ new ConcurrentHashMap<Object, Object>();
+ Random rng = new Random();
+ for (int i = 0; i < size; i++) {
+ Object x;
+ switch (rng.nextInt(4)) {
+ case 0:
+ x = new Object();
+ break;
+ case 1:
+ x = new CollidingObject(Integer.toString(i));
+ break;
+ default:
+ x = new ComparableCollidingObject(Integer.toString(i));
+ }
+ assertNull(map.put(x, x));
+ }
+ int count = 0;
+ for (Object k : map.keySet()) {
+ assertEquals(map.get(k), k);
+ ++count;
+ }
+ assertEquals(count, size);
+ assertEquals(map.size(), size);
+ for (Object k : map.keySet()) {
+ assertEquals(map.put(k, k), k);
+ }
+ }
+
+ /**
* clear removes all pairs
*/
public void testClear() {
@@ -160,6 +231,17 @@
}
/**
+ * hashCode() equals sum of each key.hashCode ^ value.hashCode
+ */
+ public void testHashCode() {
+ ConcurrentHashMap<Integer,String> map = map5();
+ int sum = 0;
+ for (Map.Entry<Integer,String> e : map.entrySet())
+ sum += e.getKey().hashCode() ^ e.getValue().hashCode();
+ assertEquals(sum, map.hashCode());
+ }
+
+ /**
* contains returns true for contained value
*/
public void testContains() {
@@ -210,6 +292,7 @@
assertEquals("A", (String)map.get(one));
ConcurrentHashMap empty = new ConcurrentHashMap();
assertNull(map.get("anything"));
+ assertNull(empty.get("anything"));
}
/**
@@ -443,29 +526,9 @@
// Exception tests
/**
- * Cannot create with negative capacity
- */
- public void testConstructor1() {
- try {
- new ConcurrentHashMap(-1,0,1);
- shouldThrow();
- } catch (IllegalArgumentException success) {}
- }
-
- /**
- * Cannot create with negative concurrency level
- */
- public void testConstructor2() {
- try {
- new ConcurrentHashMap(1,0,-1);
- shouldThrow();
- } catch (IllegalArgumentException success) {}
- }
-
- /**
* Cannot create with only negative capacity
*/
- public void testConstructor3() {
+ public void testConstructor1() {
try {
new ConcurrentHashMap(-1);
shouldThrow();
@@ -473,11 +536,71 @@
}
/**
+ * Constructor (initialCapacity, loadFactor) throws
+ * IllegalArgumentException if either argument is negative
+ */
+ public void testConstructor2() {
+ try {
+ new ConcurrentHashMap(-1, .75f);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+
+ try {
+ new ConcurrentHashMap(16, -1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor (initialCapacity, loadFactor, concurrencyLevel)
+ * throws IllegalArgumentException if any argument is negative
+ */
+ public void testConstructor3() {
+ try {
+ new ConcurrentHashMap(-1, .75f, 1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+
+ try {
+ new ConcurrentHashMap(16, -1, 1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+
+ try {
+ new ConcurrentHashMap(16, .75f, -1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * ConcurrentHashMap(map) throws NullPointerException if the given
+ * map is null
+ */
+ public void testConstructor4() {
+ try {
+ new ConcurrentHashMap(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * ConcurrentHashMap(map) creates a new map with the same mappings
+ * as the given map
+ */
+ public void testConstructor5() {
+ ConcurrentHashMap map1 = map5();
+ ConcurrentHashMap map2 = new ConcurrentHashMap(map5());
+ assertTrue(map2.equals(map1));
+ map2.put(one, "F");
+ assertFalse(map2.equals(map1));
+ }
+
+ /**
* 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) {}
@@ -487,8 +610,8 @@
* 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) {}
@@ -498,8 +621,8 @@
* 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) {}
@@ -509,8 +632,8 @@
* 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) {}
@@ -520,8 +643,8 @@
* 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) {}
@@ -531,8 +654,8 @@
* 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) {}
@@ -542,8 +665,8 @@
* 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) {}
@@ -553,8 +676,8 @@
* 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) {}
@@ -564,8 +687,8 @@
* 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) {}
@@ -575,8 +698,8 @@
* 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) {}
@@ -586,8 +709,8 @@
* 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) {}
@@ -597,8 +720,8 @@
* 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) {}
@@ -608,8 +731,8 @@
* 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) {}
@@ -619,9 +742,9 @@
* 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) {}
@@ -631,9 +754,9 @@
* 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) {}