Author: ritchiem Date: Mon Aug 3 13:18:25 2009 New Revision: 800356 URL: http://svn.apache.org/viewvc?rev=800356&view=rev Log: 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.
Added: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java Removed: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/AlertingTest.java Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java?rev=800356&r1=800355&r2=800356&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java (original) +++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java Mon Aug 3 13:18:25 2009 @@ -256,7 +256,7 @@ // 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 @@ } } - 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 Added: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java?rev=800356&view=auto ============================================================================== --- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java (added) +++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java Mon Aug 3 13:18:25 2009 @@ -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(); + } + +} Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java?rev=800356&r1=800355&r2=800356&view=diff ============================================================================== --- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java (original) +++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java Mon Aug 3 13:18:25 2009 @@ -28,19 +28,31 @@ 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 @@ } } + + /** + * 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 @@ 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); --------------------------------------------------------------------- Apache Qpid - AMQP Messaging Implementation Project: http://qpid.apache.org Use/Interact: mailto:commits-subscr...@qpid.apache.org