package org.jctools.channels.proxy;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
import org.jctools.channels.WaitStrategy;
import org.jctools.channels.mpsc.MpscOffHeapFixedSizeRingBuffer;
import org.jctools.channels.proxy.DemoIFace.CustomType;
import org.jctools.channels.spsc.SpscOffHeapFixedSizeRingBuffer;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class ProxyCreationTest {
private static final class ThrowExceptionOnFullQueue implements WaitStrategy {
private static final String MESSAGE = "queue is full";
@Override
public int idle(int idleCounter) {
throw new RuntimeException(MESSAGE);
}
}
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testGeneratedProxyInstance() {
ProxyChannel<DemoIFace> proxyChannel =
ProxyChannelFactory.createSpscProxy(10, DemoIFace.class, (idleCounter) -> 0);
DemoIFace proxy = proxyChannel.proxy();
/*
* Not sure what the proper behaviour is here but I can see from the
* types it should at least be a DemoIFace
*/
assertThat(proxyChannel.proxyInstance(proxy), instanceOf(DemoIFace.class));
}
@Test
public void givenGeneratedProxyUsingSpscReferenceChannel_whenCallMethods_expectAllCallsAreProxied() throws Exception {
util_givenGeneratedProxyUsingReferenceChannel_whenCallMethods_expectAllCallsAreProxied(SpscOffHeapFixedSizeRingBuffer.class);
}
@Test
public void givenGeneratedProxyUsingMpscReferenceChannel_whenCallMethods_expectAllCallsAreProxied() throws Exception {
util_givenGeneratedProxyUsingReferenceChannel_whenCallMethods_expectAllCallsAreProxied(MpscOffHeapFixedSizeRingBuffer.class);
}
private static void util_givenGeneratedProxyUsingReferenceChannel_whenCallMethods_expectAllCallsAreProxied(
Class<? extends ProxyChannelRingBuffer> backend) {
ProxyChannel<DemoIFace> proxyChannel =
ProxyChannelFactory.createProxy(10, DemoIFace.class, (idleCounter) -> 0, backend);
DemoIFace proxy = proxyChannel.proxy();
CustomType obj1 = new CustomType();
CustomType obj2 = new CustomType();
CustomType[] objArray = new CustomType[] { obj2, obj1 };
proxy.call1(1, 2);
proxy.call2(1, 2L, false);
proxy.call3();
proxy.call4(obj1, obj2);
proxy.call5(obj1, 1, obj2);
proxy.call6(6, objArray, obj1, obj2);
DemoIFace implAssertions = new DemoIFace() {
@Override
public void call1(int x, int y) {
Assert.assertEquals(1, x);
Assert.assertEquals(2, y);
}
@Override
public void call2(float x, double y, boolean z) {
Assert.assertEquals(1, x, 0.000000001);
Assert.assertEquals(2, y, 0.000000001);
Assert.assertEquals(false, z);
}
@Override
public void call3() {
throw new RuntimeException();
}
@Override
public void call4(Object x, CustomType y) {
Assert.assertSame(obj1, x);
Assert.assertSame(obj2, y);
}
@Override
public void call5(CustomType x, int y, CustomType z) {
Assert.assertSame(obj1, x);
Assert.assertEquals(1, y);
Assert.assertSame(obj2, z);
}
@Override
public void call6(int x, CustomType[] y, CustomType... z) {
Assert.assertEquals(6, x);
Assert.assertSame(objArray, y);
Assert.assertArrayEquals(new Object[] { obj1, obj2 }, z);
}
};
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
try {
proxyChannel.process(implAssertions, 1);
Assert.fail();
} catch (RuntimeException e) {
// Happy
}
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
}
@Test
public void givenGeneratedProxy_andQueueIsFull_whenCallAgain_expectRuntimeException() throws Exception {
ProxyChannel<DemoIFace> proxyChannel =
ProxyChannelFactory.createSpscProxy(10, DemoIFace.class, new ThrowExceptionOnFullQueue());
// capacity of 10 results in 16 slots in the queue
util_givenProxyChannel_andQueueIsFull_whenCallAgain_expectRuntimeException(16, proxyChannel);
}
@Test
public void givenDemoProxy_andQueueIsFull_whenCallAgain_expectRuntimeException() throws Exception {
ProxyChannel<DemoIFace> proxyChannel = new DemoProxyResult(10, new ThrowExceptionOnFullQueue());
// capacity of 10 results in 16 slots in the queue
util_givenProxyChannel_andQueueIsFull_whenCallAgain_expectRuntimeException(16, proxyChannel);
}
private void util_givenProxyChannel_andQueueIsFull_whenCallAgain_expectRuntimeException(
int capacity,
ProxyChannel<DemoIFace> proxyChannel) {
DemoIFace proxy = proxyChannel.proxy();
for (int i = 0; i < capacity; i++) {
proxy.call3();
}
// Then
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(ThrowExceptionOnFullQueue.MESSAGE);
// When
proxy.call3();
}
@Test
public void givenDemoProxyUsingSpscReferenceChannel_whenCallMethods_expectAllCallsAreProxied() throws Exception {
ProxyChannel<DemoIFace> proxyChannel = new DemoProxyResult(10, (idleCounter) -> 0);
DemoIFace proxy = proxyChannel.proxy();
CustomType obj1 = new CustomType();
CustomType obj2 = new CustomType();
CustomType[] objArray = new CustomType[] { obj2, obj1 };
proxy.call1(1, 2);
proxy.call2(1, 2L, false);
proxy.call3();
proxy.call4(obj1, obj2);
proxy.call5(obj1, 1, obj2);
proxy.call6(6, objArray, obj1, obj2);
DemoIFace implAssertions = new DemoIFace() {
@Override
public void call1(int x, int y) {
Assert.assertEquals(1, x);
Assert.assertEquals(2, y);
}
@Override
public void call2(float x, double y, boolean z) {
Assert.assertEquals(1, x, 0.000000001);
Assert.assertEquals(2, y, 0.000000001);
Assert.assertEquals(false, z);
}
@Override
public void call3() {
throw new RuntimeException();
}
@Override
public void call4(Object x, CustomType y) {
Assert.assertSame(obj1, x);
Assert.assertSame(obj2, y);
}
@Override
public void call5(CustomType x, int y, CustomType z) {
Assert.assertSame(obj1, x);
Assert.assertEquals(1, y);
Assert.assertSame(obj2, z);
}
@Override
public void call6(int x, CustomType[] y, CustomType... z) {
Assert.assertEquals(6, x);
Assert.assertSame(objArray, y);
Assert.assertArrayEquals(new Object[] { obj1, obj2 }, z);
}
};
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
try {
proxyChannel.process(implAssertions, 1);
Assert.fail();
} catch (RuntimeException e) {
// Happy
}
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
proxyChannel.process(implAssertions, 1);
}
}