GH-3256: Support Testing TCP Connections
Resolves https://github.com/spring-projects/spring-integration/issues/3256
This commit is contained in:
committed by
Artem Bilan
parent
02407f7dff
commit
1d4626f54c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.ip.tcp.connection;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.contains;
|
||||
@@ -30,29 +31,36 @@ import static org.mockito.Mockito.when;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.ip.config.TcpConnectionFactoryFactoryBean;
|
||||
import org.springframework.integration.ip.event.IpIntegrationEvent;
|
||||
import org.springframework.integration.ip.tcp.TcpOutboundGateway;
|
||||
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
|
||||
import org.springframework.integration.test.rule.Log4j2LevelAdjuster;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.ErrorMessage;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
@@ -65,9 +73,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
*/
|
||||
public class ConnectionFactoryTests {
|
||||
|
||||
@Rule
|
||||
public Log4j2LevelAdjuster adjuster = Log4j2LevelAdjuster.trace();
|
||||
|
||||
@Test
|
||||
public void factoryBeanTests() {
|
||||
TcpConnectionFactoryFactoryBean fb = new TcpConnectionFactoryFactoryBean("client");
|
||||
@@ -98,23 +103,13 @@ public class ConnectionFactoryTests {
|
||||
: 5; // Listening, + OPEN, CLOSE (but we *might* get exceptions, depending on timing).
|
||||
final CountDownLatch serverListeningLatch = new CountDownLatch(1);
|
||||
final CountDownLatch eventLatch = new CountDownLatch(expectedEvents);
|
||||
ApplicationEventPublisher publisher = new ApplicationEventPublisher() {
|
||||
|
||||
@Override
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
LogFactory.getLog(this.getClass()).trace("Received: " + event);
|
||||
events.add((IpIntegrationEvent) event);
|
||||
if (event instanceof TcpConnectionServerListeningEvent) {
|
||||
serverListeningLatch.countDown();
|
||||
}
|
||||
eventLatch.countDown();
|
||||
ApplicationEventPublisher publisher = event -> {
|
||||
LogFactory.getLog(this.getClass()).trace("Received: " + event);
|
||||
events.add((IpIntegrationEvent) event);
|
||||
if (event instanceof TcpConnectionServerListeningEvent) {
|
||||
serverListeningLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishEvent(Object event) {
|
||||
|
||||
}
|
||||
|
||||
eventLatch.countDown();
|
||||
};
|
||||
serverFactory.setBeanName("serverFactory");
|
||||
serverFactory.setApplicationEventPublisher(publisher);
|
||||
@@ -247,6 +242,101 @@ public class ConnectionFactoryTests {
|
||||
factory.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckSuccessNet() throws InterruptedException {
|
||||
healthCheckSuccess(new TcpNetServerConnectionFactory(0), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckSuccessNio() throws InterruptedException {
|
||||
healthCheckSuccess(new TcpNioServerConnectionFactory(0), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckFailureNet() throws InterruptedException {
|
||||
healthCheckSuccess(new TcpNetServerConnectionFactory(0), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthCheckFailureNio() throws InterruptedException {
|
||||
healthCheckSuccess(new TcpNioServerConnectionFactory(0), true);
|
||||
}
|
||||
|
||||
private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean fail) throws InterruptedException {
|
||||
CountDownLatch serverUp = new CountDownLatch(1);
|
||||
server.setApplicationEventPublisher(event -> {
|
||||
if (event instanceof TcpConnectionServerListeningEvent) {
|
||||
serverUp.countDown();
|
||||
}
|
||||
});
|
||||
server.setBeanFactory(mock(BeanFactory.class));
|
||||
AtomicReference<TcpConnection> connection = new AtomicReference<>();
|
||||
server.registerSender(conn -> {
|
||||
connection.set(conn);
|
||||
});
|
||||
AtomicInteger tested = new AtomicInteger();
|
||||
server.registerListener(msg -> {
|
||||
if (!(msg instanceof ErrorMessage)) {
|
||||
String payload = new String((byte[]) msg.getPayload());
|
||||
if (payload.equals("PING")) {
|
||||
tested.incrementAndGet();
|
||||
connection.get().send(new GenericMessage<>(fail ? "PANG" : "PONG"));
|
||||
}
|
||||
else {
|
||||
connection.get().send(msg);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
server.start();
|
||||
assertThat(serverUp.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
TcpNetClientConnectionFactory clientFactory = new TcpNetClientConnectionFactory("localhost", server.getPort());
|
||||
clientFactory.setApplicationEventPublisher(event -> { });
|
||||
clientFactory.setConnectionTest(conn -> {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
AtomicBoolean result = new AtomicBoolean();
|
||||
conn.registerTestListener(msg -> {
|
||||
if (Arrays.equals("PONG".getBytes(), (byte[]) msg.getPayload())) {
|
||||
result.set(true);
|
||||
}
|
||||
latch.countDown();
|
||||
return false;
|
||||
});
|
||||
conn.send(new GenericMessage<>("PING"));
|
||||
try {
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return result.get();
|
||||
});
|
||||
TcpOutboundGateway gateway = new TcpOutboundGateway();
|
||||
gateway.setRemoteTimeout(60000);
|
||||
gateway.setConnectionFactory(clientFactory);
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
gateway.setOutputChannel(outputChannel);
|
||||
gateway.start();
|
||||
if (fail) {
|
||||
assertThatExceptionOfType(MessagingException.class).isThrownBy(() ->
|
||||
gateway.handleMessage(new GenericMessage<>("test1")))
|
||||
.withMessageContaining("Connection test failed for");
|
||||
}
|
||||
else {
|
||||
gateway.handleMessage(new GenericMessage<>("test1"));
|
||||
Message<?> received = outputChannel.receive(0);
|
||||
assertThat(received).isNotNull();
|
||||
assertThat(received.getPayload()).isEqualTo("test1".getBytes());
|
||||
gateway.handleMessage(new GenericMessage<>("test2"));
|
||||
received = outputChannel.receive(0);
|
||||
assertThat(received).isNotNull();
|
||||
assertThat(received.getPayload()).isEqualTo("test2".getBytes());
|
||||
assertThat(tested.get()).isEqualTo(1);
|
||||
}
|
||||
gateway.stop();
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private class FooEvent extends TcpConnectionOpenEvent {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user