/** * Copyright 2014-2017 Linagora, Université Joseph Fourier, Floralis * * The present code is developed in the scope of the joint LINAGORA - * Université Joseph Fourier - Floralis research program and is designated * as a "Result" pursuant to the terms and conditions of the LINAGORA * - Université Joseph Fourier - Floralis research program. Each copyright * holder of Results enumerated here above fully & independently holds complete * ownership of the complete Intellectual Property rights applicable to the whole * of said Results, and may freely exploit it in any manner which does not infringe * the moral rights of the other copyright holders. * * 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 net.roboconf.messaging.rabbitmq.internal.utils; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.EXCHANGE_DM; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.EXCHANGE_INTER_APP; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SERVER_IP; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SERVER_PASSWORD; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SERVER_USERNAME; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SSL_AS_USER_DATA; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SSL_KEY_STORE_PASSPHRASE; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SSL_KEY_STORE_PATH; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SSL_TRUST_STORE_PASSPHRASE; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_SSL_TRUST_STORE_PATH; import static net.roboconf.messaging.rabbitmq.RabbitMqConstants.RABBITMQ_USE_SSL; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.util.HashMap; import java.util.Map; import javax.net.ssl.SSLContext; import org.junit.Assert; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import com.rabbitmq.client.Channel; import com.rabbitmq.client.ConnectionFactory; import net.roboconf.core.utils.Utils; import net.roboconf.messaging.api.extensions.MessagingContext; import net.roboconf.messaging.api.extensions.MessagingContext.RecipientKind; import net.roboconf.messaging.api.extensions.MessagingContext.ThoseThat; import net.roboconf.messaging.rabbitmq.RabbitMqConstants; /** * @author Vincent Zurczak - Linagora */ public class RabbitMqUtilsTest { private static boolean rabbitMqIsRunning = false; @BeforeClass public static void checkRabbitMqIsRunning() throws Exception { rabbitMqIsRunning = RabbitMqTestUtils.checkRabbitMqIsRunning(); } @Rule public TemporaryFolder folder = new TemporaryFolder(); @Test public void testDeclareApplicationExchanges() throws Exception { Channel channel = Mockito.mock( Channel.class ); RabbitMqUtils.declareApplicationExchanges( null, null, channel ); Mockito.verifyZeroInteractions( channel ); RabbitMqUtils.declareApplicationExchanges( "domain", "te", channel ); String exchangeName = RabbitMqUtils.buildExchangeNameForAgent( "domain", "te" ); Mockito.verify( channel, Mockito.times( 1 )).exchangeDeclare( exchangeName, "topic" ); } @Test public void testDeclareGlobalExchanges() throws Exception { Channel channel = Mockito.mock( Channel.class ); RabbitMqUtils.declareGlobalExchanges( "d", channel ); Mockito.verify( channel, Mockito.times( 1 )).exchangeDeclare( "d." + EXCHANGE_DM, "topic" ); Mockito.verify( channel, Mockito.times( 1 )).exchangeDeclare( "d." + EXCHANGE_INTER_APP, "topic" ); } @Test public void testBuildExchangeNameForAgent() { Assert.assertEquals( "d1.test.agents", RabbitMqUtils.buildExchangeNameForAgent( "d1", "test" )); Assert.assertEquals( "d2.te.agents", RabbitMqUtils.buildExchangeNameForAgent( "d2", "te" )); } @Test public void testBuildExchangeName() { MessagingContext ctx = new MessagingContext( RecipientKind.DM, "domain", "app1" ); Assert.assertEquals( "domain." + EXCHANGE_DM, RabbitMqUtils.buildExchangeName( ctx )); ctx = new MessagingContext( RecipientKind.DM, "domain", "app2" ); Assert.assertEquals( "domain." + EXCHANGE_DM, RabbitMqUtils.buildExchangeName( ctx )); ctx = new MessagingContext( RecipientKind.INTER_APP, "domain", "app1" ); Assert.assertEquals( "domain." + EXCHANGE_INTER_APP, RabbitMqUtils.buildExchangeName( ctx )); ctx = new MessagingContext( RecipientKind.INTER_APP, "domain", "facet", ThoseThat.IMPORT, "app1" ); Assert.assertEquals( "domain." + EXCHANGE_INTER_APP, RabbitMqUtils.buildExchangeName( ctx )); ctx = new MessagingContext( RecipientKind.AGENTS, "domain", "facet", ThoseThat.IMPORT, "app1" ); Assert.assertEquals( "domain.app1.agents", RabbitMqUtils.buildExchangeName( ctx )); ctx = new MessagingContext( RecipientKind.AGENTS, "domain1", "facet", ThoseThat.EXPORT, "app2" ); Assert.assertEquals( "domain1.app2.agents", RabbitMqUtils.buildExchangeName( ctx )); } @Test public void testConfigureFactory() throws Exception { String address = "http://roboconf.net/some/path"; int port = 18547; String username = "toto"; String password= "123456789"; ConnectionFactory factory = new ConnectionFactory(); Assert.assertNotSame( address, factory.getHost()); Assert.assertNotSame( port, factory.getPort()); Map<String,String> configuration = new HashMap<> (); configuration.put( RABBITMQ_SERVER_IP, "http://roboconf.net:" + port + "/some/path" ); configuration.put( RABBITMQ_SERVER_USERNAME, username ); configuration.put( RABBITMQ_SERVER_PASSWORD, password ); RabbitMqUtils.configureFactory( factory, configuration ); Assert.assertEquals( address, factory.getHost()); Assert.assertEquals( port, factory.getPort()); Assert.assertEquals( username, factory.getUsername()); Assert.assertEquals( password, factory.getPassword()); } @Test public void testConfigureFactory_nullIp() throws Exception { ConnectionFactory factory = new ConnectionFactory(); String username = "toto"; String password= "123456789"; Map<String,String> configuration = new HashMap<> (); configuration.put( RABBITMQ_SERVER_IP, null ); configuration.put( RABBITMQ_SERVER_USERNAME, username ); configuration.put( RABBITMQ_SERVER_PASSWORD, password ); RabbitMqUtils.configureFactory( factory, configuration ); Assert.assertEquals( username, factory.getUsername()); Assert.assertEquals( password, factory.getPassword()); } @Test public void testConfigureFactory_withoutSslEnabled() throws Exception { int port = 18547; ConnectionFactory factory = Mockito.mock( ConnectionFactory.class ); Map<String,String> configuration = new HashMap<> (); configuration.put( RABBITMQ_SERVER_IP, "http://roboconf.net:" + port ); configuration.put( RABBITMQ_SERVER_USERNAME, "toto" ); configuration.put( RABBITMQ_SERVER_PASSWORD, "123456789" ); configuration.put( RABBITMQ_SSL_KEY_STORE_PATH, this.folder.newFile().getAbsolutePath()); configuration.put( RABBITMQ_SSL_KEY_STORE_PASSPHRASE, "key store" ); configuration.put( RABBITMQ_SSL_TRUST_STORE_PATH, this.folder.newFile().getAbsolutePath()); configuration.put( RABBITMQ_SSL_TRUST_STORE_PASSPHRASE, "trust store" ); configuration.put( RABBITMQ_SSL_AS_USER_DATA, "true" ); RabbitMqUtils.configureFactory( factory, configuration ); Mockito.verify( factory ).setUsername( "toto" ); Mockito.verify( factory ).setPassword( "123456789" ); Mockito.verify( factory ).setHost( "http://roboconf.net" ); Mockito.verify( factory ).setPort( port ); Mockito.verify( factory ).setConnectionTimeout( Mockito.anyInt()); Mockito.verify( factory ).setAutomaticRecoveryEnabled( true ); Mockito.verify( factory ).setNetworkRecoveryInterval( Mockito.anyInt()); Mockito.verify( factory ).setTopologyRecoveryEnabled( true ); Mockito.verifyZeroInteractions( factory ); } @Test public void testConfigureFactory_withSslEnabled() throws Exception { int port = 18547; ConnectionFactory factory = Mockito.mock( ConnectionFactory.class ); String keyPassPhrase = "key store"; File keyStore = generateKeyStore( keyPassPhrase, RabbitMqConstants.DEFAULT_SSL_KEY_STORE_TYPE ); String trustPassPhrase = "trust store"; File trustStore = generateKeyStore( trustPassPhrase, RabbitMqConstants.DEFAULT_SSL_TRUST_STORE_TYPE ); Map<String,String> configuration = new HashMap<> (); configuration.put( RABBITMQ_SERVER_IP, "http://roboconf.net:" + port ); configuration.put( RABBITMQ_SERVER_USERNAME, "toto" ); configuration.put( RABBITMQ_SERVER_PASSWORD, "123456789" ); configuration.put( RABBITMQ_SSL_KEY_STORE_PATH, keyStore.getAbsolutePath()); configuration.put( RABBITMQ_SSL_KEY_STORE_PASSPHRASE, keyPassPhrase ); configuration.put( RABBITMQ_SSL_TRUST_STORE_PATH, trustStore.getAbsolutePath()); configuration.put( RABBITMQ_SSL_TRUST_STORE_PASSPHRASE, trustPassPhrase ); configuration.put( RABBITMQ_SSL_AS_USER_DATA, "true" ); configuration.put( RABBITMQ_USE_SSL, "true" ); RabbitMqUtils.configureFactory( factory, configuration ); Mockito.verify( factory ).setUsername( "toto" ); Mockito.verify( factory ).setPassword( "123456789" ); Mockito.verify( factory ).setHost( "http://roboconf.net" ); Mockito.verify( factory ).setPort( port ); Mockito.verify( factory ).setConnectionTimeout( Mockito.anyInt()); Mockito.verify( factory ).setAutomaticRecoveryEnabled( true ); Mockito.verify( factory ).setNetworkRecoveryInterval( Mockito.anyInt()); Mockito.verify( factory ).setTopologyRecoveryEnabled( true ); Mockito.verify( factory ).useSslProtocol( Mockito.any( SSLContext.class )); Mockito.verifyZeroInteractions( factory ); } @Test( expected = IOException.class ) public void testConfigureFactory_withSslEnabled_ioException() throws Exception { ConnectionFactory factory = Mockito.mock( ConnectionFactory.class ); String trustPassPhrase = "trust store"; File trustStore = generateKeyStore( trustPassPhrase, RabbitMqConstants.DEFAULT_SSL_TRUST_STORE_TYPE ); Map<String,String> configuration = new HashMap<> (); configuration.put( RABBITMQ_SERVER_IP, "http://roboconf.net:18547/some/path" ); configuration.put( RABBITMQ_SERVER_USERNAME, "toto" ); configuration.put( RABBITMQ_SERVER_PASSWORD, "123456789" ); configuration.put( RABBITMQ_SSL_KEY_STORE_PATH, "does not exist" ); configuration.put( RABBITMQ_SSL_KEY_STORE_PASSPHRASE, "key store" ); configuration.put( RABBITMQ_SSL_TRUST_STORE_PATH, trustStore.getAbsolutePath()); configuration.put( RABBITMQ_SSL_TRUST_STORE_PASSPHRASE, trustPassPhrase ); configuration.put( RABBITMQ_SSL_AS_USER_DATA, "true" ); configuration.put( RABBITMQ_USE_SSL, "true" ); RabbitMqUtils.configureFactory( factory, configuration ); } @Test public void testCloseConnection_withNull() throws Exception { RabbitMqUtils.closeConnection( null ); } @Test public void testCloseConnection() throws Exception { Assume.assumeTrue( rabbitMqIsRunning ); Channel channel = RabbitMqTestUtils.createTestChannel(); Assert.assertTrue( channel.isOpen()); Assert.assertTrue( channel.getConnection().isOpen()); // Close it RabbitMqUtils.closeConnection( channel ); Assert.assertFalse( channel.isOpen()); Assert.assertFalse( channel.getConnection().isOpen()); // Make sure closing an already closed channel does not throw an exception RabbitMqUtils.closeConnection( channel ); Assert.assertFalse( channel.isOpen()); Assert.assertFalse( channel.getConnection().isOpen()); } /** * Generates an empty key store. * @param passPhrase the pass phrase (not null) * @param type the type of the store * @return the key store file * @throws IOException * @throws GeneralSecurityException */ private File generateKeyStore( String passPhrase, String type ) throws IOException, GeneralSecurityException { File result = this.folder.newFile(); FileOutputStream fos = null; try { fos = new FileOutputStream( result.getAbsolutePath()); KeyStore ks = KeyStore.getInstance( type ); ks.load( null, null ); ks.store( fos, passPhrase.toCharArray()); } finally { Utils.closeQuietly( fos ); } Assert.assertTrue( result.isFile()); return result; } }