001package ca.uhn.hl7v2.hoh.relay.sender;
002
003import static org.junit.Assert.assertEquals;
004
005import java.io.IOException;
006import java.util.concurrent.TimeUnit;
007
008import org.junit.After;
009import org.junit.Assert;
010import org.junit.Before;
011import org.junit.Test;
012
013import ca.uhn.hl7v2.DefaultHapiContext;
014import ca.uhn.hl7v2.HL7Exception;
015import ca.uhn.hl7v2.app.Connection;
016import ca.uhn.hl7v2.app.ConnectionHub;
017import ca.uhn.hl7v2.hoh.api.DecodeException;
018import ca.uhn.hl7v2.hoh.api.EncodeException;
019import ca.uhn.hl7v2.hoh.auth.SingleCredentialServerCallback;
020import ca.uhn.hl7v2.hoh.llp.ServerSocketThreadForTesting;
021import ca.uhn.hl7v2.hoh.relay.Launcher;
022import ca.uhn.hl7v2.hoh.sockets.CustomCertificateTlsSocketFactory;
023import ca.uhn.hl7v2.hoh.sockets.CustomCertificateTlsSocketFactoryTest;
024import ca.uhn.hl7v2.hoh.util.Holder;
025import ca.uhn.hl7v2.hoh.util.RandomServerPortProvider;
026import ca.uhn.hl7v2.llp.LLPException;
027import ca.uhn.hl7v2.model.Message;
028import ca.uhn.hl7v2.model.v25.message.ACK;
029import ca.uhn.hl7v2.model.v25.message.ADT_A01;
030
031public class HttpSenderTest {
032
033        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HttpSenderTest.class);
034        private int myOutPort;
035        private ServerSocketThreadForTesting myServerSocketThread;
036        private SingleCredentialServerCallback ourServerCallback;
037        private int myInPort;
038        private int myInPort2;
039
040        @After
041        public void after() throws InterruptedException {
042                ourLog.info("Marking done as true");
043                myServerSocketThread.done();
044        }
045
046        @Before
047        public void before() throws InterruptedException {
048                // System.setProperty("javax.net.debug", "ssl");
049
050                myOutPort = RandomServerPortProvider.findFreePort();
051                myInPort = RandomServerPortProvider.findFreePort();
052                myInPort2 = RandomServerPortProvider.findFreePort();
053                System.setProperty("relay.port.out", Integer.toString(myOutPort));
054                System.setProperty("relay.port.in", Integer.toString(myInPort));
055                System.setProperty("relay.port.in.2", Integer.toString(myInPort2));
056
057                ourServerCallback = new SingleCredentialServerCallback("hello", "hapiworld");
058
059                myServerSocketThread = new ServerSocketThreadForTesting(myOutPort, ourServerCallback);
060        }
061
062        @SuppressWarnings("resource")
063        @Test
064        public void testSenderWithTls() throws HL7Exception, IOException, LLPException, InterruptedException, DecodeException, EncodeException {
065
066                CustomCertificateTlsSocketFactory serverSocketFactory = CustomCertificateTlsSocketFactoryTest.createTrustedServerSocketFactory();
067                myServerSocketThread.setServerSockewtFactory(serverSocketFactory);
068                myServerSocketThread.start();
069                myServerSocketThread.getLatch().await();
070
071                ADT_A01 adt = new ADT_A01();
072                adt.initQuickstart("ADT", "A01", "T");
073
074                Launcher l = new Launcher("src/test/resources/relay/MllpToHttpTlsMutualAuth.xml");
075
076                ConnectionHub hub = new DefaultHapiContext().getConnectionHub();
077                try {
078
079                        Connection c = hub.attach("localhost", myInPort, false);
080                        c.getInitiator().setTimeout(10000000, TimeUnit.MILLISECONDS);
081                        Message response = c.getInitiator().sendAndReceive(adt);
082
083                        ourLog.info("Response was:\n{}", response.encode().replace('\r', '\n'));
084
085                } finally {
086                        l.shutdown();
087                }
088        }
089
090        
091
092        @SuppressWarnings("resource")
093        @Test
094        public void testErrorMessageReferencesRelay() throws HL7Exception, IOException, LLPException, InterruptedException, DecodeException, EncodeException {
095
096                ADT_A01 adt = new ADT_A01();
097                adt.initQuickstart("ADT", "A01", "T");
098
099                Launcher l = new Launcher("src/test/resources/relay/MllpToHttp.xml");
100
101                ConnectionHub hub = new DefaultHapiContext().getConnectionHub();
102                try {
103
104                        Connection c = hub.attach("localhost", myInPort, false);
105                        c.getInitiator().setTimeout(10000000, TimeUnit.MILLISECONDS);
106                        Message response = c.getInitiator().sendAndReceive(adt);
107
108                        ourLog.info("Response was:\n{}", response.encode().replace('\r', '\n'));
109
110                        Assert.assertTrue(response.encode().contains("HAPI HL7 over HTTP Relay"));
111                        
112                } finally {
113                        l.shutdown();
114                }
115        }
116        
117        
118        @Test
119        public void testSetUrl() throws Exception {
120
121                RelayHttpSender s = new RelayHttpSender();
122                s.setUrlString("http://localhost:8888/path");
123
124                assertEquals("localhost", s.getHost());
125                assertEquals(8888, s.getPort());
126                assertEquals("/path", s.getUriPath());
127
128                s.afterPropertiesSet();
129
130        }
131
132        @Test
133        public void setMultipleConcurrentSenders() throws Throwable {
134                Launcher l = new Launcher("src/test/resources/relay/MllpToHttpMultipleListeners.xml");
135                try {
136
137                        myServerSocketThread.setResponseDelays(500L, 0L);
138                        myServerSocketThread.start();
139                        myServerSocketThread.getLatch().await();
140
141                        final ADT_A01 msg1 = new ADT_A01();
142                        msg1.initQuickstart("ADT", "A01", "T");
143
144                        final ADT_A01 msg2 = new ADT_A01();
145                        msg2.initQuickstart("ADT", "A01", "T");
146
147                        final Holder<ACK> resp1Holder = new Holder<ACK>();
148                        final Holder<ACK> resp2Holder = new Holder<ACK>();
149                        final Holder<Throwable> failHolder = new Holder<Throwable>();
150
151                        Thread t1 = new Thread() {
152                                @Override
153                                public void run() {
154                                        try {
155                                                Connection client1 = new DefaultHapiContext().newClient("localhost", myInPort, false);
156                                                resp1Holder.myValue = (ACK) client1.getInitiator().sendAndReceive(msg1);
157                                        } catch (Throwable e) {
158                                                failHolder.myValue = e;
159                                        }
160                                }
161                        };
162                        t1.start();
163
164                        Thread.sleep(100);
165                        
166                        Thread t2 = new Thread() {
167                                @Override
168                                public void run() {
169                                        try {
170                                                Connection client2 = new DefaultHapiContext().newClient("localhost", myInPort, false);
171                                                resp2Holder.myValue = (ACK) client2.getInitiator().sendAndReceive(msg2);
172                                        } catch (Throwable e) {
173                                                failHolder.myValue = e;
174                                        }
175                                }
176                        };
177                        t2.start();
178
179                        t1.join();
180                        t2.join();
181                        
182                        if (failHolder.myValue!=null) {
183                                throw failHolder.myValue;
184                        }
185                        
186                        ACK resp1 = resp1Holder.myValue;
187                        ACK resp2 = resp2Holder.myValue;
188                        assertEquals(msg1.getMSH().getMsh10_MessageControlID().getValue(), resp1.getMSA().getMsa2_MessageControlID().getValue());
189                        assertEquals(msg2.getMSH().getMsh10_MessageControlID().getValue(), resp2.getMSA().getMsa2_MessageControlID().getValue());
190
191                } finally {
192                        l.shutdown();
193                }
194        }
195
196}