blob: 578cb0309f264d9d6ad19611a57262449fa46f32 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.mllp.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import org.apache.camel.test.util.PayloadBuilder;
import static org.apache.camel.component.mllp.MllpEndpoint.END_OF_BLOCK;
import static org.apache.camel.component.mllp.MllpEndpoint.END_OF_DATA;
import static org.apache.camel.component.mllp.MllpEndpoint.START_OF_BLOCK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public abstract class MllpSocketReaderTestSupport {
static final String TEST_MESSAGE =
"MSH|^~\\&|REQUESTING|ICE|INHOUSE|RTH00|20161206193919||ORM^O01|00001|D|2.3|||||||" + '\r'
+ "PID|1||ICE999999^^^ICE^ICE||Testpatient^Testy^^^Mr||19740401|M|||123 Barrel Drive^^^^SW18 4RT|||||2||||||||||||||" + '\r'
+ "NTE|1||Free text for entering clinical details|" + '\r'
+ "PV1|1||^^^^^^^^Admin Location|||||||||||||||NHS|" + '\r'
+ "ORC|NW|213||175|REQ||||20080808093202|ahsl^^Administrator||G999999^TestDoctor^GPtests^^^^^^NAT|^^^^^^^^Admin Location | 819600|200808080932||RTH00||ahsl^^Administrator||" + '\r'
+ "OBR|1|213||CCOR^Serum Cortisol ^ JRH06|||200808080932||0.100||||||^|G999999^TestDoctor^GPtests^^^^^^NAT|819600|ADM162||||||820|||^^^^^R||||||||" + '\r'
+ "OBR|2|213||GCU^Serum Copper ^ JRH06 |||200808080932||0.100||||||^|G999999^TestDoctor^GPtests^^^^^^NAT|819600|ADM162||||||820|||^^^^^R||||||||" + '\r'
+ "OBR|3|213||THYG^Serum Thyroglobulin ^JRH06|||200808080932||0.100||||||^|G999999^TestDoctor^GPtests^^^^^^NAT|819600|ADM162||||||820|||^^^^^R||||||||" + '\r'
+ '\n';
static final String TEST_ACKNOWLEDGEMENT =
"MSH|^~\\&|INHOUSE|RTH00|REQUESTING|ICE|20161206193919||ACK^O01|00001|D|2.3|||||||" + '\r'
+ "MSA|AA|00001|" + '\r'
+ '\n';
static final byte[] EXCEPTION_PACKET = null;
static final byte[] EMPTY_PACKET = new byte[0];
static final byte[] START_PACKET = PayloadBuilder.build(START_OF_BLOCK);
static final byte[] END_PACKET = PayloadBuilder.build(END_OF_BLOCK, END_OF_DATA);
FakeSocket fakeSocket = new FakeSocket();
void assertSocketOpen() throws Exception {
assertTrue("socket should have been connected", fakeSocket.connected);
assertFalse("shutdownInput() should not have been called", fakeSocket.inputShutdown);
assertFalse("shutdownOutput() should not have been called", fakeSocket.outputShutdown);
assertFalse("close() should not have been called", fakeSocket.closed);
assertNotNull("socket should have an input stream", fakeSocket.fakeSocketInputStream);
}
void assertSocketClosed() throws Exception {
assertTrue("socket should have been connected", fakeSocket.connected);
assertTrue("shutdownInput() should have been called", fakeSocket.inputShutdown);
assertTrue("shutdownOutput() should have been called", fakeSocket.outputShutdown);
assertTrue("close() should have been called", fakeSocket.closed);
assertFalse("SO_LINGER should not be enabled", fakeSocket.linger);
}
void assertSocketReset() throws Exception {
assertTrue("socket should have been connected", fakeSocket.connected);
assertTrue("close() should have been called", fakeSocket.closed);
assertTrue("SO_LINGER should be enabled", fakeSocket.linger);
assertEquals("SO_LINGER timeout should be 0", 0, fakeSocket.lingerTimeout);
}
<E extends Exception> void expectedExceptionFailure(Class<E> expected) throws Exception {
fail("Expected exception " + expected.getName() + " was not thrown");
}
class FakeSocket extends Socket {
boolean connected = true;
boolean inputShutdown;
boolean outputShutdown;
boolean closed;
int receiveBufferSize = 1024;
int sendBufferSize = 1024;
int timeout = 1000;
boolean linger;
int lingerTimeout = 1024;
FakeSocketInputStream fakeSocketInputStream = new FakeSocketInputStream();
FakeSocket() {
}
@Override
public boolean isConnected() {
return connected;
}
@Override
public boolean isInputShutdown() {
return inputShutdown;
}
@Override
public boolean isOutputShutdown() {
return outputShutdown;
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public void shutdownInput() throws IOException {
inputShutdown = true;
}
@Override
public void shutdownOutput() throws IOException {
outputShutdown = true;
}
@Override
public synchronized void close() throws IOException {
closed = true;
}
@Override
public int getSoLinger() throws SocketException {
if (linger) {
return lingerTimeout;
}
return -1;
}
@Override
public void setSoLinger(boolean on, int linger) throws SocketException {
this.linger = on;
this.lingerTimeout = linger;
}
@Override
public synchronized int getReceiveBufferSize() throws SocketException {
return receiveBufferSize;
}
@Override
public synchronized void setReceiveBufferSize(int size) throws SocketException {
this.receiveBufferSize = size;
}
@Override
public synchronized int getSendBufferSize() throws SocketException {
return sendBufferSize;
}
@Override
public synchronized void setSendBufferSize(int size) throws SocketException {
this.sendBufferSize = size;
}
@Override
public synchronized int getSoTimeout() throws SocketException {
return timeout;
}
@Override
public synchronized void setSoTimeout(int timeout) throws SocketException {
this.timeout = timeout;
}
@Override
public InputStream getInputStream() throws IOException {
if (fakeSocketInputStream == null) {
throw new IOException("Faking getInputStream failure");
}
return fakeSocketInputStream;
}
}
class FakeSocketInputStream extends InputStream {
boolean useSocketExceptionOnNullPacket = true;
private Queue<ByteArrayInputStream> packetQueue = new LinkedList<>();
FakeSocketInputStream() {
}
@Override
public int read() throws IOException {
if (packetQueue.size() > 0) {
if (packetQueue.peek() == null) {
if (useSocketExceptionOnNullPacket) {
throw new SocketException("Faking Socket read() failure - simulating reset");
} else {
throw new IOException("Faking Socket read() failure");
}
}
int answer = packetQueue.element().read();
if (answer == -1 || packetQueue.element().available() == 0) {
packetQueue.remove();
}
return answer;
}
throw new SocketTimeoutException("Faking Socket read() Timeout");
}
@Override
public int read(byte[] buffer) throws IOException {
if (packetQueue.size() > 0) {
if (packetQueue.peek() == null) {
if (useSocketExceptionOnNullPacket) {
throw new SocketException("Faking Socket read(byte[]) failure - simulating reset");
} else {
throw new IOException("Faking Socket read(byte[]) failure");
}
}
int answer = packetQueue.element().read(buffer);
if (answer == -1 || packetQueue.element().available() == 0) {
packetQueue.remove();
}
return answer;
}
throw new SocketTimeoutException("Faking Socket read(byte[]) Timeout");
}
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
if (packetQueue.size() > 0) {
if (packetQueue.peek() == null) {
if (useSocketExceptionOnNullPacket) {
throw new SocketException("Faking Socket read(byte[], int, int) failure - simulating reset");
} else {
throw new IOException("Faking Socket read(byte[], int, int) failure");
}
}
int answer = packetQueue.element().read(buffer, offset, length);
if (answer == -1 || packetQueue.element().available() == 0) {
packetQueue.remove();
}
return answer;
}
throw new SocketTimeoutException("Faking Socket read(byte[], int, int) Timeout");
}
@Override
public int available() throws IOException {
if (packetQueue.size() > 0) {
return packetQueue.element().available();
}
return 0;
}
public FakeSocketInputStream addPacket(char... packet) {
this.packetQueue.add(new ByteArrayInputStream(PayloadBuilder.build(packet)));
return this;
}
public FakeSocketInputStream addPacket(byte[] bytes) throws IOException {
if (bytes != null) {
this.packetQueue.add(new ByteArrayInputStream(bytes));
} else {
this.packetQueue.add(null);
}
return this;
}
public FakeSocketInputStream addPacket(byte[] bytes, byte[]... byteArrays) throws IOException {
PayloadBuilder builder = new PayloadBuilder(bytes);
for (byte[] additionalBytes : byteArrays) {
builder.append(additionalBytes);
}
this.packetQueue.add(new ByteArrayInputStream(builder.build()));
return this;
}
public FakeSocketInputStream addPacket(String... strings) throws IOException {
this.packetQueue.add(new ByteArrayInputStream(PayloadBuilder.build(strings)));
return this;
}
public FakeSocketInputStream addPackets(String message, char delimiter) throws IOException {
StringTokenizer tokenizer = new StringTokenizer(message, String.valueOf(delimiter), true);
while (tokenizer.hasMoreTokens()) {
addPacket(tokenizer.nextToken());
}
return this;
}
public FakeSocketInputStream addPackets(char... packets) {
for (char c : packets) {
addPacket(c);
}
return this;
}
public FakeSocketInputStream addPackets(byte[]... packets) throws IOException {
for (byte[] packet : packets) {
addPacket(packet);
}
return this;
}
public FakeSocketInputStream addPackets(byte[] bytes, String s) throws IOException {
return addPacket(bytes).addPacket(s);
}
}
}