blob: 21612461ba128a15634d9fc91dadbc1aa53fe8a9 [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.commons.configuration;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy;
import org.apache.commons.configuration.reloading.FileRandomReloadingStrategy;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.NodeCombiner;
import org.apache.commons.configuration.tree.OverrideCombiner;
import org.apache.commons.configuration.tree.UnionCombiner;
import org.apache.commons.configuration.tree.MergeCombiner;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
/**
* Test class for CombinedConfiguration.
*
* @version $Id$
*/
public class TestCombinedConfiguration extends TestCase
{
/** Constant for the name of a sub configuration. */
private static final String TEST_NAME = "SUBCONFIG";
/** Constant for a test key. */
private static final String TEST_KEY = "test.value";
/** Constant for the name of the first child configuration.*/
private static final String CHILD1 = TEST_NAME + "1";
/** Constant for the name of the second child configuration.*/
private static final String CHILD2 = TEST_NAME + "2";
/** Constant for the name of the XML reload test file.*/
private static final String RELOAD_XML_NAME = "reload.xml";
/** Constant for the content of a XML reload test file.*/
private static final String RELOAD_XML_CONTENT = "<xml><xmlReload>{0}</xmlReload></xml>";
/** Constant for the name of the properties reload test file.*/
private static final String RELOAD_PROPS_NAME = "reload.properties";
/** Constant for the content of a properties reload test file.*/
private static final String RELOAD_PROPS_CONTENT = "propsReload = {0}";
/** Constant for the directory for writing test files.*/
private static final File TEST_DIR = new File("target");
/** A list with files created during a test.*/
private Collection testFiles;
/** The configuration to be tested. */
private CombinedConfiguration config;
/** The test event listener. */
private CombinedListener listener;
protected void setUp() throws Exception
{
super.setUp();
config = new CombinedConfiguration();
listener = new CombinedListener();
config.addConfigurationListener(listener);
}
/**
* Performs clean-up after a test run. If test files have been created, they
* are removed now.
*/
protected void tearDown() throws Exception
{
if (testFiles != null)
{
for (Iterator it = testFiles.iterator(); it.hasNext();)
{
File f = (File) it.next();
if (f.exists())
{
assertTrue("Cannot delete test file: " + f, f.delete());
}
}
}
}
/**
* Tests accessing a newly created combined configuration.
*/
public void testInit()
{
assertEquals("Already configurations contained", 0, config
.getNumberOfConfigurations());
assertTrue("Set of names is not empty", config.getConfigurationNames()
.isEmpty());
assertTrue("Wrong node combiner",
config.getNodeCombiner() instanceof UnionCombiner);
assertNull("Test config was found", config.getConfiguration(TEST_NAME));
assertFalse("Force reload check flag is set", config.isForceReloadCheck());
}
/**
* Tests adding a configuration (without further information).
*/
public void testAddConfiguration()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c);
checkAddConfig(c);
assertEquals("Wrong number of configs", 1, config
.getNumberOfConfigurations());
assertTrue("Name list is not empty", config.getConfigurationNames()
.isEmpty());
assertSame("Added config not found", c, config.getConfiguration(0));
assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
listener.checkEvent(1, 0);
}
/**
* Tests adding a configuration with a name.
*/
public void testAddConfigurationWithName()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, TEST_NAME);
checkAddConfig(c);
assertEquals("Wrong number of configs", 1, config
.getNumberOfConfigurations());
assertSame("Added config not found", c, config.getConfiguration(0));
assertSame("Added config not found by name", c, config
.getConfiguration(TEST_NAME));
Set names = config.getConfigurationNames();
assertEquals("Wrong number of config names", 1, names.size());
assertTrue("Name not found", names.contains(TEST_NAME));
assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
listener.checkEvent(1, 0);
}
/**
* Tests adding a configuration with a name when this name already exists.
* This should cause an exception.
*/
public void testAddConfigurationWithNameTwice()
{
config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
try
{
config.addConfiguration(setUpTestConfiguration(), TEST_NAME,
"prefix");
fail("Could add config with same name!");
}
catch (ConfigurationRuntimeException cex)
{
// ok
}
}
/**
* Tests adding a configuration and specifying an at position.
*/
public void testAddConfigurationAt()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, null, "my");
checkAddConfig(c);
assertTrue("Wrong property value", config.getBoolean("my." + TEST_KEY));
}
/**
* Tests adding a configuration with a complex at position. Here the at path
* contains a dot, which must be escaped.
*/
public void testAddConfigurationComplexAt()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, null, "This..is.a.complex");
checkAddConfig(c);
assertTrue("Wrong property value", config
.getBoolean("This..is.a.complex." + TEST_KEY));
}
/**
* Checks if a configuration was correctly added to the combined config.
*
* @param c the config to check
*/
private void checkAddConfig(AbstractConfiguration c)
{
Collection listeners = c.getConfigurationListeners();
assertEquals("Wrong number of configuration listeners", 1, listeners
.size());
assertTrue("Combined config is no listener", listeners.contains(config));
}
/**
* Tests adding a null configuration. This should cause an exception to be
* thrown.
*/
public void testAddNullConfiguration()
{
try
{
config.addConfiguration(null);
fail("Could add null configuration!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests accessing properties if no configurations have been added.
*/
public void testAccessPropertyEmpty()
{
assertFalse("Found a key", config.containsKey(TEST_KEY));
assertNull("Key has a value", config.getString("test.comment"));
assertTrue("Config is not empty", config.isEmpty());
}
/**
* Tests accessing properties if multiple configurations have been added.
*/
public void testAccessPropertyMulti()
{
config.addConfiguration(setUpTestConfiguration());
config.addConfiguration(setUpTestConfiguration(), null, "prefix1");
config.addConfiguration(setUpTestConfiguration(), null, "prefix2");
assertTrue("Prop1 not found", config.getBoolean(TEST_KEY));
assertTrue("Prop 2 not found", config.getBoolean("prefix1." + TEST_KEY));
assertTrue("Prop 3 not found", config.getBoolean("prefix2." + TEST_KEY));
assertFalse("Configuration is empty", config.isEmpty());
listener.checkEvent(3, 0);
}
/**
* Tests removing a configuration.
*/
public void testRemoveConfiguration()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c);
checkAddConfig(c);
assertTrue("Config could not be removed", config.removeConfiguration(c));
checkRemoveConfig(c);
}
/**
* Tests removing a configuration by index.
*/
public void testRemoveConfigurationAt()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c);
assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
checkRemoveConfig(c);
}
/**
* Tests removing a configuration by name.
*/
public void testRemoveConfigurationByName()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, TEST_NAME);
assertSame("Wrong config removed", c, config
.removeConfiguration(TEST_NAME));
checkRemoveConfig(c);
}
/**
* Tests removing a configuration with a name.
*/
public void testRemoveNamedConfiguration()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, TEST_NAME);
config.removeConfiguration(c);
checkRemoveConfig(c);
}
/**
* Tests removing a named configuration by index.
*/
public void testRemoveNamedConfigurationAt()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c, TEST_NAME);
assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
checkRemoveConfig(c);
}
/**
* Tests removing a configuration that was not added prior.
*/
public void testRemoveNonContainedConfiguration()
{
assertFalse("Could remove non contained config", config
.removeConfiguration(setUpTestConfiguration()));
listener.checkEvent(0, 0);
}
/**
* Tests removing a configuration by name, which is not contained.
*/
public void testRemoveConfigurationByUnknownName()
{
assertNull("Could remove configuration by unknown name", config
.removeConfiguration("unknownName"));
listener.checkEvent(0, 0);
}
/**
* Tests whether a configuration was completely removed.
*
* @param c the removed configuration
*/
private void checkRemoveConfig(AbstractConfiguration c)
{
assertTrue("Listener was not removed", c.getConfigurationListeners()
.isEmpty());
assertEquals("Wrong number of contained configs", 0, config
.getNumberOfConfigurations());
assertTrue("Name was not removed", config.getConfigurationNames()
.isEmpty());
listener.checkEvent(2, 0);
}
/**
* Tests if an update of a contained configuration leeds to an invalidation
* of the combined configuration.
*/
public void testUpdateContainedConfiguration()
{
AbstractConfiguration c = setUpTestConfiguration();
config.addConfiguration(c);
c.addProperty("test.otherTest", "yes");
assertEquals("New property not found", "yes", config
.getString("test.otherTest"));
listener.checkEvent(2, 0);
}
/**
* Tests if setting a node combiner causes an invalidation.
*/
public void testSetNodeCombiner()
{
NodeCombiner combiner = new UnionCombiner();
config.setNodeCombiner(combiner);
assertSame("Node combiner was not set", combiner, config
.getNodeCombiner());
listener.checkEvent(1, 0);
}
/**
* Tests setting a null node combiner. This should cause an exception.
*/
public void testSetNullNodeCombiner()
{
try
{
config.setNodeCombiner(null);
fail("Could set null node combiner!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests cloning a combined configuration.
*/
public void testClone()
{
config.addConfiguration(setUpTestConfiguration());
config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
config.addConfiguration(new PropertiesConfiguration(), "props");
CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
assertEquals("Wrong number of contained configurations", config
.getNumberOfConfigurations(), cc2.getNumberOfConfigurations());
assertSame("Wrong node combiner", config.getNodeCombiner(), cc2
.getNodeCombiner());
assertEquals("Wrong number of names", config.getConfigurationNames()
.size(), cc2.getConfigurationNames().size());
assertTrue("Event listeners were cloned", cc2
.getConfigurationListeners().isEmpty());
StrictConfigurationComparator comp = new StrictConfigurationComparator();
for (int i = 0; i < config.getNumberOfConfigurations(); i++)
{
assertNotSame("Configuration at " + i + " was not cloned", config
.getConfiguration(i), cc2.getConfiguration(i));
assertEquals("Wrong config class at " + i, config.getConfiguration(
i).getClass(), cc2.getConfiguration(i).getClass());
assertTrue("Configs not equal at " + i, comp.compare(config
.getConfiguration(i), cc2.getConfiguration(i)));
}
assertTrue("Combined configs not equal", comp.compare(config, cc2));
}
/**
* Tests if the cloned configuration is decoupled from the original.
*/
public void testCloneModify()
{
config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
assertTrue("Name is missing", cc2.getConfigurationNames().contains(
TEST_NAME));
cc2.removeConfiguration(TEST_NAME);
assertFalse("Names in original changed", config.getConfigurationNames()
.isEmpty());
}
/**
* Tests clearing a combined configuration. This should remove all contained
* configurations.
*/
public void testClear()
{
config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "test");
config.addConfiguration(setUpTestConfiguration());
config.clear();
assertEquals("Still configs contained", 0, config
.getNumberOfConfigurations());
assertTrue("Still names contained", config.getConfigurationNames()
.isEmpty());
assertTrue("Config is not empty", config.isEmpty());
listener.checkEvent(3, 2);
}
/**
* Tests if file-based configurations can be reloaded.
*/
public void testReloading() throws Exception
{
config.setForceReloadCheck(true);
File testXmlFile = writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 0);
File testPropsFile = writeReloadFile(RELOAD_PROPS_NAME, RELOAD_PROPS_CONTENT, 0);
XMLConfiguration c1 = new XMLConfiguration(testXmlFile);
c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
PropertiesConfiguration c2 = new PropertiesConfiguration(testPropsFile);
c2.setThrowExceptionOnMissing(true);
c2.setReloadingStrategy(new FileAlwaysReloadingStrategy());
config.addConfiguration(c1);
config.addConfiguration(c2);
assertEquals("Wrong xml reload value", 0, config.getInt("xmlReload"));
assertEquals("Wrong props reload value", 0, config
.getInt("propsReload"));
writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 1);
assertEquals("XML reload not detected", 1, config.getInt("xmlReload"));
config.setForceReloadCheck(false);
writeReloadFile(RELOAD_PROPS_NAME, RELOAD_PROPS_CONTENT, 1);
assertEquals("Props reload detected though check flag is false", 0, config
.getInt("propsReload"));
}
/**
* Tests whether the reload check works with a subnode configuration. This
* test is related to CONFIGURATION-341.
*/
public void testReloadingSubnodeConfig() throws IOException,
ConfigurationException
{
config.setForceReloadCheck(true);
File testXmlFile = writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT,
0);
XMLConfiguration c1 = new XMLConfiguration(testXmlFile);
c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
final String prefix = "reloadCheck";
config.addConfiguration(c1, CHILD1, prefix);
SubnodeConfiguration sub = config.configurationAt(prefix, true);
writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 1);
assertEquals("Reload not detected", 1, sub.getInt("xmlReload"));
}
/**
* Prepares a test of the getSource() method.
*/
private void setUpSourceTest()
{
HierarchicalConfiguration c1 = new HierarchicalConfiguration();
PropertiesConfiguration c2 = new PropertiesConfiguration();
c1.addProperty(TEST_KEY, TEST_NAME);
c2.addProperty("another.key", "test");
config.addConfiguration(c1, CHILD1);
config.addConfiguration(c2, CHILD2);
}
/**
* Tests the gestSource() method when the source property is defined in a
* hierarchical configuration.
*/
public void testGetSourceHierarchical()
{
setUpSourceTest();
assertEquals("Wrong source configuration", config
.getConfiguration(CHILD1), config.getSource(TEST_KEY));
}
/**
* Tests whether the source configuration can be detected for non
* hierarchical configurations.
*/
public void testGetSourceNonHierarchical()
{
setUpSourceTest();
assertEquals("Wrong source configuration", config
.getConfiguration(CHILD2), config.getSource("another.key"));
}
/**
* Tests the getSource() method when the passed in key is not contained.
* Result should be null in this case.
*/
public void testGetSourceUnknown()
{
setUpSourceTest();
assertNull("Wrong result for unknown key", config
.getSource("an.unknown.key"));
}
/**
* Tests the getSource() method when a null key is passed in. This should
* cause an exception.
*/
public void testGetSourceNull()
{
try
{
config.getSource(null);
fail("Could resolve source for null key!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests the getSource() method when the passed in key belongs to the
* combined configuration itself.
*/
public void testGetSourceCombined()
{
setUpSourceTest();
final String key = "yet.another.key";
config.addProperty(key, Boolean.TRUE);
assertEquals("Wrong source for key", config, config.getSource(key));
}
/**
* Tests the getSource() method when the passed in key refers to multiple
* values, which are all defined in the same source configuration.
*/
public void testGetSourceMulti()
{
setUpSourceTest();
final String key = "list.key";
config.getConfiguration(CHILD1).addProperty(key, "1,2,3");
assertEquals("Wrong source for multi-value property", config
.getConfiguration(CHILD1), config.getSource(key));
}
/**
* Tests the getSource() method when the passed in key refers to multiple
* values defined by different sources. This should cause an exception.
*/
public void testGetSourceMultiSources()
{
setUpSourceTest();
final String key = "list.key";
config.getConfiguration(CHILD1).addProperty(key, "1,2,3");
config.getConfiguration(CHILD2).addProperty(key, "a,b,c");
try
{
config.getSource(key);
fail("Multiple sources not detected!");
}
catch (IllegalArgumentException iex)
{
//ok
}
}
/**
* Tests whether escaped list delimiters are treated correctly.
*/
public void testEscapeListDelimiters()
{
PropertiesConfiguration sub = new PropertiesConfiguration();
sub.addProperty("test.pi", "3\\,1415");
config.addConfiguration(sub);
assertEquals("Wrong value", "3,1415", config.getString("test.pi"));
}
/**
* Tests whether an invalidate event is fired only after a change. This test
* is related to CONFIGURATION-315.
*/
public void testInvalidateAfterChange()
{
ConfigurationEvent event = new ConfigurationEvent(config, 0, null,
null, true);
config.configurationChanged(event);
assertEquals("Invalidate event fired", 0, listener.invalidateEvents);
event = new ConfigurationEvent(config, 0, null, null, false);
config.configurationChanged(event);
assertEquals("No invalidate event fired", 1, listener.invalidateEvents);
}
/**
* Tests using a conversion expression engine for child configurations with
* strange keys. This test is related to CONFIGURATION-336.
*/
public void testConversionExpressionEngine()
{
PropertiesConfiguration child = new PropertiesConfiguration();
child.addProperty("test(a)", "1,2,3");
config.addConfiguration(child);
DefaultExpressionEngine engineQuery = new DefaultExpressionEngine();
engineQuery.setIndexStart("<");
engineQuery.setIndexEnd(">");
config.setExpressionEngine(engineQuery);
DefaultExpressionEngine engineConvert = new DefaultExpressionEngine();
engineConvert.setIndexStart("[");
engineConvert.setIndexEnd("]");
config.setConversionExpressionEngine(engineConvert);
assertEquals("Wrong property 1", "1", config.getString("test(a)<0>"));
assertEquals("Wrong property 2", "2", config.getString("test(a)<1>"));
assertEquals("Wrong property 3", "3", config.getString("test(a)<2>"));
}
/**
* Tests whether reload operations can cause a deadlock when the combined
* configuration is accessed concurrently. This test is related to
* CONFIGURATION-344.
*/
public void testDeadlockWithReload() throws ConfigurationException,
InterruptedException
{
final PropertiesConfiguration child = new PropertiesConfiguration(
"test.properties");
child.setReloadingStrategy(new FileAlwaysReloadingStrategy());
config.addConfiguration(child);
final int count = 1000;
class ReloadThread extends Thread
{
boolean error = false;
public void run()
{
for (int i = 0; i < count && !error; i++)
{
try
{
if (!child.getBoolean("configuration.loaded"))
{
error = true;
}
}
catch (NoSuchElementException nsex)
{
error = true;
}
}
}
}
ReloadThread reloadThread = new ReloadThread();
reloadThread.start();
for (int i = 0; i < count; i++)
{
assertEquals("Wrong value of combined property", 10, config
.getInt("test.integer"));
}
reloadThread.join();
assertFalse("Failure in thread", reloadThread.error);
}
public void testGetConfigurations() throws Exception
{
config.addConfiguration(setUpTestConfiguration());
config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
AbstractConfiguration pc = new PropertiesConfiguration();
config.addConfiguration(pc, "props");
List list = config.getConfigurations();
assertNotNull("No list of configurations returned", list);
assertTrue("Incorrect number of configurations", list.size() == 3);
AbstractConfiguration c = ((AbstractConfiguration)list.get(2));
assertTrue("Incorrect configuration", c == pc);
}
public void testGetConfigurationNameList() throws Exception
{
config.addConfiguration(setUpTestConfiguration());
config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
AbstractConfiguration pc = new PropertiesConfiguration();
config.addConfiguration(pc, "props");
List list = config.getConfigurationNameList();
assertNotNull("No list of configurations returned", list);
assertTrue("Incorrect number of configurations", list.size() == 3);
String name = ((String)list.get(1));
assertNotNull("No name returned", name);
assertTrue("Incorrect configuration name", TEST_NAME.equals(name));
}
/**
* Tests whether changes on a sub node configuration that is part of a
* combined configuration are detected. This test is related to
* CONFIGURATION-368.
*/
public void testReloadWithSubNodeConfig() throws Exception
{
final String reloadContent = "<config><default><xmlReload1>{0}</xmlReload1></default></config>";
config.setForceReloadCheck(true);
config.setNodeCombiner(new OverrideCombiner());
File testXmlFile1 = writeReloadFile(RELOAD_XML_NAME, reloadContent, 0);
final String prefix1 = "default";
XMLConfiguration c1 = new XMLConfiguration(testXmlFile1);
SubnodeConfiguration sub1 = c1.configurationAt(prefix1, true);
assertEquals("Inital test for sub config 1 failed", 0, sub1
.getInt("xmlReload1"));
config.addConfiguration(sub1);
assertEquals(
"Could not get value for sub config 1 from combined config", 0,
config.getInt("xmlReload1"));
c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
writeReloadFile(RELOAD_XML_NAME, reloadContent, 1);
assertEquals("Reload of sub config 1 not detected", 1, config
.getInt("xmlReload1"));
}
public void testConcurrentGetAndReload() throws Exception
{
final int threadCount = 5;
final int loopCount = 1000;
config.setForceReloadCheck(true);
config.setNodeCombiner(new MergeCombiner());
final XMLConfiguration xml = new XMLConfiguration("configA.xml");
xml.setReloadingStrategy(new FileRandomReloadingStrategy());
config.addConfiguration(xml);
final XMLConfiguration xml2 = new XMLConfiguration("configB.xml");
xml2.setReloadingStrategy(new FileRandomReloadingStrategy());
config.addConfiguration(xml2);
config.setExpressionEngine(new XPathExpressionEngine());
assertEquals(config.getString("/property[@name='config']/@value"), "100");
Thread testThreads[] = new Thread[threadCount];
int failures[] = new int[threadCount];
for (int i = 0; i < testThreads.length; ++i)
{
testThreads[i] = new ReloadThread(config, failures, i, loopCount);
testThreads[i].start();
}
int totalFailures = 0;
for (int i = 0; i < testThreads.length; ++i)
{
testThreads[i].join();
totalFailures += failures[i];
}
assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
}
private class ReloadThread extends Thread
{
CombinedConfiguration combined;
int[] failures;
int index;
int count;
ReloadThread(CombinedConfiguration config, int[] failures, int index, int count)
{
combined = config;
this.failures = failures;
this.index = index;
this.count = count;
}
public void run()
{
failures[index] = 0;
for (int i = 0; i < count; i++)
{
try
{
String value = combined.getString("/property[@name='config']/@value");
if (value == null || !value.equals("100"))
{
++failures[index];
}
}
catch (Exception ex)
{
++failures[index];
}
}
}
}
/**
* Helper method for writing a file. The file is also added to a list and
* will be deleted in teadDown() automatically.
*
* @param file the file to be written
* @param content the file's content
* @throws IOException if an error occurs
*/
private void writeFile(File file, String content) throws IOException
{
PrintWriter out = null;
try
{
out = new PrintWriter(new FileWriter(file));
out.print(content);
if (testFiles == null)
{
testFiles = new ArrayList();
}
testFiles.add(file);
}
finally
{
if (out != null)
{
out.close();
}
}
}
/**
* Helper method for writing a test file. The file will be created in the
* test directory. It is also scheduled for automatic deletion after the
* test.
*
* @param fileName the name of the test file
* @param content the content of the file
* @return the <code>File</code> object for the test file
* @throws IOException if an error occurs
*/
private File writeFile(String fileName, String content) throws IOException
{
File file = new File(TEST_DIR, fileName);
writeFile(file, content);
return file;
}
/**
* Writes a file for testing reload operations.
*
* @param name the name of the reload test file
* @param content the content of the file
* @param value the value of the reload test property
* @return the file that was written
* @throws IOException if an error occurs
*/
private File writeReloadFile(String name, String content, int value)
throws IOException
{
return writeFile(name, MessageFormat.format(content, new Object[] {
new Integer(value)
}));
}
/**
* Helper method for creating a test configuration to be added to the
* combined configuration.
*
* @return the test configuration
*/
private AbstractConfiguration setUpTestConfiguration()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
config.addProperty(TEST_KEY, Boolean.TRUE);
config.addProperty("test.comment", "This is a test");
return config;
}
/**
* Test event listener class for checking if the expected invalidate events
* are fired.
*/
static class CombinedListener implements ConfigurationListener
{
int invalidateEvents;
int otherEvents;
public void configurationChanged(ConfigurationEvent event)
{
if (event.getType() == CombinedConfiguration.EVENT_COMBINED_INVALIDATE)
{
invalidateEvents++;
}
else
{
otherEvents++;
}
}
/**
* Checks if the expected number of events was fired.
*
* @param expectedInvalidate the expected number of invalidate events
* @param expectedOthers the expected number of other events
*/
public void checkEvent(int expectedInvalidate, int expectedOthers)
{
Assert.assertEquals("Wrong number of invalidate events",
expectedInvalidate, invalidateEvents);
Assert.assertEquals("Wrong number of other events", expectedOthers,
otherEvents);
}
}
}