package org.jacorb.test.orb.connection; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.jacorb.config.Configuration; import org.jacorb.orb.giop.ClientConnection; import org.jacorb.orb.giop.GIOPConnection; import org.jacorb.orb.giop.GIOPConnectionManager; import org.jacorb.orb.giop.LocateRequestOutputStream; import org.jacorb.orb.giop.MessageOutputStream; import org.jacorb.orb.giop.Messages; import org.jacorb.orb.giop.ReplyInputStream; import org.jacorb.orb.giop.ReplyListener; import org.jacorb.orb.giop.RequestInputStream; import org.jacorb.orb.giop.RequestListener; import org.jacorb.orb.giop.RequestOutputStream; import org.jacorb.orb.giop.ServerGIOPConnection; import org.jacorb.orb.iiop.IIOPAddress; import org.jacorb.orb.iiop.IIOPProfile; import org.jacorb.test.harness.ORBTestCase; import org.junit.Before; import org.junit.Test; import org.omg.ETF.BufferHolder; import org.omg.ETF.Profile; import org.omg.GIOP.MsgType_1_1; /** * GIOPConnectionTest.java * * @author Nicolas Noffke */ public class GIOPConnectionTest extends ORBTestCase { private Configuration config; @Before public void setUp() throws Exception { config = this.getORB().getConfiguration(); } class DummyTransport extends org.omg.ETF._ConnectionLocalBase { private boolean closed = false; private byte[] data = null; private int index = 0; private ByteArrayOutputStream b_out = new ByteArrayOutputStream(); private org.omg.ETF.Profile profile = new IIOPProfile ( new IIOPAddress ("127.0.0.1", 4711), null, getORB().getGIOPMinorVersion() ); public DummyTransport( List<byte[]> messages ) { // convert the message list into a plain byte array int size = 0; for (Iterator<byte[]> i = messages.iterator(); i.hasNext();) { size += i.next().length; } data = new byte[size]; int index = 0; for (Iterator<byte[]> i = messages.iterator(); i.hasNext();) { byte[] msg = i.next(); System.arraycopy(msg, 0, data, index, msg.length); index += msg.length; } } public byte[] getWrittenMessage() { return b_out.toByteArray(); } @Override public void connect (org.omg.ETF.Profile profile, long time_out) { // nothing } public boolean hasBeenClosed() { return closed; } @Override public boolean is_connected() { return !closed; } @Override public void write( boolean is_first, boolean is_last, byte[] message, int start, int size, long timeout ) { b_out.write( message, start, size ); } @Override public void flush() { } @Override public void close() { closed = true; } public boolean isSSL() { return false; } public void turnOnFinalTimeout() { } @Override public Profile get_server_profile() { return profile; } @Override public int read (BufferHolder data, int offset, int min_length, int max_length, long time_out) { if (this.index + min_length > this.data.length) { throw new org.omg.CORBA.COMM_FAILURE ("end of stream"); } System.arraycopy(this.data, this.index, data.value, offset, min_length); this.index += min_length; return min_length; } @Override public boolean is_data_available() { return true; } @Override public boolean supports_callback() { return false; } @Override public boolean use_handle_time_out() { return false; } @Override public boolean wait_next_data(long time_out) { return false; } } private class DummyRequestListener implements RequestListener { private byte[] request = null; public DummyRequestListener() { } public byte[] getRequest() { return request; } @Override public void requestReceived( byte[] request, GIOPConnection connection ) { this.request = request; } @Override public void locateRequestReceived( byte[] request, GIOPConnection connection ) { this.request = request; } @Override public void cancelRequestReceived( byte[] request, GIOPConnection connection ) { this.request = request; } } private class DummyReplyListener implements ReplyListener { private byte[] reply = null; public DummyReplyListener() { } public byte[] getReply() { return reply; } @Override public void replyReceived( byte[] reply, GIOPConnection connection ) { this.reply = reply; } @Override public void locateReplyReceived( byte[] reply, GIOPConnection connection ) { this.reply = reply; } @Override public void closeConnectionReceived( byte[] close_conn, GIOPConnection connection ) { this.reply = close_conn; } } @Test public void testGIOP_1_2_CorrectFragmentedRequest() { List<byte[]> messages = new Vector<byte[]>(); RequestOutputStream r_out = new RequestOutputStream( getORB(), //ClientConnection (ClientConnection) null, //request id 0, //operation "foo", // response expected true, // SYNC_SCOPE (irrelevant) (short)-1, //request start time null, //request end time null, //reply start time null, //object key new byte[1], 2 // giop minor ); //manually write the first half of the string "barbaz" r_out.write_ulong( 7 ); //string length r_out.write_octet( (byte) 'b' ); r_out.write_octet( (byte) 'a' ); r_out.write_octet( (byte) 'r' ); r_out.insertMsgSize(); byte[] b = r_out.getBufferCopy(); b[6] |= 0x02; //set "more fragments follow" messages.add( b ); MessageOutputStream m_out = new MessageOutputStream(orb); m_out.writeGIOPMsgHeader( MsgType_1_1._Fragment, 2 // giop minor ); m_out.write_ulong( 0 ); // Fragment Header (request id) m_out.write_octet( (byte) 'b' ); m_out.write_octet( (byte) 'a' ); m_out.write_octet( (byte) 'z' ); m_out.write_octet( (byte) 0); m_out.insertMsgSize(); messages.add( m_out.getBufferCopy() ); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } ServerGIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //did the GIOPConnection hand the complete request over to the //listener? assertTrue( request_listener.getRequest() != null ); RequestInputStream r_in = new RequestInputStream ( getORB(), null, request_listener.getRequest() ); //is the body correct? assertEquals( "barbaz", r_in.read_string() ); r_out.close(); r_in.close(); m_out.close(); } @Test public void testGIOP_1_0_CorrectRefusing() { List<byte[]> messages = new Vector<byte[]>(); RequestOutputStream r_out = new RequestOutputStream( getORB(), //ClientConnection null, //request id 0, //operation "foo", //response expected true, //SYNC_SCOPE (irrelevant) (short)-1, //request start time null, //request end time null, //reply end time null, //object key new byte[1], 0 // giop minor ); r_out.write_string( "bar" ); r_out.insertMsgSize(); byte[] b = r_out.getBufferCopy(); b[6] |= 0x02; //set "more fragments follow" messages.add( b ); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } GIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //instead, an error message have must been sent via the //transport assertTrue( transport.getWrittenMessage() != null ); byte[] result = transport.getWrittenMessage(); assertTrue( Messages.getMsgType( result ) == MsgType_1_1._MessageError ); MessageOutputStream m_out = new MessageOutputStream(orb); m_out.writeGIOPMsgHeader( MsgType_1_1._Fragment, 0 // giop minor ); m_out.write_ulong( 0 ); // Fragment Header (request id) m_out.write_octet( (byte) 'b' ); m_out.write_octet( (byte) 'a' ); m_out.write_octet( (byte) 'z' ); m_out.insertMsgSize(); messages.add( m_out.getBufferCopy() ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //instead, an error message have must been sent via the //transport assertTrue( transport.getWrittenMessage() != null ); //must be a new one assertTrue( transport.getWrittenMessage() != result ); result = transport.getWrittenMessage(); assertTrue( Messages.getMsgType( result ) == MsgType_1_1._MessageError ); r_out.close(); m_out.close(); } @Test public void testGIOP_1_1_IllegalMessageType() { List<byte[]> messages = new Vector<byte[]>(); LocateRequestOutputStream r_out = new LocateRequestOutputStream( getORB(), new byte[1], //object key 0, //request id 1 // giop minor ); r_out.insertMsgSize(); byte[] b = r_out.getBufferCopy(); b[6] |= 0x02; //set "more fragments follow" messages.add( b ); // MessageOutputStream m_out = // new MessageOutputStream(); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } GIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //instead, an error message have must been sent via the //transport assertTrue( transport.getWrittenMessage() != null ); byte[] result = transport.getWrittenMessage(); assertTrue( Messages.getMsgType( result ) == MsgType_1_1._MessageError ); r_out.close(); } @Test public void testGIOP_1_1_NoImplement() { List<byte[]> messages = new Vector<byte[]>(); RequestOutputStream r_out = new RequestOutputStream( getORB(), //ClientConnection null, //request id 0, //operation "foo", //response expected true, //SYNC_SCOPE (irrelevant) (short)-1, //request start time null, //request end time null, //reply end time null, //object key new byte[1], 1 // giop minor ); r_out.write_string( "bar" ); r_out.insertMsgSize(); byte[] b = r_out.getBufferCopy(); b[6] |= 0x02; //set "more fragments follow" messages.add( b ); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } GIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //instead, an error message have must been sent via the //transport assertTrue( transport.getWrittenMessage() != null ); byte[] result = transport.getWrittenMessage(); ReplyInputStream r_in = new ReplyInputStream( getORB(), result ); Exception ex = r_in.getException(); if ( ex != null && ex.getClass() == org.omg.CORBA.NO_IMPLEMENT.class ) { // o.k. } else { fail(); } MessageOutputStream m_out = new MessageOutputStream(orb); m_out.writeGIOPMsgHeader( MsgType_1_1._Fragment, 1 // giop minor ); m_out.write_ulong( 0 ); // Fragment Header (request id) m_out.write_octet( (byte) 'b' ); m_out.write_octet( (byte) 'a' ); m_out.write_octet( (byte) 'z' ); m_out.insertMsgSize(); messages.add( m_out.getBufferCopy() ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //can't check more, message is discarded m_out.close(); r_out.close(); r_in.close(); } @Test public void testGIOP_1_2_CorrectCloseOnGarbage() { List<byte[]> messages = new Vector<byte[]>(); String garbage = "This is a garbage message"; byte[] b = garbage.getBytes(); messages.add( b ); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } GIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //no request or reply must have been handed over assertTrue( request_listener.getRequest() == null ); assertTrue( reply_listener.getReply() == null ); //instead, connection should be closed assertTrue( transport.hasBeenClosed() ); //no message is written (makes no real sense) assertTrue( transport.getWrittenMessage() != null ); assertTrue( transport.getWrittenMessage().length == 0 ); } @Test public void testGIOP_1_1_CorrectRequest() { List<byte[]> messages = new Vector<byte[]>(); RequestOutputStream r_out = new RequestOutputStream( getORB(), //ClientConnection (ClientConnection) null, //request id 0, //operation "foo", // response expected true, // SYNC_SCOPE (irrelevant) (short)-1, //request start time null, //request end time null, //reply start time null, //object key new byte[1], 1 // giop minor ); String message = "Request"; r_out.write_string(message); r_out.insertMsgSize(); messages.add( r_out.getBufferCopy() ); DummyTransport transport = new DummyTransport( messages ); DummyRequestListener request_listener = new DummyRequestListener(); DummyReplyListener reply_listener = new DummyReplyListener(); GIOPConnectionManager giopconn_mg = new GIOPConnectionManager(); try { giopconn_mg.configure (config); } catch (Exception e) { } ServerGIOPConnection conn = giopconn_mg.createServerGIOPConnection( null, transport, request_listener, reply_listener ); try { //will not return until an IOException is thrown (by the //DummyTransport) conn.receiveMessages(); } catch( IOException e ) { //o.k., thrown by DummyTransport } //did the GIOPConnection hand the complete request over to the //listener? assertTrue( request_listener.getRequest() != null ); RequestInputStream r_in = new RequestInputStream( getORB(), null, request_listener.getRequest() ); //is the body correct? assertEquals( message, r_in.read_string() ); r_out.close(); r_in.close(); } }// GIOPConnectionTest