/**
* Copyright 2006 by Know-Center, Graz, Austria
* PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
* joint initiative of the Federal Chancellery Austria and Graz University of
* Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*/
package at.knowcenter.wag.egov.egiz.cfg;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
/**
* Tests dealing with include-capable properties.
*
* @author Datentechnik Innovation GmbH
*/
public class NestedPropertiesTest {
@Test
public void testNoIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("config_noincludes.properties").getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = new FileInputStream(configFile));
} finally {
IOUtils.closeQuietly(in);
}
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testSingleIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("config_single_includes.properties")
.getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = getClass().getResourceAsStream("config_noincludes.properties"));
} finally {
IOUtils.closeQuietly(in);
}
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testSingleIncludesWithDefaultConfig() throws IOException {
// add some properties to a default configuration object
Properties defaultConfiguration = new Properties();
defaultConfiguration.put("key1", "defaultValue1");
defaultConfiguration.put("key2", "defaultValue2");
// set a property which will be locally overridden by config_single_includes.properties
defaultConfiguration.put("correct_document_on_verify_if_necessary", "false");
defaultConfiguration.put("sig_obj.types.INVISIBLE", "off");
File configFile = new File(NestedPropertiesTest.class.getResource("config_single_includes.properties")
.getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = getClass().getResourceAsStream("config_noincludes.properties"));
expectedProperties.put("key1", "defaultValue1");
expectedProperties.put("key2", "defaultValue2");
} finally {
IOUtils.closeQuietly(in);
}
// load include aware properties considering default configuration
NestedProperties nestedProperties = new NestedProperties(defaultConfiguration);
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testWildcardIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("config_wildcard_includes.properties")
.getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = getClass().getResourceAsStream("config_noincludes.properties"));
} finally {
IOUtils.closeQuietly(in);
}
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testNestedIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("config_nested_includes.properties")
.getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = getClass().getResourceAsStream("config_noincludes.properties"));
} finally {
IOUtils.closeQuietly(in);
}
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testSubdirIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("config_subdir_includes.properties")
.getFile());
Properties expectedProperties = new Properties();
InputStream in = null;
try {
expectedProperties.load(in = getClass().getResourceAsStream("config_noincludes.properties"));
} finally {
IOUtils.closeQuietly(in);
}
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
assertEquals(expectedProperties, nestedProperties);
}
@Test(timeout = 2500, expected = CircularIncludeException.class)
public void testCircularIncludes() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("circular/profile.1.properties").getFile());
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
fail("Circular references should have been detected.");
}
@Test
/**
* Tests include priority: Included properties should override locally set properties.
*/
public void testLocalVsIncludedProperties() throws IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("local_vs_included_properties.properties")
.getFile());
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
Properties expectedProperties = new Properties();
expectedProperties.put("key1", "included value 1");
expectedProperties.put("key2", "local value 2");
expectedProperties.put("key3", "local value 3");
expectedProperties.put("key4", "local value 4");
assertEquals(expectedProperties, nestedProperties);
}
@Test
public void testIncludeOrder() throws CircularIncludeException, IOException {
File configFile = new File(NestedPropertiesTest.class.getResource("include_order.properties").getFile());
NestedProperties nestedProperties = new NestedProperties();
nestedProperties.load(configFile);
Properties expectedProperties = new Properties();
expectedProperties.put("key1", "include_xyz");
expectedProperties.put("key2", "include_abc");
expectedProperties.put("key3", "include_3");
expectedProperties.put("key4", "include_2");
expectedProperties.put("key5", "include_1");
expectedProperties.put("key6", "include");
assertEquals(expectedProperties, nestedProperties);
}
/**
* Java default {@link Properties} does not provide equals and hashcode methods therefore default properties are not
* taken into consideration when comparing two Properties (using {@link Hashtable#equals(Object)}. This method
* compares two Properties considering defaults. Note that this method considers two Properties equal if the
* respective union of keys and default keys equals.
*
* @param expected
* The expected set of Properties.
* @param actual
* Properties to be compared with.
*/
private static void assertEquals(Properties expected, Properties actual) {
if (expected == actual) {
// same object
return;
}
if (expected == null || actual == null) {
fail("expected: <" + expected + "> but was <" + actual + ">");
}
// fetch all keys (including defaults) from actual properties
@SuppressWarnings("unchecked")
Enumeration actualPropertyNames = (Enumeration) actual.propertyNames();
Set actualKeys = new HashSet();
while (actualPropertyNames.hasMoreElements()) {
actualKeys.add(actualPropertyNames.nextElement());
}
@SuppressWarnings("unchecked")
Enumeration expectedPropertyNames = (Enumeration) expected.propertyNames();
while (expectedPropertyNames.hasMoreElements()) {
String key = expectedPropertyNames.nextElement();
String expectedValue = expected.getProperty(key);
if (!actualKeys.contains(key)) {
fail("missing entry for key '" + key + "'");
}
String actualValue = actual.getProperty(key);
if (!StringUtils.equals(expectedValue, actualValue)) {
fail("key '" + key + "' value expected: <" + expectedValue + "> but was <" + actualValue + ">");
}
actualKeys.remove(key);
}
if (!actualKeys.isEmpty()) {
fail("more entries found than expected: " + StringUtils.join(actualKeys, ", "));
}
}
}