}
}
public void testGetSecurity_byUniqueId_b() throws Exception {
final UniqueId uidA = UniqueId.of("Test", "A");
final Security secA = Mockito.mock(Security.class);
final UniqueId uidB = UniqueId.of("Test", "B");
final Security secB = Mockito.mock(Security.class);
final UniqueId uidC = UniqueId.of("Test", "C");
final Security secC = Mockito.mock(Security.class);
final CyclicBarrier barrier1 = new CyclicBarrier(3);
final CyclicBarrier barrier2 = new CyclicBarrier(2);
final MockSecuritySource underlying = new MockSecuritySource() {
int _state;
@Override
public Security get(final UniqueId uid) {
assertEquals(_state++, 0);
join(barrier1);
assertEquals(uid, uidA);
// Pause for a bit to make sure that the other thread gets blocked in their getSecurity methods
sleep();
return secA;
}
@Override
public Map<UniqueId, Security> get(final Collection<UniqueId> uids) {
assertEquals(_state++, 1);
assertEquals(uids.size(), 2);
assertTrue(uids.contains(uidB));
assertTrue(uids.contains(uidC));
final Map<UniqueId, Security> result = Maps.newHashMapWithExpectedSize(2);
result.put(uidB, secB);
result.put(uidC, secC);
return result;
}
};
final CoalescingSecuritySource coalescing = new CoalescingSecuritySource(underlying) {
@Override
protected void releaseOtherWritingThreads() {
join(barrier2); // 1 + 2 // release the third thread
}
};
// Start two threads. One will do the first write, the other will be blocked. Suppressing releaseOtherThreads means a third
// call will try to write its own value plus those from the other threads. The second thread will do no I/O itself.
final ExecutorService exec = Executors.newCachedThreadPool();
try {
final Future<?> a = exec.submit(new Runnable() {
@Override
public void run() {
final Security s = coalescing.get(uidA);
assertSame(s, secA);
}
});
final Future<?> b = exec.submit(new Runnable() {
@Override
public void run() {
join(barrier1);
final Security s = coalescing.get(uidB);
assertSame(s, secB);
}
});
final Future<?> c = exec.submit(new Runnable() {
@Override
public void run() {
join(barrier2); // 1
final Security s = coalescing.get(uidC);
assertSame(s, secC);
}
});
join(barrier1);
a.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);