/**
*
*/
package vnet.routing.netty.server.support.window.map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Test;
/**
* @author obergner
*
*/
@Ignore("ConcurrentFixedSizeHashMap needs a complete overhaul")
public class ConcurrentFixedSizeHashMapConcurrentTest {
private static class KeyValue {
final long key;
final String value;
public KeyValue(final long key, final String value) {
this.key = key;
this.value = value;
}
}
/**
* Test method for
* {@link vnet.routing.netty.server.support.window.map.ConcurrentFixedSizeHashMap#put(java.lang.Object, java.lang.Object)}
* .
*
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public final void assertThatPutFillsFixedSizeMapToCapacity()
throws InterruptedException, ExecutionException {
final int capacity = 10000;
final BlockingQueue<KeyValue> queue = new ArrayBlockingQueue<KeyValue>(
capacity);
final Set<KeyValue> backup = new HashSet<KeyValue>(capacity);
for (long key = 0; key < capacity; key++) {
final KeyValue keyValue = new KeyValue(key, String.valueOf(key));
queue.put(keyValue);
backup.add(keyValue);
}
final ConcurrentFixedSizeHashMap<Long, String> objectUnderTest = new ConcurrentFixedSizeHashMap<Long, String>(
capacity);
final int numberOfTasks = 100;
final Set<PutTask> putTasks = new HashSet<PutTask>(numberOfTasks);
for (int i = 0; i < numberOfTasks; i++) {
putTasks.add(new PutTask(objectUnderTest, queue));
}
final ExecutorService executor = Executors
.newFixedThreadPool(numberOfTasks);
final Set<Future<?>> completions = new HashSet<Future<?>>();
for (final PutTask putTask : putTasks) {
completions.add(executor.submit(putTask));
}
for (final Future<?> completion : completions) {
completion.get();
}
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
executor.shutdownNow();
assertEquals(
"ConcurrentFixedSizeHashMap should be completely filled, yet it isn't",
capacity, objectUnderTest.size());
for (final KeyValue keyValue : backup) {
final String putValue = objectUnderTest.get(keyValue.key);
assertNotNull("ConcurrentFixedSizeHashMap should contain id "
+ keyValue.key + ", yet it doesn't", putValue);
assertEquals(
"ConcurrentFixedSizeHashMap stored wrong message under id "
+ keyValue.key, keyValue.value, putValue);
}
}
private static class PutTask implements Runnable {
private final ConcurrentFixedSizeHashMap<Long, String> objectUnderTest;
private final BlockingQueue<KeyValue> queue;
public PutTask(
final ConcurrentFixedSizeHashMap<Long, String> objectUnderTest,
final BlockingQueue<KeyValue> queue) {
this.objectUnderTest = objectUnderTest;
this.queue = queue;
}
@Override
public void run() {
while (true) {
final KeyValue next = this.queue.poll();
if (next == null) {
break;
}
this.objectUnderTest.put(next.key, next.value);
}
}
}
/**
* Test method for
* {@link vnet.routing.netty.server.support.window.map.ConcurrentFixedSizeHashMap#put(java.lang.Object, java.lang.Object)}
* .
*
* @throws Throwable
*/
@Test(expected = MapCapacityExhaustedException.class)
public final void assertThatPutRefusesToFillMapBeyondCapacity()
throws Throwable {
ExecutorService executor = null;
try {
final int capacity = 10000;
final int numberOfKeyValuesToPut = capacity + 1;
final BlockingQueue<KeyValue> queue = new ArrayBlockingQueue<KeyValue>(
numberOfKeyValuesToPut);
final Set<KeyValue> backup = new HashSet<KeyValue>(
numberOfKeyValuesToPut);
for (long key = 0; key < numberOfKeyValuesToPut; key++) {
final KeyValue keyValue = new KeyValue(key, String.valueOf(key));
queue.put(keyValue);
backup.add(keyValue);
}
final ConcurrentFixedSizeHashMap<Long, String> objectUnderTest = new ConcurrentFixedSizeHashMap<Long, String>(
capacity);
final int numberOfTasks = 100;
final Set<PutTask> putTasks = new HashSet<PutTask>(numberOfTasks);
for (int i = 0; i < numberOfTasks; i++) {
putTasks.add(new PutTask(objectUnderTest, queue));
}
executor = Executors.newFixedThreadPool(numberOfTasks);
final Set<Future<?>> completions = new HashSet<Future<?>>();
for (final PutTask putTask : putTasks) {
completions.add(executor.submit(putTask));
}
for (final Future<?> completion : completions) {
completion.get();
}
System.out.println(objectUnderTest.size());
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
executor.shutdownNow();
} catch (final ExecutionException e) {
if (e.getCause() instanceof MapCapacityExhaustedException) {
throw e.getCause();
}
} finally {
if (executor != null) {
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
executor.shutdownNow();
}
}
}
/**
* Test method for
* {@link vnet.routing.netty.server.support.window.map.ConcurrentFixedSizeHashMap#putIfAbsent(java.lang.Object, java.lang.Object)}
* .
*/
@Test
public final void testPutIfAbsent() {
fail("Not yet implemented"); // TODO
}
/**
* Test method for
* {@link vnet.routing.netty.server.support.window.map.ConcurrentFixedSizeHashMap#remove(java.lang.Object)}
* .
*/
@Test
public final void testRemoveObject() {
fail("Not yet implemented"); // TODO
}
}