I write test cases to evaluate RacerD concurrency issues detection rate. I have created several tests, but majority of them are false negative.
Examples:
Example 1 (if I would replace HashSet with HashMap, then RacerD can detect issues, but for HashSet no chance; I tried to add @threadsafe, tried to call from another class which starts two threads and calls addData/getData etc. None of the combinations detect the race.
public class UnsafeSetWithSynchronized1_FALSE_NEGATIVE {
private final Set<String> data = new HashSet<>();
public synchronized void addData(String value) {
data.add(value);
}
public boolean contains(String value) {
return data.contains(value);
}
public Set<String> getData() {
return data;
}
}
Example 2:
public class UnsafeObjectConditionWithSynchronized1_FALSE_NEGATIVE {
private boolean flag;
public void set(boolean flag) {
this.flag = flag;
}
public synchronized int get() {
if (flag) {
return 0;
} else {
return 1;
}
}
}
Example 3:
public class UnsafeListInParallelStreamWithSynchronized_FALSE_NEGATIVE {
private final List<String> data = new ArrayList<>();
public synchronized void processData(List<String> ids) {
// multiple threads will try to add to the list simultaneously
ids.parallelStream().forEach(id -> {
data.add(id);
});
}
public List<String> get() {
return data;
}
}
Example 4:
@ThreadSafe
public class UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE {
private final Set<String> data = new HashSet<>();
public synchronized void addData(String value) {
data.add(value);
}
public boolean contains(String value) {
return data.contains(value);
}
public Set<String> getData() {
return data;
}
public static UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE createAndStartNew() {
UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE instance = new UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE();
Thread t = new Thread(() -> {
instance.addData("Auto-generated data");
});
t.start();
return instance;
}
public static Thread useAndStartExisting1(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) {
Thread t = new Thread(() -> {
existing.contains("Some value");
});
return t;
}
public static Thread useAndStartExisting2(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) {
Thread t = new Thread(() -> {
existing.addData("Some value");
});
return t;
}
public static Set<String> useAndStartExisting3(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) throws InterruptedException {
Set<String> result = new HashSet<>();
Thread t = new Thread(() -> {
result.addAll(existing.getData());
});
t.start();
t.join();
return result;
}
}
And lots of other examples ... only in limited number of cases RacerD could discover some data race.
I start RacerD in following way:
ProcessBuilder pb = new ProcessBuilder(
INFER_PATH, "run",
"--racerd-only",
"--reactive",
"--no-filtering", // Disables noise filters
"--", "/usr/bin/javac", "-cp", ANNOTATIONS_JAR_PATH, filePath.toString()
);
I write test cases to evaluate RacerD concurrency issues detection rate. I have created several tests, but majority of them are false negative.
Examples:
Example 1 (if I would replace HashSet with HashMap, then RacerD can detect issues, but for HashSet no chance; I tried to add @threadsafe, tried to call from another class which starts two threads and calls addData/getData etc. None of the combinations detect the race.
Example 2:
Example 3:
Example 4:
And lots of other examples ... only in limited number of cases RacerD could discover some data race.
I start RacerD in following way: