/*
* Copyright 2014 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed 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 li.strolch.communication;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import li.strolch.communication.CommandKey;
import li.strolch.communication.CommunicationConnection;
import li.strolch.communication.CommunicationEndpoint;
import li.strolch.communication.ConnectionMode;
import li.strolch.communication.IoMessage;
import li.strolch.communication.tcpip.ClientSocketEndpoint;
import li.strolch.communication.tcpip.ServerSocketEndpoint;
import li.strolch.communication.tcpip.SocketEndpointConstants;
import li.strolch.communication.tcpip.SocketMessageVisitor;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class SocketEndpointTest extends AbstractEndpointTest {
private static final String PORT = "45678"; //$NON-NLS-1$
private static final String HOST = "localhost"; //$NON-NLS-1$
private static final String CLIENT_CONNECTION_ID = "ClientSocket"; //$NON-NLS-1$
private static final String SERVER_CONNECTION_ID = "ServerSocket"; //$NON-NLS-1$
private CommunicationConnection clientConnection;
private CommunicationConnection serverConnection;
@Before
public void before() {
{
Map<String, String> parameters = new HashMap<>();
parameters.put(SocketEndpointConstants.PARAMETER_REMOTE_INPUT_ADDRESS, HOST);
parameters.put(SocketEndpointConstants.PARAMETER_REMOTE_INPUT_PORT, PORT);
// we close after send, so that the server can read whole lines, as that is what we are sending
parameters.put(SocketEndpointConstants.PARAMETER_CLOSE_AFTER_SEND, Boolean.TRUE.toString());
CommunicationEndpoint endpoint = new ClientSocketEndpoint();
SocketMessageVisitor messageVisitor = new SocketMessageVisitorExtension(CLIENT_CONNECTION_ID);
this.clientConnection = new CommunicationConnection(CLIENT_CONNECTION_ID, ConnectionMode.ON, parameters,
endpoint, messageVisitor);
this.clientConnection.configure();
}
{
Map<String, String> parameters = new HashMap<>();
parameters.put(SocketEndpointConstants.PARAMETER_LOCAL_INPUT_ADDRESS, HOST);
parameters.put(SocketEndpointConstants.PARAMETER_LOCAL_INPUT_PORT, PORT);
CommunicationEndpoint endpoint = new ServerSocketEndpoint();
SocketMessageVisitor messageVisitor = new SocketMessageVisitorExtension(SERVER_CONNECTION_ID);
this.serverConnection = new CommunicationConnection(SERVER_CONNECTION_ID, ConnectionMode.ON, parameters,
endpoint, messageVisitor);
this.serverConnection.configure();
}
}
@After
public void after() {
if (this.clientConnection != null)
this.clientConnection.stop();
if (this.serverConnection != null)
this.serverConnection.stop();
}
@Test
public void testSocketEndpoints() throws Exception {
this.serverConnection.start();
Thread.sleep(100);
this.clientConnection.start();
TestConnectionObserver serverObserver = new TestConnectionObserver();
CommandKey inboundKey = CommandKey.key(SERVER_CONNECTION_ID, "lines"); //$NON-NLS-1$
this.serverConnection.addConnectionObserver(inboundKey, serverObserver);
TestConnectionObserver clientObserver = new TestConnectionObserver();
CommandKey outboundKey = CommandKey.key(CLIENT_CONNECTION_ID, "lines"); //$NON-NLS-1$
this.clientConnection.addConnectionObserver(outboundKey, clientObserver);
TestIoMessage outboundMsg = createTestMessage(outboundKey, CLIENT_CONNECTION_ID);
this.clientConnection.send(outboundMsg);
waitForMessage(clientObserver);
assertEquals(outboundMsg.getKey(), clientObserver.getMessage().getKey());
waitForMessage(serverObserver);
assertEquals(inboundKey, serverObserver.getMessage().getKey());
assertEquals(outboundMsg.getContents(), ((TestIoMessage) serverObserver.getMessage()).getContents());
}
private final class SocketMessageVisitorExtension extends SocketMessageVisitor {
public SocketMessageVisitorExtension(String connectionId) {
super(connectionId);
}
@Override
public void visit(DataInputStream inputStream, DataOutputStream outputStream, IoMessage message)
throws Exception {
TestIoMessage msg = (TestIoMessage) message;
logger.info(MessageFormat
.format("Writing {0} lines for message {1}", msg.getContents().size(), msg.getId())); //$NON-NLS-1$
for (String line : msg.getContents()) {
outputStream.writeBytes(line);
outputStream.write('\n');
}
outputStream.flush();
}
@Override
public IoMessage visit(DataInputStream inputStream, DataOutputStream outputStream) throws Exception {
List<String> lines = new ArrayList<>();
// since we are reading whole lines, we must close the stream when we read null i.e. EOF
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
logger.info("Reading from stream..."); //$NON-NLS-1$
while ((line = reader.readLine()) != null) {
lines.add(line);
}
}
logger.info(MessageFormat.format("Read {0} lines from stream.", lines.size())); //$NON-NLS-1$
return new TestIoMessage(UUID.randomUUID().toString(),
CommandKey.key(SERVER_CONNECTION_ID, "lines"), SERVER_CONNECTION_ID, lines); //$NON-NLS-1$
}
}
}