package org.jacorb.test.orb.giop;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.ByteArrayOutputStream;
import org.jacorb.config.Configuration;
import org.jacorb.orb.giop.ClientGIOPConnection;
import org.jacorb.orb.giop.GIOPConnection;
import org.jacorb.orb.giop.Messages;
import org.jacorb.orb.giop.ReplyListener;
import org.jacorb.test.harness.ORBTestCase;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.omg.ETF.BufferHolder;
import org.omg.ETF.Connection;
import org.omg.ETF.Profile;
import org.slf4j.LoggerFactory;
public class GIOPConnectionTest extends ORBTestCase
{
@Test
public void testCorrectFragmentedResponseSize() throws Exception
{
// Prepare data on the wire
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("GIOP".getBytes()); // magic
baos.write(1); // major: 1
baos.write(2); // minor: 2
baos.write(2); // more fragments, big endian (0000 0010)
baos.write(1); // type: Response
baos.write(new byte[]{0, 0, 0, 11}); // size
baos.write(new byte[]{0, 0, 0, 0}); // request ID
baos.write(new byte[]{0, 0, 0, 0}); // no service context
baos.write("foo".getBytes()); // content
baos.write("GIOP".getBytes()); // magic
baos.write(1); // major: 1
baos.write(2); // minor: 2
baos.write(1); // no more fragments, little endian (0000 0001)
baos.write(7); // type: Fragment
baos.write(new byte[]{10, 0, 0, 0}); // size
baos.write(new byte[]{0, 0, 0, 0}); // request ID
baos.write("barbaz".getBytes()); // content
final byte[] buffer = baos.toByteArray();
Connection transport = mock(Connection.class);
when(transport.is_connected())
.thenReturn(true);
when(transport.read(any(BufferHolder.class), anyInt(), anyInt(), anyInt(), anyLong()))
.thenAnswer(new TransportAnswer(buffer));
Configuration config = mock(Configuration.class);
when(config.getORB())
.thenReturn(getORB());
when(config.getLogger(anyString()))
.thenReturn(LoggerFactory.getLogger(GIOPConnectionTest.class));
when(config.getAttributeAsBoolean(matches(".*\\.disconnect_after_systemexception"), anyBoolean()))
.thenReturn(true);
ReplyListener listener = mock(ReplyListener.class);
GIOPConnection conn = new ClientGIOPConnection(mock(Profile.class), transport, null, listener, null);
conn.configure(config);
// Read the wire
conn.receiveMessages();
// Single message received, correct size
ArgumentCaptor<byte[]> arg = ArgumentCaptor.forClass(byte[].class);
verify(listener)
.replyReceived(arg.capture(), eq(conn));
assertEquals(1, Messages.getMsgType(arg.getValue()));
assertEquals(17, Messages.getMsgSize(arg.getValue()));
}
static class TransportAnswer implements Answer<Integer>
{
TransportAnswer(byte[] buffer)
{
this.buffer = buffer;
}
@Override
public Integer answer(InvocationOnMock inv) throws Throwable
{
if (buffer.length <= readIndex)
throw new org.omg.CORBA.COMM_FAILURE();
BufferHolder holder = inv.getArgumentAt(0, BufferHolder.class);
int offset = inv.getArgumentAt(1, Integer.class);
int minLength = inv.getArgumentAt(2, Integer.class);
System.arraycopy(buffer, readIndex, holder.value, offset, minLength);
readIndex += minLength;
return minLength;
}
private byte[] buffer;
int readIndex = 0;
}
}