/*
* Copyright 2002-2016 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.
* 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.springframework.integration.syslog.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.net.SocketFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.syslog.MessageConverter;
import org.springframework.integration.syslog.RFC5424MessageConverter;
import org.springframework.integration.syslog.inbound.TcpSyslogReceivingChannelAdapter;
import org.springframework.integration.syslog.inbound.UdpSyslogReceivingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @since 3.0
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class SyslogReceivingChannelAdapterParserTests {
@Autowired @Qualifier("foo.adapter")
private UdpSyslogReceivingChannelAdapter adapter1;
@Autowired
private UdpSyslogReceivingChannelAdapter foobar;
@Autowired
private PollableChannel foo;
@Autowired @Qualifier("explicitUdp.adapter")
private UdpSyslogReceivingChannelAdapter explicitUdpAdapter;
@Autowired
private PollableChannel explicitUdp;
@Autowired
private PollableChannel errors;
@Autowired
private UdpSyslogReceivingChannelAdapter fullBoatUdp;
@Autowired
private PassThruConverter converter;
@Autowired
private RFC5424MessageConverter rfc5424;
@Autowired @Qualifier("bar.adapter")
private TcpSyslogReceivingChannelAdapter adapter2;
@Autowired
private PollableChannel bar;
@Autowired
private TcpSyslogReceivingChannelAdapter fullBoatTcp;
@Autowired
private AbstractServerConnectionFactory cf;
@Test
public void testSimplestUdp() throws Exception {
int port = TestUtils.getPropertyValue(adapter1, "udpAdapter.port", Integer.class);
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", port));
DatagramSocket socket = new DatagramSocket();
Thread.sleep(1000);
socket.send(packet);
socket.close();
Message<?> message = foo.receive(10000);
assertNotNull(message);
adapter1.stop();
}
@Test
public void testExplicitChannelUdp() throws Exception {
assertEquals(1514, TestUtils.getPropertyValue(foobar, "udpAdapter.port"));
assertSame(foo, TestUtils.getPropertyValue(foobar, "outputChannel"));
}
@Test
public void testExplicitUdp() throws Exception {
assertSame(explicitUdp, TestUtils.getPropertyValue(explicitUdpAdapter, "outputChannel"));
}
@Test
public void testFullBoatUdp() {
assertSame(foo, TestUtils.getPropertyValue(fullBoatUdp, "outputChannel"));
assertFalse(fullBoatUdp.isAutoStartup());
assertEquals(123, fullBoatUdp.getPhase());
assertEquals(456L, TestUtils.getPropertyValue(fullBoatUdp, "messagingTemplate.sendTimeout"));
assertSame(converter, TestUtils.getPropertyValue(fullBoatUdp, "converter"));
assertSame(errors, TestUtils.getPropertyValue(fullBoatUdp, "errorChannel"));
assertFalse(TestUtils.getPropertyValue(fullBoatUdp, "udpAdapter.mapper.lookupHost", Boolean.class));
}
@Test
public void testSimplestTcp() throws Exception {
AbstractServerConnectionFactory connectionFactory = TestUtils.getPropertyValue(adapter2, "connectionFactory",
AbstractServerConnectionFactory.class);
int port = connectionFactory.getPort();
waitListening(connectionFactory, 10000L);
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE\n".getBytes("UTF-8");
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
Thread.sleep(1000);
socket.getOutputStream().write(buf);
socket.close();
Message<?> message = bar.receive(10000);
assertNotNull(message);
adapter2.stop();
assertNotNull(TestUtils.getPropertyValue(adapter2, "connectionFactory.applicationEventPublisher"));
}
@Test
public void testFullBoatTcp() {
assertSame(bar, TestUtils.getPropertyValue(fullBoatTcp, "outputChannel"));
assertFalse(fullBoatTcp.isAutoStartup());
assertEquals(123, fullBoatTcp.getPhase());
assertEquals(456L, TestUtils.getPropertyValue(fullBoatUdp, "messagingTemplate.sendTimeout"));
assertSame(rfc5424, TestUtils.getPropertyValue(fullBoatTcp, "converter"));
assertSame(errors, TestUtils.getPropertyValue(fullBoatTcp, "errorChannel"));
assertSame(cf, TestUtils.getPropertyValue(fullBoatTcp, "connectionFactory"));
}
@Test
public void testPortOnUdpChild() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail1-context.xml", this.getClass())
.close();
fail("Expected exception");
}
catch (BeanDefinitionParsingException e) {
assertTrue(e.getMessage().startsWith(
"Configuration problem: When child element 'udp-attributes' is present, 'port' must be defined there"));
}
}
@Test
public void testPortWithTCPFactory() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail2-context.xml", this.getClass())
.close();
fail("Expected exception");
}
catch (BeanCreationException e) {
assertEquals("Cannot specify both 'port' and 'connectionFactory'", e.getCause().getMessage());
}
}
@Test
public void testUdpChildWithTcp() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail3-context.xml", this.getClass())
.close();
fail("Expected exception");
}
catch (BeanCreationException e) {
e.printStackTrace();
assertEquals("Cannot specify 'udp-attributes' when the protocol is 'tcp'", e.getCause().getMessage());
}
}
@Test
public void testUDPWithTCPFactory() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail4-context.xml", this.getClass())
.close();
fail("Expected exception");
}
catch (BeanCreationException e) {
assertEquals("Cannot specify 'connection-factory' unless the protocol is 'tcp'",
e.getCause().getMessage());
}
}
public static class PassThruConverter implements MessageConverter {
@Override
public Message<?> fromSyslog(Message<?> syslog) throws Exception {
return syslog;
}
}
/**
* Wait for a server connection factory to actually start listening before
* starting a test. Waits for up to 10 seconds by default.
* @param serverConnectionFactory The server connection factory.
* @param delay How long to wait in milliseconds; default 10000 (10 seconds) if null.
* @throws IllegalStateException
*/
private void waitListening(AbstractServerConnectionFactory serverConnectionFactory, Long delay)
throws IllegalStateException {
if (delay == null) {
delay = 100L;
}
else {
delay = delay / 100;
}
int n = 0;
while (!serverConnectionFactory.isListening()) {
try {
Thread.sleep(100);
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e1);
}
if (n++ > delay) {
throw new IllegalStateException("Server didn't start listening.");
}
}
}
}