|
Description
|
Collections.newSetFromMap().equals is failing with ConcurrentSkipListMap.
The following testcase will fail on the average of 13 times out of 100.
<testcase>
import java.util.Set;
import static java.util.Collections.*;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
public class Test1 {
private static void testSet(final Set<Integer> s1,
final Set<Integer> s2,
final boolean checkToString) {
final int iterations = 100000;
final Integer two = Integer.valueOf(2);
final Thread t1 = new CheckedThread() { public void realRun() {
for (int i = 0; i < iterations; i++) {
s2.add(two);
s2.remove(two);
}}};
t1.start();
for (int i = 0; i < iterations; i++) {
check(s1.equals(s1));
check(s2.equals(s2));
check(! s1.equals(s2));
check(! s2.equals(s1));
equal(s1.toString(),s1.toString());
notEqual(s1.toString(),s2.toString());
notEqual(s2.toString(),s1.toString());
}
try { t1.join(); } catch (Throwable t) { unexpected(t); }
}
public static void realMain(String... arg) throws Throwable{
System.out.println("SetFromMap");
Set<Integer> s1 = newSetFromMap(new ConcurrentSkipListMap<Integer,Boolean>());
Set<Integer> s2 = newSetFromMap(new ConcurrentSkipListMap<Integer,Boolean>());
s1.add(1);
testSet(s1,s2,true);
System.out.println("Direct");
Set<Integer> customer = new ConcurrentSkipListSet<Integer>();
Set<Integer> s4 = new ConcurrentSkipListSet<Integer>();
customer .add(1);
testSet( customer ,s4,true);
}
static volatile int passed = 0, failed = 0;
static void pass() {passed++;}
static void fail() {failed++; Thread.dumpStack();}
static void fail(String msg) {System.out.println(msg); fail();}
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
static void check(boolean cond) {if (cond) pass(); else fail();}
static void equal(Object x, Object y) {
if (x == null ? y == null : x.equals(y)) pass();
else fail(x + " not equal to " + y);}
static void notEqual(Object x, Object y) {
if (x == null ? y == null : x.equals(y)) fail(x + " equal to " + y);
else pass();}
public static void main(String[] args) throws Throwable {
try {realMain(args);} catch (Throwable t) {unexpected(t);}
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new AssertionError("Some tests failed");}
private static abstract class CheckedThread extends Thread {
public abstract void realRun() throws Throwable;
public void run() {
try { realRun(); } catch (Throwable t) { unexpected(t); }}}
}
</testcase>
newSetFromMap spec says:
"Returns a set backed by the specified map. The resulting set displays the same ordering, *concurrency*, and performance characteristics as the backing map."
In the above testcase, when ConcurrentSkipListSet is directly used testcase will pass always but when set is constructed from newSetFromMap(ConcurrentSkipListMap). The testcase will fail.
Tested on :
<java-version>
java version "1.6.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-rc-b66)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b66, mixed mode)
</java-version>
Posted Date : 2006-01-20 10:36:45.0
testbase: /net/sqindia.india/export/disk03/coresqe/j2se_sqe_libs_ws/mustang_libs_ws
failing testcase: java_util/Collections/SetFromMap/ConcurrentSkipList/ConcurrentSkipListTest02
Posted Date : 2006-03-16 17:45:13.0
|
|
Evaluation
|
Various .equals() methods implicitly assume that "this" or the
argument collection is not being concurrently mutated during
method execution. It would be good to improve this,
especially for the .equals() methods of concurrent collections.
Posted Date : 2006-01-20 22:57:25.0
One can argue that the semantics of equals() when comparing mutating collections
is unclear, and that mutable set equality should be identity comparison,
while immutable set equality should be content comparison.
But Java is not ML.
Posted Date : 2006-02-04 19:11:52.0
|