blob: b666b1f42452070ce54f50835624d204ea458f1f [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 org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.util.LogMonitor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Abstract superclass for logging test set up and utility methods.
*
* So named to prevent it being selected itself as a test to run by the test suite.
*/
public class AbstractTestLogging extends QpidBrokerTestCase
{
public static final long DEFAULT_LOG_WAIT = 2000;
public static final String TEST_LOG_PREFIX = "MESSAGE";
protected LogMonitor _monitor;
private InternalBrokerBaseCase _configLoader;
@Override
public void setUp() throws Exception
{
setLogMessagePrefix();
super.setUp();
_monitor = new LogMonitor(_outputFile);
}
protected ServerConfiguration getServerConfig() throws ConfigurationException
{
ServerConfiguration _serverConfiguration;
if (isExternalBroker())
{
_serverConfiguration = new ServerConfiguration(_configFile)
{
@Override
public void initialise() throws ConfigurationException
{
//Overriding initialise to only setup the vhosts and not
//perform the ConfigurationPlugin setup, removing need for
//an ApplicationRegistry to be loaded.
setupVirtualHosts(getConfig());
}
};
_serverConfiguration.initialise();
}
else
{
_serverConfiguration = ApplicationRegistry.getInstance().getConfiguration();
}
return _serverConfiguration;
}
protected void setLogMessagePrefix()
{
//set the message prefix to facilitate scraping from the munged test output.
setSystemProperty("qpid.logging.prefix", TEST_LOG_PREFIX);
}
@Override
public void tearDown() throws Exception
{
_monitor.close();
if (isExternalBroker() && _configLoader != null)
{
_configLoader.tearDown();
}
super.tearDown();
}
/**
* assert that the requested log message has not occured
*
* @param log
*
* @throws IOException
*/
public void assertLoggingNotYetOccured(String log) throws IOException
{
// Ensure the alert has not occured yet
assertEquals("Message has already occured:" + log, 0,
findMatches(log).size());
}
protected void validateMessageID(String id, String log)
{
assertEquals("Incorrect message", id, getMessageID(log));
}
protected String getMessageID(String log)
{
String message = fromMessage(log);
return message.substring(0, message.indexOf(" "));
}
/**
* Return the first channel id from the log string
* ' ch;X' if there is no channel id return -1.
*
* @param log the log string to search.
*
* @return channel id or -1 if no channel id exists.
*/
protected int getChannelID(String log)
{
int start = log.indexOf("ch:") + 3;
// If we do a check for ] as the boundary we will get cases where log
// is presented with the bounding. If we don't match a ] then we can use
// the end of the string as the boundary.
int end = log.indexOf("]", start);
if (end == -1)
{
end = log.length();
}
try
{
return Integer.parseInt(log.substring(start, end));
}
catch (Exception e)
{
return -1;
}
}
protected String fromMessage(String log)
{
int startSubject = log.indexOf("]") + 1;
int start = log.indexOf("]", startSubject) + 1;
// If we don't have a subject then the second indexOf will return 0
// in which case we can use the end of the actor as the index.
if (start == 0)
{
start = startSubject;
}
return log.substring(start).trim();
}
/**
* Extract the Subject from the Log Message.
*
* The subject is the second block inclosed in brackets '[ ]'.
*
* If there is no Subject or the second block of brackets '[ ]' cannot be
* identified then an empty String ("") is returned.
*
* The brackets '[ ]' are not included in the returned String.
*
* @param log The log message to process
*
* @return the Subject string or the empty string ("") if the subject can't be identified.
*/
protected String fromSubject(String log)
{
int start = log.indexOf("[") + 1;
// Take the second index
start = log.indexOf("[", start) + 1;
// There may not be a subject so in that case return nothing.
if (start == 0)
{
return "";
}
int end = log.indexOf("]", start);
try
{
return log.substring(start, end);
}
catch (IndexOutOfBoundsException iobe)
{
return "";
}
}
/**
* Extract the actor segment from the log message.
* The Actor segment is the first section enclosed in '[ ]'.
*
* No analysis is performed to ensure that the first '[ ]' section of the
* given log is really an Actor segment.
*
* The brackets '[ ]' are not included in the returned String.
*
* @param log the Log Message
*
* @return the Actor segment or "" if unable to locate '[ ]' section
*/
protected String fromActor(String log)
{
int start = log.indexOf("[") + 1;
int end = log.indexOf("]", start);
try
{
return log.substring(start, end).trim();
}
catch (IndexOutOfBoundsException iobe)
{
return "";
}
}
/**
* Return the message String from the given message section
*
* @param log the Message Section
*
* @return the Message String.
*/
protected String getMessageString(String log)
{
// Remove the Log ID from the returned String
int start = log.indexOf(":") + 1;
return log.substring(start).trim();
}
/**
* Given our log message extract the connection ID:
*
* The log string will contain the connectionID identified by 'con:'
*
* So extract the value shown here by X:
*
* 'con:X('
*
* Extract the value between the ':' and '(' and process it as an Integer
*
* If we are unable to find the right index or process the substring as an
* Integer then return -1.
*
* @param log the log String to process
*
* @return the connection ID or -1.
*/
protected int getConnectionID(String log)
{
int conIDStart = log.indexOf("con:") + 4;
int conIDEnd = log.indexOf("(", conIDStart);
try
{
return Integer.parseInt(log.substring(conIDStart, conIDEnd));
}
catch (Exception e)
{
return -1;
}
}
/**
* Extract the log entry from the raw log line which will contain other
* log4j formatting.
*
* This formatting may impead our testing process so extract the log message
* as we know it to be formatted.
*
* This starts with the string MESSAGE
*
* @param rawLog the raw log
*
* @return the log we are expecting to be printed without the log4j prefixes
*/
protected String getLog(String rawLog)
{
int start = rawLog.indexOf(TEST_LOG_PREFIX);
return rawLog.substring(start);
}
/**
* Extract the log entry from the result set. Positions are 0-based.
*
* @param results list of log message results to extract from
* @param position position in the list of the message to extract
* @return the message string
*/
protected String getLogMessage(List<String> results, int position)
{
return getLog(results.get(position));
}
/**
* Extract the nth-from-last log entry from the result set.
*
* @param results list of log message results to extract from
* @param positionFromEnd position from end of the message list to extract (eg 0 for last)
* @return the message string
*/
protected String getLogMessageFromEnd(List<String> results, int positionFromEnd)
{
int resultSize = results.size();
return getLogMessage(results, resultSize - 1 - positionFromEnd);
}
protected List<String> findMatches(String toFind) throws IOException
{
return _monitor.findMatches(toFind);
}
protected List<String> waitAndFindMatches(String toFind) throws IOException
{
return waitAndFindMatches(toFind, DEFAULT_LOG_WAIT);
}
protected List<String> waitAndFindMatches(String toFind, long wait) throws IOException
{
return _monitor.waitAndFindMatches(toFind, wait);
}
public boolean waitForMessage(String message) throws FileNotFoundException, IOException
{
return waitForMessage(message, DEFAULT_LOG_WAIT);
}
public boolean waitForMessage(String message, long wait) throws FileNotFoundException, IOException
{
return _monitor.waitForMessage(message, wait);
}
/**
* Given a list of messages that have been pulled out of a log file
* Process the results splitting the log statements in to lists based on the
* actor's connection ID.
*
* So for each log entry extract the Connecition ID from the Actor of the log
*
* Then use that as a key to a HashMap storing the list of log messages for
* that connection.
*
* @param logMessages The list of mixed connection log messages
*
* @return Map indexed by connection id to a list of log messages just for that connection.
*/
protected HashMap<Integer, List<String>> splitResultsOnConnectionID(List<String> logMessages)
{
HashMap<Integer, List<String>> connectionSplitList = new HashMap<Integer, List<String>>();
for (String log : logMessages)
{
// Get the connectionID from the Actor in the Message Log.
int cID = getConnectionID(fromActor(getLog(log)));
List<String> connectionData = connectionSplitList.get(cID);
// Create the initial List if we don't have one already
if (connectionData == null)
{
connectionData = new LinkedList<String>();
connectionSplitList.put(cID, connectionData);
}
// Store the log
connectionData.add(log);
}
return connectionSplitList;
}
/**
* Filter the give result set by the specficifed virtualhost.
* This is done using the getSlice to identify the virtualhost (vh) in the
* log message
*
* @param results full list of logs
* @param virtualHostName the virtualhostName to filter on
*
* @return the list of messages only for that virtualhost
*/
protected List<String> filterResultsByVirtualHost(List<String> results, String virtualHostName)
{
List<String> filteredResults = new LinkedList<String>();
Iterator<String> iterator = results.iterator();
while (iterator.hasNext())
{
String log = iterator.next();
if (AbstractTestLogSubject.getSlice("vh", log).equals(virtualHostName))
{
filteredResults.add(log);
}
}
return filteredResults;
}
/**
* Dump the log results.
*/
protected void dumpLogs(List<String> results) throws IOException
{
dumpLogs(results, null);
}
/**
* Dump the log results or if there are none, the contents of the
* monitored log file if the monitor is non-null.
*/
protected void dumpLogs(List<String> results, LogMonitor monitor) throws IOException
{
System.err.println("Log Dump:");
for (String log : results)
{
System.err.println(log);
}
if (results.isEmpty() && monitor != null)
{
System.err.println("Monitored file contents:");
System.err.println(monitor.readFile());
}
}
}