001package ca.uhn.hl7v2.hoh.raw.client;
002
003import static org.junit.Assert.assertEquals;
004import static org.junit.Assert.assertTrue;
005
006import java.net.MalformedURLException;
007import java.net.URL;
008
009import org.apache.log4j.Level;
010import org.apache.log4j.LogManager;
011import org.junit.After;
012import org.junit.Before;
013import org.junit.Test;
014
015import ca.uhn.hl7v2.hoh.api.IReceivable;
016import ca.uhn.hl7v2.hoh.auth.SingleCredentialClientCallback;
017import ca.uhn.hl7v2.hoh.auth.SingleCredentialServerCallback;
018import ca.uhn.hl7v2.hoh.encoder.EncodingStyle;
019import ca.uhn.hl7v2.hoh.llp.Hl7OverHttpLowerLayerProtocol;
020import ca.uhn.hl7v2.hoh.llp.ServerSocketThreadForTesting;
021import ca.uhn.hl7v2.hoh.raw.api.RawSendable;
022import ca.uhn.hl7v2.hoh.util.RandomServerPortProvider;
023import ca.uhn.hl7v2.hoh.util.ServerRoleEnum;
024import ca.uhn.hl7v2.parser.DefaultXMLParser;
025import ca.uhn.hl7v2.parser.PipeParser;
026
027public class HohRawClientSimpleTest {
028        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HohRawClientSimpleTest.class);
029        private static int myPort;
030        private static Hl7OverHttpLowerLayerProtocol myLlp;
031        private static SingleCredentialServerCallback ourServerCallback;
032        private static ServerSocketThreadForTesting myServerSocketThread;
033        private Level myExistingLogLevel;
034
035
036        @Test
037        public void testSendMessageSimple() throws Exception {
038                LogManager.getRootLogger().setLevel((Level)Level.TRACE);
039
040                String message = // -
041                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
042                                "EVN||200803051509\r" + // -
043                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
044
045                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
046                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
047                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
048
049                ourLog.info("Received response");
050
051                assertEquals(message, myServerSocketThread.getMessage());
052                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
053
054                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
055                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
056
057        }
058
059        
060        @Test
061        public void testSendMessageAndRespectCloseHeaderInResponse() throws Exception {
062
063                String message = // -
064                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
065                                "EVN||200803051509\r" + // -
066                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
067
068                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
069                
070                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
071
072                myServerSocketThread.setCloseNormallyWithHeaderAfterEachMessage();
073                
074                /*
075                 * Send one message
076                 */
077                ourLog.info("*** Send message #1");
078                
079                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
080                assertEquals(message, myServerSocketThread.getMessage());
081                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
082
083                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
084                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
085                assertEquals(1, myServerSocketThread.getConnectionCount());
086                
087                
088                /*
089                 * Send a second message
090                 */
091                ourLog.info("*** Send message #2");
092                
093                response = client.sendAndReceive(new RawSendable(message));
094                assertEquals(message, myServerSocketThread.getMessage());
095                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
096
097                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
098                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
099                assertEquals(2, myServerSocketThread.getConnectionCount());
100
101                Thread.sleep(1000);
102                
103                /*
104                 * Send a third message
105                 */
106                ourLog.info("*** Send message #3");
107                
108                response = client.sendAndReceive(new RawSendable(message));
109                assertEquals(message, myServerSocketThread.getMessage());
110                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
111
112                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
113                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
114                assertEquals(3, myServerSocketThread.getConnectionCount());
115
116        }
117
118        @Test
119        public void testUnderstandsGzippedResponse() throws Exception {
120                LogManager.getRootLogger().setLevel((Level)Level.TRACE);
121
122                myServerSocketThread.setGZipResponse(true);
123                
124                String message = // -
125                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
126                                "EVN||200803051509\r" + // -
127                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
128
129                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
130                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
131                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
132
133                ourLog.info("Received response");
134
135                assertEquals(message, myServerSocketThread.getMessage());
136                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
137
138                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
139                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
140
141        }
142
143        
144        @Test(expected = IllegalArgumentException.class)
145        public void testInvalidUriRejected1() throws Exception {
146                new HohRawClientSimple("localhost", 9999, "/uri space");
147        }
148
149        @Test(expected = IllegalArgumentException.class)
150        public void testInvalidUriRejected2() throws Exception {
151                new HohRawClientSimple("localhost", 9999, "uri_with_no_starting_slash");
152        }
153
154        @Test(expected = IllegalArgumentException.class)
155        public void testInvalidUriRejected3() throws Exception {
156                new HohRawClientSimple("localhost", 9999, "/uri_with_%_bad_char");
157        }
158
159        // TODO: add test with chunked encoding and additional trailing headers
160
161        /**
162         * Ensure that if chunked transfer encoding is used, and there is a pause in
163         * the middle of transmission, the whole message is still read
164         */
165        @Test
166        public void testSendMessageWithChunkedResponseAndPauseInMiddle() throws Exception {
167
168                myServerSocketThread.setSimulateOneSecondPauseInChunkedEncoding(true);
169
170                String message = // -
171                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
172                                "EVN||200803051509\r" + // -
173                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
174
175                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
176                client.setSoTimeout(500);
177                client.setResponseTimeout(2000);
178                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
179                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
180
181                ourLog.info("Received response");
182
183                assertEquals(message, myServerSocketThread.getMessage());
184                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
185
186                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
187                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
188
189        }
190
191        /**
192         * Ensure that if chunked transfer encoding is used, and there is a pause in
193         * the middle of transmission, the whole message is still read
194         */
195        @Test
196        public void testSendMessageWithChunkedResponseAndPauseInMiddleWithLongSoTimeout() throws Exception {
197
198                myServerSocketThread.setSimulateOneSecondPauseInChunkedEncoding(true);
199
200                String message = // -
201                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
202                                "EVN||200803051509|||||||||||||||||||||||||||||||||||||||||\r" + // -
203                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
204
205                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
206                client.setSoTimeout(980);
207                client.setKeepAlive(false);
208                client.setResponseTimeout(2000);
209                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
210                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
211
212                ourLog.info("Received response");
213
214                assertEquals(message, myServerSocketThread.getMessage());
215                assertEquals(myServerSocketThread.getReply().encode(), response.getMessage());
216
217                assertEquals(EncodingStyle.ER7.getContentType(), myServerSocketThread.getContentType());
218                assertEquals(EncodingStyle.ER7, myServerSocketThread.getEncoding());
219
220        }
221
222        @Test
223        public void testSendMessageSimpleXml() throws Exception {
224
225                String message = // -
226                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
227                                "EVN||200803051509\r" + // -
228                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
229                message = new DefaultXMLParser().encode(PipeParser.getInstanceWithNoValidation().parse(message));
230
231                HohRawClientSimple client = new HohRawClientSimple("localhost", myPort, "/theUri");
232                client.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
233                IReceivable<String> response = client.sendAndReceive(new RawSendable(message));
234
235                ourLog.info("Received response");
236
237                assertEquals(message, myServerSocketThread.getMessage());
238                String responseMessage = response.getMessage();
239                assertTrue(responseMessage, responseMessage.contains("<MSH>"));
240                assertEquals(myServerSocketThread.getReply().encode(), responseMessage);
241
242                assertEquals(EncodingStyle.XML.getContentType(), myServerSocketThread.getContentType());
243                assertEquals(EncodingStyle.XML, myServerSocketThread.getEncoding());
244        }
245
246        @Test
247        public void testCreateUsingUrl() throws MalformedURLException {
248
249                HohRawClientSimple c = new HohRawClientSimple(new URL("http://somehost/"));
250                assertEquals("somehost", c.getHost());
251                assertEquals("/", c.getUriPath());
252                assertEquals(80, c.getPort());
253
254                c = new HohRawClientSimple(new URL("http://somehost:8888/"));
255                assertEquals("somehost", c.getHost());
256                assertEquals("/", c.getUriPath());
257                assertEquals(8888, c.getPort());
258
259                c = new HohRawClientSimple(new URL("http://somehost:8888/someuri/path/test.jsp"));
260                assertEquals("somehost", c.getHost());
261                assertEquals("/someuri/path/test.jsp", c.getUriPath());
262                assertEquals(8888, c.getPort());
263
264                c = new HohRawClientSimple(new URL("https://somehost/someuri/path/test.jsp"));
265                assertEquals("somehost", c.getHost());
266                assertEquals("/someuri/path/test.jsp", c.getUriPath());
267                assertEquals(443, c.getPort());
268
269        }
270
271        @After
272        public void after() throws InterruptedException {
273                ourLog.info("Marking done as true");
274                myServerSocketThread.done();
275                
276                // Restore the log level
277                LogManager.getRootLogger().setLevel(myExistingLogLevel);
278        }
279
280        @Before
281        public void before() throws InterruptedException {
282                myExistingLogLevel = LogManager.getRootLogger().getLevel();
283
284                myPort = RandomServerPortProvider.findFreePort();
285
286                myLlp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
287                myLlp.setAuthorizationCallback(new SingleCredentialClientCallback("hello", "hapiworld"));
288                ourServerCallback = new SingleCredentialServerCallback("hello", "hapiworld");
289
290                myServerSocketThread = new ServerSocketThreadForTesting(myPort, ourServerCallback);
291                myServerSocketThread.start();
292                myServerSocketThread.getLatch().await();
293        }
294        
295        
296
297
298}