package gobblin.eventhub.writer;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import gobblin.writer.SequentialBasedBatchAccumulator;
import org.testng.Assert;
import org.testng.annotations.Test;
import gobblin.writer.WriteCallback;
public class EventhubAccumulatorTest {
private CountDownLatch latchEmpty = new CountDownLatch(1);
private CountDownLatch latchCapacity = new CountDownLatch(1);
@Test
public void testAccumulatorEmpty() throws IOException, InterruptedException{
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 1000, 5);
// Spawn a new thread to add new batches
(new Thread(new AddBatchThread(accumulator))).start();
// Below three get operation will be blocked until we fill the empty queue
accumulator.getNextAvailableBatch();
accumulator.getNextAvailableBatch();
accumulator.getNextAvailableBatch();
this.latchEmpty.await();
// The spawned thread should unblock current thread because it removes some front batches
Assert.assertTrue(accumulator.getNumOfBatches() >=2);
Assert.assertTrue(accumulator.getNumOfBatches() <=5);
}
@Test
public void testAccumulatorCapacity () throws IOException, InterruptedException {
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 1000, 5);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 40; ++i) {
buffer.append('a');
}
String record = buffer.toString();
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
// Spawn a new thread to remove available batches
(new Thread(new RemoveBatchThread(accumulator))).start();
// Flowing two appends will be blocked
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
this.latchCapacity.await();
// The spawned thread should unblock current thread because it removes some front batches
Assert.assertEquals(accumulator.getNumOfBatches(), 4);
}
@Test
public void testCloseBeforeAwait () throws IOException, InterruptedException {
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 1000, 5);
(new Thread(new CloseAccumulatorThread(accumulator))).start();
Thread.sleep(1000);
Assert.assertNull(accumulator.getNextAvailableBatch());
}
@Test
public void testCloseAfterAwait () throws IOException, InterruptedException {
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 1000, 5);
(new Thread(new CloseAccumulatorThread(accumulator))).start();
// this thread should be blocked and waked up by spawned thread
Assert.assertNull(accumulator.getNextAvailableBatch());
}
@Test
public void testClose () throws IOException, InterruptedException {
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 3000, 5);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 40; ++i) {
buffer.append('a');
}
String record1 = buffer.toString() + "1";
String record2 = buffer.toString() + "2";
String record3 = buffer.toString() + "3";
String record4 = buffer.toString() + "4";
String record5 = buffer.toString() + "5";
accumulator.append(record1, WriteCallback.EMPTY);
accumulator.append(record2, WriteCallback.EMPTY);
accumulator.append(record3, WriteCallback.EMPTY);
accumulator.append(record4, WriteCallback.EMPTY);
accumulator.append(record5, WriteCallback.EMPTY);
(new Thread(new CloseAccumulatorThread(accumulator))).start();
Thread.sleep(1000);
Assert.assertEquals(accumulator.getNextAvailableBatch().getRecords().get(0), record1);
Assert.assertEquals(accumulator.getNextAvailableBatch().getRecords().get(0), record2);
Assert.assertEquals(accumulator.getNextAvailableBatch().getRecords().get(0), record3);
Assert.assertEquals(accumulator.getNextAvailableBatch().getRecords().get(0), record4);
Assert.assertEquals(accumulator.getNextAvailableBatch().getRecords().get(0), record5);
}
@Test
public void testExpiredBatch () throws IOException, InterruptedException {
SequentialBasedBatchAccumulator accumulator = new EventhubBatchAccumulator(64, 3000, 5);
String record = "1";
accumulator.append(record, WriteCallback.EMPTY);
Assert.assertNull(accumulator.getNextAvailableBatch());
Thread.sleep(3000);
Assert.assertNotNull(accumulator.getNextAvailableBatch());
}
public class CloseAccumulatorThread implements Runnable {
SequentialBasedBatchAccumulator accumulator;
public CloseAccumulatorThread (SequentialBasedBatchAccumulator accumulator) {
this.accumulator = accumulator;
}
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
this.accumulator.close();
}
}
public class RemoveBatchThread implements Runnable {
SequentialBasedBatchAccumulator accumulator;
public RemoveBatchThread (SequentialBasedBatchAccumulator accumulator) {
this.accumulator = accumulator;
}
public void run() {
try {
Thread.sleep(1000);
this.accumulator.getNextAvailableBatch();
this.accumulator.getNextAvailableBatch();
this.accumulator.getNextAvailableBatch();
latchCapacity.countDown();
} catch (InterruptedException e) {
}
}
}
public class AddBatchThread implements Runnable {
SequentialBasedBatchAccumulator accumulator;
public AddBatchThread (SequentialBasedBatchAccumulator accumulator) {
this.accumulator = accumulator;
}
public void run() {
try {
Thread.sleep(1000);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 40; ++i) {
buffer.append('a');
}
String record = buffer.toString();
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
accumulator.append(record, WriteCallback.EMPTY);
latchEmpty.countDown();
} catch (InterruptedException e) {
}
}
}
}