diff options
| author | Martin Ritchie <ritchiem@apache.org> | 2009-08-03 13:18:25 +0000 |
|---|---|---|
| committer | Martin Ritchie <ritchiem@apache.org> | 2009-08-03 13:18:25 +0000 |
| commit | 1eba218ee48f01532072461147dcdfaaefa8efb9 (patch) | |
| tree | 0a9046a668ea6f6c7ea5dec3cb5fc6734cded266 /java | |
| parent | 4462f69cd4cf9be6111c61e350f80de4ec910c47 (diff) | |
| download | qpid-python-1eba218ee48f01532072461147dcdfaaefa8efb9.tar.gz | |
QPID-2011 : Updated AlertingTest to use new LogMonitoring class and corrected failures in test.
Failures corrected by:
- Ensuring message count is as expected after first publication
- Validating that the max count alert level is correctly changed (when InVM)
- Validate that the log file does not contain alerts after restart
- Validate that alerting occurs after extra messages have been published
- Modified QPID_WORK (using QTC.setSystemProperty so it is only set for that test run) to ensure each test has a clean store.
Additions to QpidTestCase:
- Ability to enable persistence on a given virtualhost. Currently it tries to set the JBoss BerkelyDB store failing back to Qpid's DerbyDB store.
- Ability to set properties in the configuration file, this involves re-writting the config files so that both inVM and external java brokers will correctly function with the desired configuration.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@800356 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java')
4 files changed, 352 insertions, 187 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index e56f1cda12..90b4590d4c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -256,7 +256,7 @@ public class ServerConfiguration implements SignalHandler // Our configuration class needs to make the interpolate method // public so it can be called below from the config method. - private static class MyConfiguration extends CompositeConfiguration + public static class MyConfiguration extends CompositeConfiguration { public String interpolate(String obj) { @@ -264,7 +264,7 @@ public class ServerConfiguration implements SignalHandler } } - private final static Configuration flatConfig(File file) throws ConfigurationException + public final static Configuration flatConfig(File file) throws ConfigurationException { // We have to override the interpolate methods so that // interpolation takes place accross the entirety of the diff --git a/java/systests/src/main/java/org/apache/qpid/server/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/AlertingTest.java deleted file mode 100644 index 205a741b2f..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/AlertingTest.java +++ /dev/null @@ -1,182 +0,0 @@ -/* -* -* 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; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; - -import javax.jms.Connection; -import javax.jms.MessageConsumer; -import javax.jms.Queue; -import javax.jms.Session; - -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.log4j.FileAppender; -import org.apache.log4j.Logger; -import org.apache.log4j.SimpleLayout; -import org.apache.qpid.server.store.DerbyMessageStore; -import org.apache.qpid.test.utils.QpidTestCase; - -public class AlertingTest extends QpidTestCase -{ - private String VIRTUALHOST = "test"; - private Session _session; - private Connection _connection; - private Queue _destination; - private MessageConsumer _consumer; // Never read, but does need to be here to create the destination. - private File _logfile; - private XMLConfiguration _configuration; - private int _numMessages; - - public void setUp() throws Exception - { - // First we munge the config file and, if we're in a VM, set up an additional logfile - - _configuration = new XMLConfiguration(_configFile); - _configuration.setProperty("management.enabled", "false"); - Class storeClass = DerbyMessageStore.class; - Class bdb = null; - try { - bdb = Class.forName("org.apache.qpid.store.berkleydb.BDBMessageStore"); - } - catch (ClassNotFoundException e) - { - // No BDB store, we'll use Derby instead. - } - if (bdb != null) - { - storeClass = bdb; - } - - _configuration.setProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".store.class", storeClass.getName()); - _numMessages = 50; - - File tmpFile = File.createTempFile("configFile", "test"); - tmpFile.deleteOnExit(); - _configuration.save(tmpFile); - _configFile = tmpFile; - - - if (_outputFile != null) - { - _logfile = _outputFile; - } - else - { - // This is mostly for running the test outside of the ant setup - _logfile = File.createTempFile("logFile", "test"); - FileAppender appender = new FileAppender(new SimpleLayout(), _logfile.getAbsolutePath()); - appender.setFile(_logfile.getAbsolutePath()); - appender.setImmediateFlush(true); - Logger.getRootLogger().addAppender(appender); - //_logfile.deleteOnExit(); - } - - // Then we do the normal setup stuff like starting the broker, getting a connection etc. - - super.setUp(); - - _connection = getConnection(); - _session = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); - _destination = _session.createQueue("testQueue"); - - // Consumer is only used to actually create the destination - _consumer = _session.createConsumer(_destination); - } - - /** - * Checks the log file for MESSAGE_COUNT_ALERT, fails() the test if it's not found and - * places the entire contents in the message to help debug cruise control failures. - * @throws Exception - */ - private void wasAlertFired() throws Exception - { - // Loop through alerts until we're done or 5 seconds have passed, - // just in case the logfile takes a while to flush. - BufferedReader reader = new BufferedReader(new FileReader(_logfile)); - boolean found = false; - long endtime = System.currentTimeMillis()+5000; - while (!found && System.currentTimeMillis() < endtime) - { - while (reader.ready()) - { - String line = reader.readLine(); - if (line.contains("MESSAGE_COUNT_ALERT")) - { - found = true; - } - } - } - if (!found) - { - StringBuffer message = new StringBuffer("Could not find alert in log file: "+_logfile.getAbsolutePath()); - message.append("\n"); - reader = new BufferedReader(new FileReader(_logfile)); - for (int i = 0; i < 79; i++) { message.append("-"); }; - message.append("\n"); - while (reader.ready()) { message.append(reader.readLine() + "\n");} - message.append("\n"); - for (int i = 0; i < 79; i++) { message.append("-"); }; - message.append("\n"); - fail(message.toString()); - } - } - - public void testAlertingReallyWorks() throws Exception - { - // Send 5 messages, make sure that the alert was fired properly. - sendMessage(_session, _destination, _numMessages + 1); - _session.commit(); - wasAlertFired(); - } - - public void testAlertingReallyWorksWithRestart() throws Exception - { - sendMessage(_session, _destination, _numMessages + 1); - _session.commit(); - stopBroker(); - (new FileOutputStream(_logfile)).getChannel().truncate(0); - startBroker(); - wasAlertFired(); - } - - public void testAlertingReallyWorksWithChanges() throws Exception - { - // send some messages and nuke the logs - sendMessage(_session, _destination, 2); - _session.commit(); - stopBroker(); - (new FileOutputStream(_logfile)).getChannel().truncate(0); - - // Change max message count to 5, start broker and make sure that that's triggered at the right time - _configuration.setProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", 5); - startBroker(); - _connection = getConnection(); - _session = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); - - // Trigger the new value - sendMessage(_session, _destination, 3); - _session.commit(); - wasAlertFired(); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java new file mode 100644 index 0000000000..f985530ca5 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -0,0 +1,207 @@ +/* +* +* 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.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; +import org.apache.qpid.util.LogMonitor; + +import javax.jms.Connection; +import javax.jms.Queue; +import javax.jms.Session; +import java.io.File; + +public class AlertingTest extends QpidTestCase +{ + private String VIRTUALHOST = "test"; + private Session _session; + private Connection _connection; + private Queue _destination; + private int _numMessages; + + private LogMonitor _monitor; + private static final int ALERT_LOG_WAIT_PERIOD = 5000; + private static final String MESSAGE_COUNT_ALERT = "MESSAGE_COUNT_ALERT"; + + public void setUp() throws Exception + { + // set QPID_WORK to be [QPID_WORK|io.tmpdir]/<testName> + // This ensures that each of these tests operate independantly. + setSystemProperty("QPID_WORK", + System.getProperty("QPID_WORK", + System.getProperty("java.io.tmpdir")) + + File.separator + getName()); + + // Update the configuration to make our virtualhost Persistent. + makeVirtualHostPersistent(VIRTUALHOST); + + //Create a log file monitor + _monitor = new LogMonitor(_outputFile); + + _numMessages = 50; + + // Then we do the normal setup stuff like starting the broker, getting a connection etc. + super.setUp(); + + setupConnection(); + } + + /** + * Create a new connection and ensure taht our destination queue is created + * and bound. + * + * Note that the tests here that restart the broker rely on persistence. + * However, the queue creation here is transient. So the queue will not be + * rebound on restart. Hence the consumer creation here rather than just the + * once. + * + * The persistent messages will recreate the queue but not bind it (as it + * was not a durable queue) However, the consumer creation here will ensure + * that the queue is correctly bound and can receive new messages. + * + * @throws Exception + */ + private void setupConnection() + throws Exception + { + _connection = getConnection(); + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _destination = _session.createQueue("testQueue"); + + // Consumer is only used to actually create the destination + _session.createConsumer(_destination).close(); + } + + /** + * Checks the log file for MESSAGE_COUNT_ALERT, fails() the test if it's not found and + * places the entire contents in the message to help debug cruise control failures. + * + * @throws Exception + */ + private void wasAlertFired() throws Exception + { + if (!_monitor.waitForMessage(MESSAGE_COUNT_ALERT, ALERT_LOG_WAIT_PERIOD)) + { + StringBuffer message = new StringBuffer("Could not find 'MESSAGE_COUNT_ALERT' in log file: " + _monitor.getMonitoredFile().getAbsolutePath()); + message.append("\n"); + + // Add the current contents of the log file to test output + message.append(_monitor.readFile()); + + // Write the server config file to test output + message.append("Server configuration file in use:\n"); + message.append(FileUtils.readFileAsString(_configFile)); + + // Write the virtualhost config file to test output + message.append("\nVirtualhost configuration file in use:\n"); + message.append(FileUtils.readFileAsString(ServerConfiguration. + flatConfig(_configFile).getString("virtualhosts"))); + + fail(message.toString()); + } + } + + public void testAlertingReallyWorks() throws Exception + { + // Send 5 messages, make sure that the alert was fired properly. + sendMessage(_session, _destination, _numMessages + 1); + _session.commit(); + wasAlertFired(); + } + + public void testAlertingReallyWorksWithRestart() throws Exception + { + sendMessage(_session, _destination, _numMessages + 1); + _session.commit(); + stopBroker(); + + // Rest the monitoring clearing the current output file. + _monitor.reset(); + startBroker(); + wasAlertFired(); + } + + /** + * Test that if the alert value is change from the previous value we can + * still get alerts. + * + * Test sends two messages to the broker then restarts the broker with new + * configuration. + * + * If the test is running inVM the test validates that the new configuration + * has been applied. + * + * Validates that we only have two messages on the queue and then sends + * enough messages to trigger the alert. + * + * The alert is then validate. + * + * + * @throws Exception + */ + public void testAlertingReallyWorksWithChanges() throws Exception + { + // send some messages and nuke the logs + sendMessage(_session, _destination, 2); + _session.commit(); + // To prevent any failover/retry/connection dropped errors + _connection.close(); + + stopBroker(); + + _monitor.reset(); + + // Change max message count to 5, start broker and make sure that that's triggered at the right time + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5"); + + startBroker(); + + if (!isExternalBroker()) + { + assertEquals("Alert Max Msg Count is not correct", 5, ApplicationRegistry.getInstance().getVirtualHostRegistry(). + getVirtualHost(VIRTUALHOST).getQueueRegistry().getQueue(new AMQShortString(_destination.getQueueName())). + getMaximumMessageCount()); + } + + setupConnection(); + + // Validate the queue depth is as expected + long messageCount = ((AMQSession) _session).getQueueDepth((AMQDestination) _destination); + assertEquals("Broker has invalid message count for test", 2, messageCount); + + // Ensure the alert has not occured yet + assertEquals("Alert has already occured", 0, + _monitor.findMatches(MESSAGE_COUNT_ALERT).size()); + + // Trigger the new value + sendMessage(_session, _destination, 3); + _session.commit(); + + // Validate that the alert occured. + wasAlertFired(); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 91732bc010..f3cf870c31 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -28,19 +28,31 @@ import javax.jms.Message; import javax.jms.JMSException; import javax.naming.InitialContext; import javax.naming.NamingException; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.PrintStream; +import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; -import java.util.StringTokenizer; import java.util.Map; import java.util.HashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.net.MalformedURLException; + + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.store.DerbyMessageStore; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.jms.BrokerDetails; @@ -490,6 +502,119 @@ public class QpidTestCase extends TestCase } } + + /** + * Attempt to set the Java Broker to use the BDBMessageStore for persistence + * Falling back to the DerbyMessageStore if + * + * @param virtualhost - The virtualhost to modify + * + * @throws ConfigurationException - when reading/writing existing configuration + * @throws IOException - When creating a temporary file. + */ + protected void makeVirtualHostPersistent(String virtualhost) + throws ConfigurationException, IOException + { + Class storeClass = DerbyMessageStore.class; + + Class bdb = null; + try + { + bdb = Class.forName("org.apache.qpid.store.berkleydb.BDBMessageStore"); + } + catch (ClassNotFoundException e) + { + // No BDB store, we'll use Derby instead. + } + + if (bdb != null) + { + storeClass = bdb; + } + + // First we munge the config file and, if we're in a VM, set up an additional logfile + XMLConfiguration configuration = new XMLConfiguration(_configFile); + configuration.setProperty("virtualhosts.virtualhost." + virtualhost + + ".store.class", storeClass.getName()); + configuration.setProperty("virtualhosts.virtualhost." + virtualhost + + ".store." + DerbyMessageStore.ENVIRONMENT_PATH_PROPERTY, + "${work}"); + + File tmpFile = File.createTempFile("configFile", "test"); + tmpFile.deleteOnExit(); + configuration.save(tmpFile); + _configFile = tmpFile; + } + + /** + * Set a configuration Property for this test run. + * + * This creates a new configuration based on the current configuration + * with the specified property change. + * + * Multiple calls to this method will result in multiple temporary + * configuration files being created. + * + * @param property the configuration property to set + * @param value the new value + * @throws ConfigurationException when loading the current config file + * @throws IOException when writing the new config file + */ + protected void setConfigurationProperty(String property, String value) + throws ConfigurationException, IOException + { + XMLConfiguration configuration = new XMLConfiguration(_configFile); + + // If we are modifying a virtualhost value then we need to do so in + // the virtualhost.xml file as these values overwrite the values in + // the main config.xml file + if (property.startsWith("virtualhosts")) + { + // So locate the virtualhost.xml file and use the ServerConfiguration + // flatConfig method to get the interpolated value. + String vhostConfigFile = ServerConfiguration. + flatConfig(_configFile).getString("virtualhosts"); + + // Load the vhostConfigFile + XMLConfiguration vhostConfiguration = new XMLConfiguration(vhostConfigFile); + + // Set the value specified in to the vhostConfig. + // Remembering that property will be 'virtualhosts.virtulhost....' + // so we need to take off the 'virtualhosts.' from the start. + vhostConfiguration.setProperty(property.substring(property.indexOf(".") + 1), value); + + // Write out the new virtualhost config file + File tmpFile = File.createTempFile("virtualhost-configFile", ".xml"); + tmpFile.deleteOnExit(); + vhostConfiguration.save(tmpFile); + + // Change the property and value to be the new virtualhosts file + // so that then update the value in the main config file. + property = "virtualhosts"; + value = tmpFile.getAbsolutePath(); + } + + configuration.setProperty(property, value); + + // Write the new server config file + File tmpFile = File.createTempFile("configFile", ".xml"); + tmpFile.deleteOnExit(); + configuration.save(tmpFile); + + _logger.info("Qpid Test Case now using configuration File:" + + tmpFile.getAbsolutePath()); + + _configFile = tmpFile; + } + + /** + * Set a System property for the duration of this test. + * + * When the test run is complete the value will be reverted. + + * @param property the property to set + * @param value the new value to use + */ protected void setSystemProperty(String property, String value) { if (!_setProperties.containsKey(property)) @@ -531,6 +656,21 @@ public class QpidTestCase extends TestCase return _brokerVersion.equals(VERSION_010); } + protected boolean isJavaBroker() + { + return _brokerLanguage.equals("java"); + } + + protected boolean isCppBroker() + { + return _brokerLanguage.equals("cpp"); + } + + protected boolean isExternalBroker() + { + return !_broker.equals("vm"); + } + public void restartBroker() throws Exception { restartBroker(0); |
