package org.jctools.queues.alt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Arrays;
import java.util.Collection;
import org.jctools.queues.spec.ConcurrentQueueSpec;
import org.jctools.queues.spec.Ordering;
import org.jctools.queues.spec.Preference;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ConcurrentQueueSanityTest {
private static final int SIZE = 8192 * 2;
@SuppressWarnings("rawtypes")
@Parameterized.Parameters
public static Collection queues() {
return Arrays.asList(new Object[][] {
{ new ConcurrentQueueSpec(1, 1, 1, Ordering.FIFO, Preference.NONE) },
{ new ConcurrentQueueSpec(1, 1, SIZE, Ordering.FIFO, Preference.NONE) },
{ new ConcurrentQueueSpec(0, 0, 1, Ordering.FIFO, Preference.NONE) },
{ new ConcurrentQueueSpec(0, 0, SIZE, Ordering.FIFO, Preference.NONE) }, });
}
final ConcurrentQueue<Integer> q;
final ConcurrentQueueSpec spec;
public ConcurrentQueueSanityTest(ConcurrentQueueSpec spec) {
q = ConcurrentQueueFactory.newQueue(spec);
this.spec = spec;
}
@Before
public void clear() {
q.consumer().clear();
}
@Test
public void sanity() {
final ConcurrentQueueConsumer<Integer> consumer = q.consumer();
for (int i = 0; i < SIZE; i++) {
assertNull(consumer.poll());
assertEquals(0, q.size());
}
int i = 0;
final ConcurrentQueueProducer<Integer> producer = q.producer();
while (i < SIZE && producer.offer(i))
i++;
int size = i;
assertEquals(size, q.size());
if (spec.ordering == Ordering.FIFO) {
// expect FIFO
i = 0;
Integer e;
while ((e = consumer.poll()) != null) {
assertEquals(size - (i + 1), q.size());
assertEquals(e.intValue(), i++);
}
assertEquals(size, i);
} else {
// expect sum of elements is (size - 1) * size / 2 = 0 + 1 + .... + (size - 1)
int sum = (size - 1) * size / 2;
i = 0;
Integer e;
while ((e = consumer.poll()) != null) {
assertEquals(--size, q.size());
sum -= e;
}
assertEquals(0, sum);
}
}
@Test
public void sanityWeak() {
final ConcurrentQueueConsumer<Integer> consumer = q.consumer();
for (int i = 0; i < SIZE; i++) {
assertNull(consumer.weakPoll());
assertEquals(0, q.size());
}
int i = 0;
final ConcurrentQueueProducer<Integer> producer = q.producer();
while (i < SIZE && producer.weakOffer(i))
i++;
int size = i;
assertEquals(size, q.size());
if (spec.ordering == Ordering.FIFO) {
// expect FIFO
i = 0;
Integer e;
while ((e = consumer.weakPoll()) != null) {
assertEquals(size - (i + 1), q.size());
assertEquals(e.intValue(), i++);
}
assertEquals(size, i);
} else {
// expect sum of elements is (size - 1) * size / 2 = 0 + 1 + .... + (size - 1)
int sum = (size - 1) * size / 2;
i = 0;
Integer e;
while ((e = consumer.weakPoll()) != null) {
assertEquals(--size, q.size());
sum -= e;
}
assertEquals(0, sum);
}
}
int testCounter = 0;
@Test
public void sanityBatch() {
final ConcurrentQueueConsumer<Integer> consumer = q.consumer();
// consume batch will consume nothing, queue is empty
for (int i = 0; i < SIZE; i+=10) {
assertEquals(0, consumer.consume(e -> {
Assert.fail("expecting no elements");
}, 10));
assertEquals(0, q.size());
}
final ConcurrentQueueProducer<Integer> producer = q.producer();
if(!spec.isBounded())
return;
int produced = 0;
for (int i = 0; i < q.capacity() - 10; i+=10) {
produced += producer.produce(() -> testCounter < SIZE ? testCounter++ : null, 10);
assertEquals(i+10, produced);
}
produced += producer.produce(() -> testCounter < SIZE ? testCounter++ : null, q.capacity() - produced);
int size = testCounter;
assertEquals(size, q.size());
assertEquals(size, produced);
if (spec.ordering != Ordering.FIFO)
return;
int i = 0;
// expect FIFO
testCounter = 0;
Integer e;
while ((e = consumer.weakPoll()) != null) {
assertEquals(size - (i + 1), q.size());
assertEquals(e.intValue(), i++);
}
assertEquals(size, i);
}
}