package io.lumify.core.util;
import io.lumify.core.metrics.JmxMetricsManager;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Timer;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ThreadedInputStreamProcessTest {
@Mock
private JmxMetricsManager metricsManager;
@Mock
private Counter metricCounter;
@Mock
private Timer metricTimer;
@Mock
private Timer.Context metricTimerContext;
@Before
public void before() {
when(metricsManager.getNamePrefix(anyObject())).thenReturn("metric1");
when(metricsManager.counter(anyString())).thenReturn(metricCounter);
when(metricsManager.timer(anyString())).thenReturn(metricTimer);
when(metricTimer.time()).thenReturn(metricTimerContext);
}
@Test
public void testDoWork() throws Exception {
ArrayList<ThreadedTeeInputStreamWorker<byte[], String>> workers = new ArrayList<ThreadedTeeInputStreamWorker<byte[], String>>();
TestThreadedTeeInputStreamWorker worker1 = new TestThreadedTeeInputStreamWorker("1");
worker1.setMetricsManager(metricsManager);
workers.add(worker1);
TestThreadedTeeInputStreamWorker worker2 = new TestThreadedTeeInputStreamWorker("2");
worker2.setMetricsManager(metricsManager);
workers.add(worker2);
ThreadedInputStreamProcess process = new ThreadedInputStreamProcess<byte[], String>("test", workers);
byte[] data = createMockData(10);
// first run
ByteArrayInputStream in = new ByteArrayInputStream(data);
List<ThreadedTeeInputStreamWorker.WorkResult<byte[]>> results = process.doWork(in, "test1");
assertEquals(2, results.size());
assertEquals(null, results.get(0).getError());
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write("1".getBytes());
expected.write("test1".getBytes());
expected.write(data);
assertArrayEquals(expected.toByteArray(), results.get(0).getResult());
assertEquals(null, results.get(1).getError());
expected = new ByteArrayOutputStream();
expected.write("2".getBytes());
expected.write("test1".getBytes());
expected.write(data);
assertArrayEquals(expected.toByteArray(), results.get(1).getResult());
// second run
in = new ByteArrayInputStream(data);
results = process.doWork(in, "test2");
assertEquals(2, results.size());
assertEquals(null, results.get(0).getError());
expected = new ByteArrayOutputStream();
expected.write("1".getBytes());
expected.write("test2".getBytes());
expected.write(data);
assertArrayEquals(expected.toByteArray(), results.get(0).getResult());
assertEquals(null, results.get(1).getError());
expected = new ByteArrayOutputStream();
expected.write("2".getBytes());
expected.write("test2".getBytes());
expected.write(data);
assertArrayEquals(expected.toByteArray(), results.get(1).getResult());
}
@Test
public void testDoWorkWithException() throws Exception {
ArrayList<ThreadedTeeInputStreamWorker<byte[], String>> workers = new ArrayList<ThreadedTeeInputStreamWorker<byte[], String>>();
TestThreadedTeeInputStreamWorker worker1 = new TestThreadedTeeInputStreamWorker("1");
worker1.setMetricsManager(metricsManager);
workers.add(worker1);
TestThreadedTeeInputStreamWorkerWithException worker2 = new TestThreadedTeeInputStreamWorkerWithException("2");
worker2.setMetricsManager(metricsManager);
workers.add(worker2);
ThreadedInputStreamProcess process = new ThreadedInputStreamProcess<byte[], String>("test", workers);
byte[] data = createMockData(10);
// first run
ByteArrayInputStream in = new ByteArrayInputStream(data);
List<ThreadedTeeInputStreamWorker.WorkResult<byte[]>> results = process.doWork(in, "test1", 5);
assertEquals(2, results.size());
assertEquals(null, results.get(0).getError());
assertNotEquals(null, results.get(1).getError());
assertEquals("2 throwing exception", results.get(1).getError().getMessage());
ByteArrayOutputStream expected = new ByteArrayOutputStream();
expected.write("1".getBytes());
expected.write("test1".getBytes());
expected.write(data);
assertArrayEquals(expected.toByteArray(), results.get(0).getResult());
}
private byte[] createMockData(int len) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = (byte) i;
}
return data;
}
private static class TestThreadedTeeInputStreamWorker extends ThreadedTeeInputStreamWorker<byte[], String> {
private final String prefix;
public TestThreadedTeeInputStreamWorker(String prefix) {
this.prefix = prefix;
}
@Override
protected byte[] doWork(InputStream work, String s) throws Exception {
Thread.sleep(new Random().nextInt(100));
ByteArrayOutputStream temp = new ByteArrayOutputStream();
temp.write(prefix.getBytes());
temp.write(s.getBytes());
IOUtils.copy(work, temp);
return temp.toByteArray();
}
}
private static class TestThreadedTeeInputStreamWorkerWithException extends ThreadedTeeInputStreamWorker<byte[], String> {
private final String prefix;
public TestThreadedTeeInputStreamWorkerWithException(String prefix) {
this.prefix = prefix;
}
@Override
protected byte[] doWork(InputStream work, String s) throws Exception {
throw new RuntimeException(prefix + " throwing exception");
}
}
}