/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.ringbuffer.impl;
import com.hazelcast.config.Config;
import com.hazelcast.config.RingbufferConfig;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IAtomicLong;
import com.hazelcast.core.ICompletableFuture;
import com.hazelcast.core.IFunction;
import com.hazelcast.ringbuffer.ReadResultSet;
import com.hazelcast.ringbuffer.Ringbuffer;
import com.hazelcast.ringbuffer.StaleSequenceException;
import com.hazelcast.spi.InternalCompletableFuture;
import com.hazelcast.spi.exception.DistributedObjectDestroyedException;
import com.hazelcast.test.AssertTask;
import com.hazelcast.test.HazelcastTestSupport;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static com.hazelcast.config.InMemoryFormat.OBJECT;
import static com.hazelcast.ringbuffer.OverflowPolicy.FAIL;
import static com.hazelcast.ringbuffer.OverflowPolicy.OVERWRITE;
import static com.hazelcast.test.AbstractHazelcastClassRunner.getTestMethodName;
import static java.lang.Math.max;
import static java.lang.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public abstract class RingbufferAbstractTest extends HazelcastTestSupport {
protected HazelcastInstance[] instances;
protected IAtomicLong atomicLong;
private Ringbuffer<String> ringbuffer;
private Config config;
private HazelcastInstance local;
private String name;
@Before
public void setup() {
config = new Config();
config.addRingBufferConfig(new RingbufferConfig("add_overwritingOldData*")
.setCapacity(5));
config.addRingBufferConfig(new RingbufferConfig("add_manyTimesRoundTheRing*")
.setCapacity(5));
config.addRingBufferConfig(new RingbufferConfig("readOne_whenBeforeHead*")
.setCapacity(5));
config.addRingBufferConfig(new RingbufferConfig("readOne_whenObjectInMemoryFormat*")
.setCapacity(5)
.setInMemoryFormat(OBJECT));
config.addRingBufferConfig(new RingbufferConfig("readManyAsync_whenEnoughItems_andObjectInMemoryFormat*")
.setCapacity(5)
.setInMemoryFormat(OBJECT));
config.addRingBufferConfig(new RingbufferConfig("addAsync_whenOverwrite_andNoTTL*")
.setCapacity(300)
.setTimeToLiveSeconds(0));
config.addRingBufferConfig(new RingbufferConfig("addAllAsync_whenCollectionExceedsCapacity*")
.setCapacity(5));
config.addRingBufferConfig(new RingbufferConfig("addAllAsync_manyTimesRoundTheRing*")
.setCapacity(50));
config.addRingBufferConfig(new RingbufferConfig("addAllAsync_whenObjectInMemoryFormat*")
.setCapacity(50)
.setInMemoryFormat(OBJECT));
config.addRingBufferConfig(new RingbufferConfig("addAsync_fail_whenNoSpace*")
.setCapacity(300)
.setTimeToLiveSeconds(10));
config.addRingBufferConfig(new RingbufferConfig("addAsync_whenOverwrite_andTTL*")
.setCapacity(300));
config.addRingBufferConfig(new RingbufferConfig("addAsync_whenOverwrite_andNoTTL*")
.setCapacity(300)
.setTimeToLiveSeconds(0));
config.addRingBufferConfig(new RingbufferConfig("remainingCapacity*")
.setCapacity(300)
.setTimeToLiveSeconds(10));
config.addRingBufferConfig(new RingbufferConfig("readOne_staleSequence*").setCapacity(5));
config.addRingBufferConfig(new RingbufferConfig("readOne_futureSequence*").setCapacity(5));
instances = newInstances(config);
local = instances[0];
HazelcastInstance target = instances[instances.length - 1];
name = HazelcastTestSupport.randomNameOwnedBy(target, getTestMethodName());
ringbuffer = local.getRingbuffer(name);
}
protected abstract HazelcastInstance[] newInstances(Config config);
private static List<String> randomList(int size) {
List<String> items = new ArrayList<String>(size);
for (int k = 0; k < size; k++) {
items.add("" + k);
}
return items;
}
// ================ tailSequence ==========================================
@Test
public void tailSequence_whenNothingAdded() {
long found = ringbuffer.tailSequence();
assertEquals(-1, found);
}
// ================ remainingCapacity ==========================================
// the actual logic of remaining capacity is tested directly in the RingbufferContainerTest. So we just need
// to do some basic tests to see if the operation itself is set up correctly
@Test
public void remainingCapacity() {
assertEquals(ringbuffer.capacity(), ringbuffer.remainingCapacity());
ringbuffer.add("first");
assertEquals(ringbuffer.capacity() - 1, ringbuffer.remainingCapacity());
ringbuffer.add("second");
assertEquals(ringbuffer.capacity() - 2, ringbuffer.remainingCapacity());
}
// ================ headSequence ==========================================
@Test
public void headSequence_whenNothingAdded() {
long found = ringbuffer.headSequence();
assertEquals(0, found);
}
// ================ capacity =========================================
@Test
public void capacity() {
assertEquals(RingbufferConfig.DEFAULT_CAPACITY, ringbuffer.capacity());
}
// ================ size =========================================
@Test
public void size_whenUnused() {
long found = ringbuffer.size();
assertEquals(0, found);
}
@Test
public void size_whenSomeItemsAdded() throws Exception {
// we are adding some items, but we don't go beyond the capacity
// most of the testing already is done in the RingbufferContainerTest
for (int k = 1; k <= 100; k++) {
ringbuffer.add("foo");
assertEquals(k, ringbuffer.size());
}
}
// ================ add ==========================================
@Test(expected = NullPointerException.class)
public void addAsync_whenNullItem() {
ringbuffer.addAsync(null, FAIL);
}
@Test(expected = NullPointerException.class)
public void addAsync_whenNullOverflowPolicy() {
ringbuffer.addAsync("foo", null);
}
@Test
public void addAsync_fail_whenSpace() throws Exception {
long sequence = ringbuffer.addAsync("item", FAIL).get();
assertEquals(0, sequence);
assertEquals(0, ringbuffer.headSequence());
assertEquals(0, ringbuffer.tailSequence());
assertEquals("item", ringbuffer.readOne(sequence));
}
@Test
public void addAsync_fail_whenNoSpace() throws Exception {
// fill the buffer with data
for (int k = 0; k < ringbuffer.capacity(); k++) {
ringbuffer.add("old");
}
long oldHead = ringbuffer.headSequence();
long oldTail = ringbuffer.tailSequence();
long result = ringbuffer.addAsync("item", FAIL).get();
assertEquals(-1, result);
assertEquals(oldHead, ringbuffer.headSequence());
assertEquals(oldTail, ringbuffer.tailSequence());
// verify that all the old data is still present.
for (long seq = oldHead; seq <= oldTail; seq++) {
assertEquals("old", ringbuffer.readOne(seq));
}
}
@Test
public void addAsync_overwrite_whenSpace() throws Exception {
long sequence = ringbuffer.addAsync("item", OVERWRITE).get();
assertEquals(0, sequence);
assertEquals(0, ringbuffer.headSequence());
assertEquals(0, ringbuffer.tailSequence());
assertEquals("item", ringbuffer.readOne(sequence));
}
@Test
public void addAsync_whenOverwrite_andTTL() throws ExecutionException, InterruptedException {
addAsync_whenOverwrite();
}
@Test
public void addAsync_whenOverwrite_andNoTTL() throws ExecutionException, InterruptedException {
addAsync_whenOverwrite();
}
private void addAsync_whenOverwrite() throws InterruptedException, ExecutionException {
RingbufferConfig c = config.getRingbufferConfig(ringbuffer.getName());
// fill the buffer with data
for (int k = 0; k < ringbuffer.capacity(); k++) {
ringbuffer.add("old");
}
for (int iteration = 0; iteration < c.getCapacity() * 100; iteration++) {
long oldTail = ringbuffer.tailSequence();
String item = "" + iteration;
long sequence = ringbuffer.addAsync(item, OVERWRITE).get();
long expectedSequence = oldTail + 1;
assertEquals(expectedSequence, sequence);
assertEquals(expectedSequence, ringbuffer.tailSequence());
if (ringbuffer.tailSequence() < c.getCapacity()) {
assertEquals(0, ringbuffer.headSequence());
} else {
assertEquals(ringbuffer.tailSequence() - c.getCapacity() + 1, ringbuffer.headSequence());
}
assertEquals(item, ringbuffer.readOne(expectedSequence));
}
}
// ================ add ==========================================
@Test(expected = NullPointerException.class)
public void add_whenNullItem() throws Exception {
ringbuffer.add(null);
}
/**
* In this test we are going to overwrite old data a few times (so we are going round
* the ring a few times). At the end we expect to see the latest items; everything
* that is overwritten should not be shown anymore.
*/
@Test
public void add_overwritingOldData() throws Exception {
RingbufferConfig c = config.getRingbufferConfig(ringbuffer.getName());
long lastSequence = ringbuffer.tailSequence();
long expectedTailSeq = 0;
for (long k = 0; k < 2 * c.getCapacity(); k++) {
long sequence = ringbuffer.add("item-" + k);
lastSequence = ringbuffer.tailSequence();
assertEquals(expectedTailSeq, sequence);
assertEquals(expectedTailSeq, lastSequence);
assertEquals(expectedTailSeq, ringbuffer.tailSequence());
expectedTailSeq++;
}
assertEquals(lastSequence - c.getCapacity() + 1, ringbuffer.headSequence());
// verifying the content
for (long sequence = ringbuffer.headSequence(); sequence <= ringbuffer.tailSequence(); sequence++) {
assertEquals("bad content at sequence:" + sequence, "item-" + sequence, ringbuffer.readOne(sequence));
}
}
// this test verifies that the add works correctly if we go round the ringbuffer many times.
@Test
public void add_manyTimesRoundTheRing() throws Exception {
RingbufferConfig c = config.getRingbufferConfig(ringbuffer.getName());
for (int iteration = 0; iteration < c.getCapacity() * 100; iteration++) {
long oldTail = ringbuffer.tailSequence();
String item = "" + iteration;
long sequence = ringbuffer.add(item);
long expectedSequence = oldTail + 1;
assertEquals(expectedSequence, sequence);
assertEquals(expectedSequence, ringbuffer.tailSequence());
if (ringbuffer.tailSequence() < c.getCapacity()) {
assertEquals(0, ringbuffer.headSequence());
} else {
assertEquals(ringbuffer.tailSequence() - c.getCapacity() + 1, ringbuffer.headSequence());
}
assertEquals(item, ringbuffer.readOne(expectedSequence));
}
}
// ================== addAll ========================================
@Test(expected = IllegalArgumentException.class)
public void addAllAsync_whenCollectionTooLarge() {
ringbuffer.addAllAsync(randomList(RingbufferProxy.MAX_BATCH_SIZE + 1), OVERWRITE);
}
@Test(expected = NullPointerException.class)
public void addAllAsync_whenNullCollection() {
ringbuffer.addAllAsync(null, OVERWRITE);
}
@Test(expected = NullPointerException.class)
public void addAllAsync_whenCollectionContainsNullElement() {
List<String> list = new LinkedList<String>();
list.add(null);
ringbuffer.addAllAsync(list, OVERWRITE);
}
@Test(expected = NullPointerException.class)
public void addAllAsync_whenNullOverflowPolicy() {
ringbuffer.addAllAsync(new LinkedList<String>(), null);
}
@Test(expected = IllegalArgumentException.class)
public void addAllAsync_whenEmpty() throws Exception {
ringbuffer.addAllAsync(new LinkedList<String>(), OVERWRITE);
}
@Test(expected = IllegalArgumentException.class)
public void readOne_futureSequence() throws Exception {
for (int i = 0; i < 2 * ringbuffer.capacity(); i++) {
ringbuffer.add(String.valueOf(i));
}
ringbuffer.readOne(ringbuffer.tailSequence() + 2);
}
@Test(expected = StaleSequenceException.class)
public void readOne_staleSequence() throws Exception {
for (int i = 0; i < 2 * ringbuffer.capacity(); i++) {
ringbuffer.add(String.valueOf(i));
}
ringbuffer.readOne(ringbuffer.headSequence() - 1);
}
@Test
public void addAllAsync_whenCollectionExceedsCapacity() throws Exception {
RingbufferConfig c = config.getRingbufferConfig(ringbuffer.getName());
long oldTailSeq = ringbuffer.tailSequence();
List<String> items = randomList(c.getCapacity() + 20);
long result = ringbuffer.addAllAsync(items, OVERWRITE).get();
assertEquals(oldTailSeq + items.size(), ringbuffer.tailSequence());
assertEquals(ringbuffer.tailSequence() - c.getCapacity() + 1, ringbuffer.headSequence());
assertEquals(ringbuffer.tailSequence(), result);
}
@Test
public void addAllAsync_whenObjectInMemoryFormat() throws Exception {
List<String> items = randomList(10);
long oldTailSeq = ringbuffer.tailSequence();
long result = ringbuffer.addAllAsync(items, OVERWRITE).get();
assertEquals(0, ringbuffer.headSequence());
assertEquals(oldTailSeq + items.size(), ringbuffer.tailSequence());
assertEquals(ringbuffer.tailSequence(), result);
long startSequence = ringbuffer.headSequence();
for (int k = 0; k < items.size(); k++) {
assertEquals(items.get(k), ringbuffer.readOne(startSequence + k));
}
}
@Test
public void addAllAsync() throws Exception {
List<String> items = randomList(10);
long oldTailSeq = ringbuffer.tailSequence();
long result = ringbuffer.addAllAsync(items, OVERWRITE).get();
assertEquals(0, ringbuffer.headSequence());
assertEquals(oldTailSeq + items.size(), ringbuffer.tailSequence());
assertEquals(ringbuffer.tailSequence(), result);
long startSequence = ringbuffer.headSequence();
for (int k = 0; k < items.size(); k++) {
assertEquals(items.get(k), ringbuffer.readOne(startSequence + k));
}
}
// this test verifies that the addAllAsync works correctly if we go round the ringbuffer many times.
@Test
public void addAllAsync_manyTimesRoundTheRing() throws Exception {
RingbufferConfig c = config.getRingbufferConfig(ringbuffer.getName());
Random random = new Random();
for (int iteration = 0; iteration < 1000; iteration++) {
List<String> items = randomList(max(1, random.nextInt(c.getCapacity())));
long previousTailSeq = ringbuffer.tailSequence();
long result = ringbuffer.addAllAsync(items, OVERWRITE).get();
assertEquals(previousTailSeq + items.size(), ringbuffer.tailSequence());
if (ringbuffer.tailSequence() < c.getCapacity()) {
assertEquals(0, ringbuffer.headSequence());
} else {
assertEquals(ringbuffer.tailSequence() - c.getCapacity() + 1, ringbuffer.headSequence());
}
assertEquals(ringbuffer.tailSequence(), result);
long startSequence = previousTailSeq + 1;
for (int k = 0; k < items.size(); k++) {
assertEquals(items.get(k), ringbuffer.readOne(startSequence + k));
}
}
}
// ================== read ========================================
@Test
public void readOne() throws Exception {
ringbuffer.add("first");
ringbuffer.add("second");
long oldHead = ringbuffer.headSequence();
long oldTail = ringbuffer.tailSequence();
assertEquals("first", ringbuffer.readOne(0));
assertEquals("second", ringbuffer.readOne(1));
// make sure that the head/tail of the ringbuffer have not changed.
assertEquals(oldHead, ringbuffer.headSequence());
assertEquals(oldTail, ringbuffer.tailSequence());
}
@Test
public void readOne_whenObjectInMemoryFormat() throws Exception {
ringbuffer.add("first");
ringbuffer.add("second");
long oldHead = ringbuffer.headSequence();
long oldTail = ringbuffer.tailSequence();
assertEquals("first", ringbuffer.readOne(0));
assertEquals("second", ringbuffer.readOne(1));
// make sure that the head/tail of the ringbuffer have not changed.
assertEquals(oldHead, ringbuffer.headSequence());
assertEquals(oldTail, ringbuffer.tailSequence());
}
@Test
public void readOne_whenOneAfterTail_thenBlock() throws Exception {
ringbuffer.add("1");
ringbuffer.add("2");
final long tail = ringbuffer.tailSequence();
// first we do the invocation. This invocation is going to block
final Future f = spawn(new Callable<String>() {
@Override
public String call() throws Exception {
return ringbuffer.readOne(tail + 1);
}
});
// then we check if the future is not going to complete.
assertTrueAllTheTime(new AssertTask() {
@Override
public void run() throws Exception {
assertFalse(f.isDone());
}
}, 2);
// then we add the item
ringbuffer.add("3");
// and eventually the future should complete
assertCompletesEventually(f);
assertEquals("3", f.get());
}
@Test(expected = IllegalArgumentException.class)
public void readOne_whenTooFarAfterTail_thenIllegalArgumentException() throws Exception {
ringbuffer.add("1");
ringbuffer.add("2");
long tailSeq = ringbuffer.tailSequence();
ringbuffer.readOne(tailSeq + 2);
}
@Test
public void readOne_whenBeforeHead_thenStaleSequenceException() throws Exception {
RingbufferConfig ringbufferConfig = config.getRingbufferConfig(ringbuffer.getName());
for (int k = 0; k < ringbufferConfig.getCapacity() * 2; k++) {
ringbuffer.add("foo");
}
long headSeq = ringbuffer.headSequence();
try {
ringbuffer.readOne(headSeq - 1);
fail();
} catch (StaleSequenceException expected) {
assertEquals(headSeq, expected.getHeadSeq());
}
}
@Test(expected = IllegalArgumentException.class)
public void read_whenNegativeSequence_thenIllegalArgumentException() throws Exception {
ringbuffer.readOne(-1);
}
// ==================== asyncReadOrWait ==============================
@Test
public void readManyAsync_whenReadingBeyondTail() throws ExecutionException, InterruptedException {
ringbuffer.add("1");
ringbuffer.add("2");
long seq = ringbuffer.tailSequence() + 2;
ICompletableFuture f = ringbuffer.readManyAsync(seq, 1, 1, null);
try {
f.get();
fail();
} catch (ExecutionException e) {
assertInstanceOf(IllegalArgumentException.class, e.getCause());
}
}
@Test
public void readyManyAsync_whenSomeWaitingForSingleItemNeeded() throws ExecutionException, InterruptedException {
final ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 1, 10, null);
assertTrueAllTheTime(new AssertTask() {
@Override
public void run() throws Exception {
assertFalse(f.isDone());
}
}, 5);
ringbuffer.add("1");
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertThat(f.get(), contains("1"));
assertEquals(1, resultSet.readCount());
}
@Test
public void readManyAsync_whenSomeWaitingNeeded() throws ExecutionException, InterruptedException {
final ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 2, 10, null);
assertTrueAllTheTime(new AssertTask() {
@Override
public void run() throws Exception {
assertFalse(f.isDone());
}
}, 5);
ringbuffer.add("1");
assertTrueAllTheTime(new AssertTask() {
@Override
public void run() throws Exception {
assertFalse(f.isDone());
}
}, 5);
ringbuffer.add("2");
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertNotNull(resultSet);
assertThat(f.get(), contains("1", "2"));
assertEquals(2, resultSet.readCount());
}
@Test
public void readManyAsync_whenMinZeroAndItemAvailable() throws ExecutionException, InterruptedException {
ringbuffer.add("1");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 0, 10, null);
assertCompletesEventually(f);
assertThat(f.get(), contains("1"));
}
@Test
public void readManyAsync_whenMinZeroAndNoItemAvailable() throws ExecutionException, InterruptedException {
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 0, 10, null);
assertCompletesEventually(f);
assertEquals(0, f.get().readCount());
}
@Test
public void readManyAsync_whenEnoughItems() throws ExecutionException, InterruptedException {
ringbuffer.add("item1");
ringbuffer.add("item2");
ringbuffer.add("item3");
ringbuffer.add("item4");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(1, 1, 2, null);
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertNotNull(resultSet);
Assert.assertThat(f.get(), contains("item2", "item3"));
assertEquals(2, resultSet.readCount());
}
@Test
public void readManyAsync_whenEnoughItems_andObjectInMemoryFormat() throws ExecutionException, InterruptedException {
ringbuffer.add("item1");
ringbuffer.add("item2");
ringbuffer.add("item3");
ringbuffer.add("item4");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(1, 1, 2, null);
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertNotNull(resultSet);
assertThat(f.get(), contains("item2", "item3"));
assertEquals(2, resultSet.readCount());
}
public static class GoodStringFunction implements IFunction<String, Boolean>, Serializable {
@Override
public Boolean apply(String input) {
return input.startsWith("good");
}
}
@Test
public void readManyAsync_withFilter() throws ExecutionException, InterruptedException {
ringbuffer.add("good1");
ringbuffer.add("bad1");
ringbuffer.add("good2");
ringbuffer.add("bad");
ringbuffer.add("good3");
ringbuffer.add("bad1");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 2, 10, new GoodStringFunction());
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertNotNull(resultSet);
Assert.assertThat(f.get(), contains("good1", "good2", "good3"));
assertEquals(6, resultSet.readCount());
}
@Test
public void readManyAsync_emptyBatchAndNoItems() throws Exception {
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(0, 0, 10, null);
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertEquals(0, f.get().readCount());
assertEquals(0, resultSet.readCount());
}
@Test
public void readManyAsync_whenMoreAvailableThanMinimumLessThanMaximum() throws ExecutionException, InterruptedException {
ringbuffer.add("1");
ringbuffer.add("2");
ringbuffer.add("3");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(ringbuffer.headSequence(), 2, 10, null);
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertThat(f.get(), contains("1", "2", "3"));
assertEquals(3, resultSet.readCount());
}
@Test
public void readManyAsync_whenMoreAvailableThanMaximum() throws ExecutionException, InterruptedException {
ringbuffer.add("1");
ringbuffer.add("2");
ringbuffer.add("3");
ICompletableFuture<ReadResultSet<String>> f = ringbuffer.readManyAsync(ringbuffer.headSequence(), 1, 2, null);
assertCompletesEventually(f);
ReadResultSet<String> resultSet = f.get();
assertNotNull(resultSet);
assertThat(f.get(), contains("1", "2"));
assertEquals(2, resultSet.readCount());
}
@Test(expected = IllegalArgumentException.class)
public void readManyAsync_whenMinCountLargerThanCapacity() {
ringbuffer.readManyAsync(0, RingbufferConfig.DEFAULT_CAPACITY + 1, RingbufferConfig.DEFAULT_CAPACITY + 1, null);
}
@Test(expected = IllegalArgumentException.class)
public void readManyAsync_whenStartSequenceNegative() {
ringbuffer.readManyAsync(-1, 1, 1, null);
}
@Test(expected = IllegalArgumentException.class)
public void readManyAsync_whenMinCountNegative() {
ringbuffer.readManyAsync(0, -1, 1, null);
}
@Test(expected = IllegalArgumentException.class)
public void readManyAsync_whenMaxSmallerThanMinCount() {
ringbuffer.readManyAsync(0, 5, 4, null);
}
@Test
public void readManyAsync_whenMaxCountTooHigh() throws Exception {
ringbuffer.readManyAsync(0, 1, RingbufferProxy.MAX_BATCH_SIZE, null);
}
// ===================== destroy ==========================
@Test
public void destroy() throws Exception {
ringbuffer.add("1");
ringbuffer.destroy();
ringbuffer = local.getRingbuffer(name);
assertEquals(0, ringbuffer.headSequence());
assertEquals(-1, ringbuffer.tailSequence());
}
@Test(expected = DistributedObjectDestroyedException.class)
public void destroy_whenBlockedThreads_thenDistributedObjectDestroyedException() throws Exception {
spawn(new Runnable() {
@Override
public void run() {
sleepSeconds(2);
ringbuffer.destroy();
}
});
InternalCompletableFuture f = (InternalCompletableFuture) ringbuffer.readManyAsync(0, 1, 1, null);
f.join();
}
// ===================== misc ==========================
@Test
public void test_toString() {
String actual = ringbuffer.toString();
String expected = format("Ringbuffer{name='%s'}", ringbuffer.getName());
assertEquals(expected, actual);
}
}