blob: 6bc0ca36fffe6fb9ac454588b7e96276950e5b1f [file] [log] [blame]
/*
*
* 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.qpid.server.logging;
import java.util.List;
import java.util.regex.Pattern;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import org.apache.qpid.QpidException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.server.virtualhost.VirtualHostPropertiesNodeCreator;
public class ChannelLoggingTest extends AbstractTestLogging
{
private static final String CHANNEL_CLOSE_FORCED_MESSAGE_PATTERN = "CHN-1003 : Close : \\d* - .*";
private static final String CHANNEL_PREFIX = "CHN-";
@Override
public void setUp() throws Exception
{
// disable the virtualhostPropertiesNode as it messes with the logging since it causes the client to
// create a session and then it sends a message
setTestSystemProperty("qpid.plugin.disabled:systemnodecreator."+ VirtualHostPropertiesNodeCreator.TYPE, "true");
super.setUp();
}
/**
* Description:
* When a new Channel (JMS Session) is created this will be logged as a CHN-1001 Create message. The messages will contain the prefetch details about this new Channel.
* Input:
*
* 1. Running Broker
* 2. New JMS Session/Channel creation
*
* Output:
* <date> CHN-1001 : Create
* <date> CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number}
*
* Validation Steps:
* 1. The CHN ID is correct
* 2. The prefetch value matches that defined by the requesting client.
*
* @throws Exception - if an error occurs
*/
public void testChannelCreate() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
int PREFETCH = 12;
if(!(isBroker010() || isBroker10()))
{
// Test that calling session.close gives us the expected output
((AMQConnection) connection).createSession(false, Session.AUTO_ACKNOWLEDGE, PREFETCH);
}
else
{
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
// Wait to ensure that the CHN-1001 message is logged
waitForMessage("CHN-1001");
List<String> results = findMatches("CHN-1001");
// Validation
assertEquals("CHN-1001 messages not logged", isBroker10() ? 2 : 1, results.size());
String log = getLogMessage(results, isBroker10() ? 1 : 0);
// MESSAGE [con:0(guest@anonymous(3273383)/test)/ch:1] CHN-1001 : Create
validateMessageID("CHN-1001", log);
final String fromActor = fromActor(log);
final int channelID = getChannelID(fromActor);
assertEquals("Incorrect Channel in actor:"+fromActor(log), isBroker010()? 0 : 1, channelID);
if (!(isBroker010() || isBroker10()))
{
// Wait to ensure that the CHN-1004 message is logged
waitForMessage("CHN-1004");
results = findMatches("CHN-1004");
// Validation
assertEquals("CHN-1004 messages not logged", 1, results.size());
log = getLogMessage(results, 0);
// MESSAGE [con:0(guest@anonymous(3273383)/test)/ch:1] CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number}
validateMessageID("CHN-1004", log);
assertEquals("Incorrect Channel in actor:"+fromActor(log), 1, getChannelID(fromActor(log)));
assertTrue("Prefetch Count not correct",getMessageString(fromMessage(log)).endsWith("Count "+PREFETCH));
}
connection.close();
}
/**
* Description:
* The Apache Qpid Broker for Java implements consumer flow control for all ack modes except
* No-Ack. When a client connects the session's flow is initially set to
* Stopped. Verify this message appears
*
* Input:
* 1. Running broker
* 2. Create consumer
* Output:
*
* <date> CHN-1002 : Flow Stopped
*
* Validation Steps:
* 4. The CHN ID is correct
*
* @throws Exception - if an error occurs
*/
public void testChannelStartsFlowStopped() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
// Create a session to fill up
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = createTestQueue(session);
connection.start();
// Wait to ensure that the CHN-1002 message is logged
waitForMessage("CHN-1002");
List<String> results = findMatches(CHANNEL_PREFIX);
assertTrue("No CHN messages logged", results.size() > 0);
// The last channel message should be:
//
// INFO - MESSAGE [con:0(guest@anonymous(4205299)/test)/ch:1] [con:0(guest@anonymous(4205299)/test)/ch:1] CHN-1002 : Flow Stopped
// Verify the last channel message is stopped
validateChannelStart(results, false);
}
private void validateChannelStart(List<String> results, boolean flowStarted)
{
String log = getLogMessageFromEnd(results, 0);
String flow = flowStarted ? "Started" : "Stopped";
validateMessageID("CHN-1002", log);
assertEquals("Message should be Flow " + flow, "Flow " + flow, getMessageString(fromMessage(log)));
}
/**
* Description:
* The Apache Qpid Broker for Java implements consumer flow control for all ack modes except
* No-Ack. When the client first attempts to receive a message then the Flow
* status of the Session is set to Started.
*
* Input:
* 1. Running broker
* 2. Create a consumer
* 3. Attempt to receive a message
* Output:
*
* <date> CHN-1002 : Flow Started
*
* Validation Steps:
* 4. The CHN ID is correct
*
* @throws Exception - if an error occurs
*/
public void testChannelStartConsumerFlowStarted() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
// Create a session to fill up
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = createTestQueue(session);
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
//Call receive to send the Flow On message
consumer.receiveNoWait();
//Wait for up to 2 seconds for message to appear
// ignore response as we will use the findMatches afterwards just
// incase it did take more than 2 seconds to log.
_monitor.waitForMessage(CHANNEL_PREFIX, 2000);
// Wait to ensure that the CHN-1002 message is logged
waitForMessage("CHN-1002");
List<String> results = findMatches(CHANNEL_PREFIX);
assertTrue("No CHN messages logged", results.size() > 0);
// The last two channel messages(before the close) should be:
//
// INFO [qpid.message] MESSAGE [con:1(guest@/127.0.0.1:49869/test)/ch:1] [con:1(guest@/127.0.0.1:49869/test)/ch:1] CHN-1002 : Flow Stopped
// INFO [qpid.message] MESSAGE [con:1(guest@/127.0.0.1:49869/test)/ch:1] [con:1(guest@/127.0.0.1:49869/test)/ch:1] CHN-1002 : Flow Started
// Verify the last channel msg is Started.
validateChannelStart(results, true);
}
/**
* Description:
* When the client gracefully closes the Connection then a CHN-1003 Close
* message will be issued. This must be the last message logged for this
* Channel.
* Input:
* 1. Running Broker
* 2. Connected Client
* 3. Client then requests that the Connection is closed
* Output:
*
* <date> CHN-1003 : Close
*
* Validation Steps:
* 4. The MST ID is correct
* 5. This must be the last message logged for this Channel.
*
* @throws Exception - if an error occurs
*/
public void testChannelCloseViaConnectionClose() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
// Create a session
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Close the connection to verify the created session closing is logged.
connection.close();
// Wait to ensure that the CHN-1003 message is logged
waitForMessage("CHN-1003");
List<String> results = findMatches(CHANNEL_PREFIX);
assertTrue("No CHN messages logged", results.size() > 0);
// The last two channel messages should be:
//
// INFO - MESSAGE [con:0(guest@anonymous(4205299)/test)/ch:1] [con:0(guest@anonymous(4205299)/test)/ch:1] CHN-1002 : Flow On
// Verify
validateChannelClose(results);
}
/**
* Description:
* When the client gracefully closes the Connection then a CHN-1003 Close
* message will be issued. This must be the last message logged for this
* Channel.
* Input:
* 1. Running Broker
* 2. Connected Client
* 3. Client then requests that the Channel is closed
* Output:
*
* <date> CHN-1003 : Close
*
* Validation Steps:
* 4. The MST ID is correct
* 5. This must be the last message logged for this Channel.
*
* @throws Exception - if an error occurs
*/
public void testChannelCloseViaChannelClose() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
// Create a session and then close it
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
waitForMessage("CHN-1001");
// Wait to ensure that the CHN-1003 message is logged
session.close();
waitForMessage("CHN-1003");
List<String> results = findMatches(CHANNEL_PREFIX);
assertTrue("No CHN messages logged", results.size() > 0);
// Verify
validateChannelClose(results);
}
public void testChannelClosedOnExclusiveQueueDeclaredOnDifferentSession() throws Exception
{
assertLoggingNotYetOccured(CHANNEL_PREFIX);
Connection connection = getConnection();
// Create a session and then close it
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
waitForMessage("CHN-1001");
Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
waitForMessage("CHN-1001");
String testQueueName = getTestQueueName();
Queue queue = (Queue) session.createQueue("direct://amq.direct/" + testQueueName + "/" + testQueueName
+ "?exclusive='true'");
((AMQSession<?,?>)session).declareAndBind((AMQDestination)queue);
try
{
((AMQSession<?,?>)session2).declareAndBind((AMQDestination) queue);
fail("Exception not thrown");
}
catch (QpidException acce)
{
// pass
}
catch (Exception e)
{
fail("Wrong exception thrown " + e);
}
waitForMessage("CHN-1003");
List<String> results = findMatches(CHANNEL_PREFIX);
assertTrue("No CHN messages logged", results.size() > 0);
String closeLog = results.get(results.size() -1);
int closeMessageID = closeLog.indexOf("CHN-1003");
assertFalse("CHN-1003 is not found", closeMessageID == -1);
String closeMessage = closeLog.substring(closeMessageID);
assertTrue("Unexpected close channel message :" + closeMessage, Pattern.matches(CHANNEL_CLOSE_FORCED_MESSAGE_PATTERN, closeMessage));
session.close();
connection.close();
}
private void validateChannelClose(List<String> results)
{
String open = getLogMessage(results, isBroker10() ? 1 : 0);
String close = getLogMessageFromEnd(results, 0);
validateMessageID("CHN-1001", open);
validateMessageID("CHN-1003", close);
assertEquals("Message should be Close", "Close", getMessageString(fromMessage(close)));
assertEquals("Incorrect Channel ID closed: " + close, isBroker010()? 0 : 1, getChannelID(fromSubject(close)));
assertEquals("Channel IDs should be the same", getChannelID(fromActor(open)), getChannelID(fromSubject(close)));
assertEquals("Connection IDs should be the same", getConnectionID(fromActor(open)), getConnectionID(fromSubject(close)));
}
}