/** * 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.activemq.network; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Session; import javax.jms.TopicConnection; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; import junit.framework.TestCase; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.region.Destination; import org.apache.activemq.command.ActiveMQTopic; /** * Various Tests to show the memory leak suspect in network of brokers. This is * for https://issues.apache.org/activemq/browse/AMQ-2530 */ public class NetworkRemovesSubscriptionsTest extends TestCase { private final static String frontEndAddress = "tcp://0.0.0.0:61617"; private final static String backEndAddress = "tcp://0.0.0.0:61616"; private final static String TOPIC_NAME = "TEST_TOPIC"; private BrokerService frontEnd; private BrokerService backEnd; private final ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(frontEndAddress); private final ActiveMQTopic topic = new ActiveMQTopic(TOPIC_NAME); public void testWithSessionAndSubsciberClose() throws Exception { TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); for (int i = 0; i < 100; i++) { TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSubscriber subscriber = subscriberSession.createSubscriber(topic); DummyMessageListener listener = new DummyMessageListener(); subscriber.setMessageListener(listener); subscriber.close(); subscriberSession.close(); } connection.close(); Thread.sleep(1000); Destination dest = backEnd.getRegionBroker().getDestinationMap().get(topic); assertNotNull(dest); assertTrue(dest.getConsumers().isEmpty()); } public void testWithSessionCloseOutsideTheLoop() throws Exception { TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); for (int i = 0; i < 100; i++) { TopicSubscriber subscriber = subscriberSession.createSubscriber(topic); DummyMessageListener listener = new DummyMessageListener(); subscriber.setMessageListener(listener); subscriber.close(); } subscriberSession.close(); connection.close(); Thread.sleep(1000); Destination dest = backEnd.getRegionBroker().getDestinationMap().get(topic); assertNotNull(dest); assertTrue(dest.getConsumers().isEmpty()); } public void testWithOneSubscriber() throws Exception { TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSubscriber subscriber = subscriberSession.createSubscriber(topic); DummyMessageListener listener = new DummyMessageListener(); subscriber.setMessageListener(listener); subscriber.close(); subscriberSession.close(); connection.close(); Thread.sleep(1000); Destination dest = backEnd.getRegionBroker().getDestinationMap().get(topic); assertNotNull(dest); assertTrue(dest.getConsumers().isEmpty()); } public void testWithoutSessionAndSubsciberClose() throws Exception { TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); for (int i = 0; i < 100; i++) { TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSubscriber subscriber = subscriberSession.createSubscriber(topic); assertNotNull(subscriber); } connection.close(); Thread.sleep(1000); Destination dest = backEnd.getRegionBroker().getDestinationMap().get(topic); assertNotNull(dest); assertTrue(dest.getConsumers().isEmpty()); } /** * Running this test you can produce a leak of only 2 ConsumerInfo on BE * broker, NOT 200 as in other cases! */ public void testWithoutSessionAndSubsciberClosePlayAround() throws Exception { TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); for (int i = 0; i < 100; i++) { TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSubscriber subscriber = subscriberSession.createSubscriber(topic); DummyMessageListener listener = new DummyMessageListener(); subscriber.setMessageListener(listener); if (i != 50) { subscriber.close(); subscriberSession.close(); } } connection.close(); Thread.sleep(1000); Destination dest = backEnd.getRegionBroker().getDestinationMap().get(topic); assertNotNull(dest); assertTrue(dest.getConsumers().isEmpty()); } class DummyMessageListener implements MessageListener { @Override public void onMessage(Message arg0) { // TODO Auto-generated method stub } } @Override protected void setUp() throws Exception { this.backEnd = new BrokerService(); this.backEnd.setBrokerName("backEnd"); this.backEnd.setPersistent(false); NetworkConnector backEndNetwork = this.backEnd.addNetworkConnector("static://" + frontEndAddress); backEndNetwork.setName("backEndNetwork"); backEndNetwork.setDynamicOnly(true); this.backEnd.addConnector(backEndAddress); this.backEnd.start(); this.frontEnd = new BrokerService(); this.frontEnd.setBrokerName("frontEnd"); this.frontEnd.setPersistent(false); NetworkConnector frontEndNetwork = this.frontEnd.addNetworkConnector("static://" + backEndAddress); frontEndNetwork.setName("frontEndNetwork"); this.frontEnd.addConnector(frontEndAddress); this.frontEnd.start(); Thread.sleep(2000); } @Override protected void tearDown() throws Exception { if (this.backEnd != null) { this.backEnd.stop(); } if (this.frontEnd != null) { this.frontEnd.stop(); } } }