package org.geoserver.threadlocals;
import static org.junit.Assert.assertNotEquals;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.After;
import org.junit.Before;
/**
* Base class for {@link ThreadLocalTransfer} tests. Just implement a ThreadLocalTransferCallable
* and call {@link #testThreadLocalTransfer(ThreadLocalTransferCallable)} to have the thread local
* transfer be tested for proper transfer and cleanup.
*
* @author Andrea Aime - GeoSolutions
*
*/
public abstract class AbstractThreadLocalTransferTest {
protected ExecutorService executor;
@Before
public void setupExecutor() {
executor = Executors.newCachedThreadPool();
}
@After
public void stopExecutor() {
executor.shutdown();
}
public void testThreadLocalTransfer(ThreadLocalTransferCallable callable)
throws InterruptedException, ExecutionException {
Future<Void> future = executor.submit(callable);
future.get();
}
protected abstract static class ThreadLocalTransferCallable implements Callable<Void> {
Thread originalThread;
ThreadLocalTransfer transfer;
Map<String, Object> storage = new HashMap<String, Object>();
public ThreadLocalTransferCallable(ThreadLocalTransfer transfer) {
this.originalThread = Thread.currentThread();
this.transfer = transfer;
this.transfer.collect(storage);
}
@Override
public Void call() throws Exception {
// this is the the main thread, we are actually running inside the thread pool
assertNotEquals(originalThread, Thread.currentThread());
// apply the thread local, check it has been applied correctly
transfer.apply(storage);
assertThreadLocalApplied();
// clean up, check the therad local is now empty
transfer.cleanup();
assertThreadLocalCleaned();
return null;
}
abstract void assertThreadLocalCleaned();
abstract void assertThreadLocalApplied();
};
}