summaryrefslogtreecommitdiffstats
path: root/yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java
diff options
context:
space:
mode:
Diffstat (limited to 'yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java')
-rw-r--r--yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java146
1 files changed, 146 insertions, 0 deletions
diff --git a/yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java b/yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java
new file mode 100644
index 00000000000..794a8f4e75f
--- /dev/null
+++ b/yolean/src/test/java/com/yahoo/yolean/concurrent/ThreadRobustListTestCase.java
@@ -0,0 +1,146 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.yolean.concurrent;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
+ */
+public class ThreadRobustListTestCase {
+
+ private final static int NUM_THREADS = 64;
+ private final static int NUM_ITEMS_TO_WRITE = 1000000;
+ private final static int NUM_TIMES_TO_READ = 10;
+
+ @Test
+ public void requireThatListIsThreadRobust() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(NUM_THREADS);
+ final ThreadRobustList<Integer> sharedList = new ThreadRobustList<>();
+
+ List<Callable<Boolean>> tasks = new ArrayList<>(NUM_THREADS);
+ tasks.add(new WriterTask(latch, sharedList));
+ for (int i = 1; i < NUM_THREADS; ++i) {
+ tasks.add(new ReaderTask(latch, sharedList));
+ }
+ for (Future<Boolean> result : Executors.newFixedThreadPool(NUM_THREADS).invokeAll(tasks)) {
+ assertTrue(result.get(60, TimeUnit.SECONDS));
+ }
+ }
+
+ @Test
+ public void requireThatAccessorsWork() {
+ ThreadRobustList<Object> lst = new ThreadRobustList<>();
+ assertTrue(lst.isEmpty());
+ assertFalse(lst.iterator().hasNext());
+
+ Object foo = new Object();
+ lst.add(foo);
+ assertFalse(lst.isEmpty());
+ Iterator<Object> it = lst.iterator();
+ assertNotNull(it);
+ assertTrue(it.hasNext());
+ assertSame(foo, it.next());
+ assertFalse(it.hasNext());
+
+ Object bar = new Object();
+ lst.add(bar);
+ assertFalse(lst.isEmpty());
+ assertNotNull(it = lst.iterator());
+ assertTrue(it.hasNext());
+ assertSame(foo, it.next());
+ assertTrue(it.hasNext());
+ assertSame(bar, it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void requireThatIteratorNextThrowsNoSuchElementExceptionWhenDone() {
+ ThreadRobustList<Object> lst = new ThreadRobustList<>();
+ Iterator<Object> it = lst.iterator();
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ fail();
+ } catch (NoSuchElementException e) {
+
+ }
+ }
+
+ @Test
+ public void requireThatIteratorRemoveIsNotSupported() {
+ ThreadRobustList<Object> lst = new ThreadRobustList<>();
+ Object obj = new Object();
+ lst.add(obj);
+ Iterator<Object> it = lst.iterator();
+ assertTrue(it.hasNext());
+ assertSame(obj, it.next());
+ try {
+ it.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+
+ }
+ }
+
+ private static class WriterTask implements Callable<Boolean> {
+
+ final CountDownLatch latch;
+ final ThreadRobustList<Integer> sharedList;
+
+ WriterTask(CountDownLatch latch, ThreadRobustList<Integer> sharedList) {
+ this.latch = latch;
+ this.sharedList = sharedList;
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+ latch.countDown();
+ assertTrue(latch.await(60, TimeUnit.SECONDS));
+ for (int i = 0; i < NUM_ITEMS_TO_WRITE; ++i) {
+ sharedList.add(i);
+ }
+ return true;
+ }
+ }
+
+ private static class ReaderTask implements Callable<Boolean> {
+
+ final CountDownLatch latch;
+ final ThreadRobustList<Integer> sharedList;
+
+ ReaderTask(CountDownLatch latch, ThreadRobustList<Integer> sharedList) {
+ this.latch = latch;
+ this.sharedList = sharedList;
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+ latch.countDown();
+ assertTrue(latch.await(60, TimeUnit.SECONDS));
+ for (int i = 0; i < NUM_TIMES_TO_READ; ++i) {
+ Iterator<Integer> it = sharedList.iterator();
+ for (int j = 0; it.hasNext(); ++j) {
+ assertEquals(j, it.next().intValue());
+ }
+ }
+ return true;
+ }
+ }
+}