/**********************************************************************************
*
* $Id: ConfigurationLoadingTest.java 122214 2013-04-04 20:50:04Z azeckoski@unicon.net $
*
***********************************************************************************
*
* Copyright (c) 2007, 2008 Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.component.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.extensions.TestSetup;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.test.SakaiKernelTestBase;
/**
*
*/
public class ConfigurationLoadingTest extends SakaiKernelTestBase {
private static Log log = LogFactory.getLog(ConfigurationLoadingTest.class);
private ServerConfigurationService serverConfigurationService;
protected static final String CONFIG = "src/test/webapp/WEB-INF/components.xml";
public static Test suite() {
TestSetup setup = new TestSetup(new TestSuite(ConfigurationLoadingTest.class)) {
protected void setUp() throws Exception {
try {
oneTimeSetup("filesystem", CONFIG);
} catch (Exception e) {
log.warn(e);
}
}
protected void tearDown() throws Exception {
oneTimeTearDown();
}
};
return setup;
}
public void setUp() throws Exception {
serverConfigurationService = (ServerConfigurationService)getService(ServerConfigurationService.class.getName());
}
public void testSakaiProperties() throws Exception {
// Check that the test sakai-configuration.xml and sakai.properties files have been loaded.
Assert.assertTrue(serverConfigurationService.getString("loadedTomcatSakaiProperties").equals("true"));
Assert.assertTrue(serverConfigurationService.getString("kernel.test.key").equals("kernel"));
ITestComponent testComponent = (ITestComponent)getService(ITestComponent.class.getName());
Assert.assertTrue(testComponent.getOverrideString1().equals("nondefault"));
Assert.assertTrue(testComponent.getPlaceholderString1().equals("nondefault"));
if (log.isDebugEnabled()) log.debug("serverId=" + testComponent.getServerId());
String testBean = (String)getService("org.sakaiproject.component.test.String");
Assert.assertTrue(testBean.equals("local"));
ITestProvider testProvider = (ITestProvider)getService(ITestProvider.class.getName());
Assert.assertTrue(testProvider.getProviderName().equals("provider2"));
Assert.assertTrue(testComponent.getListOverride1().size() == 3);
Assert.assertTrue(testComponent.getListOverride1().get(0).equals("nondefault1"));
Assert.assertTrue(testComponent.getMapOverride1().size() == 3);
Assert.assertTrue(testComponent.getMapOverride1().get("key1").equals("nondefault1"));
// Test for use of a local properties file other than sakai.properties.
String[] stringArrayPlaceholder1 = testComponent.getStringArrayPlaceholder1();
Assert.assertTrue(stringArrayPlaceholder1.length == 4);
Assert.assertTrue(stringArrayPlaceholder1[0].equals("peculiar1"));
// Test for promotion of certain Sakai properties to system properties.
String uploadMax = System.getProperty("sakai.content.upload.max");
Assert.assertTrue(uploadMax.equals("5"));
// Test that an untouched component-defined alias came through.
// <alias name="org.sakaiproject.component.test.ITestComponent" alias="testAliasRetention"/>
Object aliasedObject = getService("testAliasRetention");
Assert.assertTrue(aliasedObject instanceof ITestComponent);
}
public void testStringHandling() throws Exception {
/*
stringSetToValue=value
stringIsEmpty=
#stringNotSet=
*/
String s;
String defaultS = "DEFAULT";
s = serverConfigurationService.getString("stringSetToValue");
assertNotNull(s);
assertEquals("value", s);
s = serverConfigurationService.getString("stringIsEmpty");
assertNull(s);
//assertEquals("", s);
s = serverConfigurationService.getString("stringNotSet");
assertNotNull(s);
assertEquals("", s);
s = serverConfigurationService.getString("stringSetToValue", defaultS);
assertNotNull(s);
assertEquals("value", s);
s = serverConfigurationService.getString("stringIsEmpty", defaultS);
assertNull(s);
//assertEquals(defaultS, s);
s = serverConfigurationService.getString("stringNotSet", defaultS);
assertNotNull(s);
assertEquals(defaultS, s);
}
/**
* As implemented (configured, actually), verifies that property placeholders are
* dereferenced recursively. I.e. the property retrieved references another property,
* which references another, and so on. Presumably simpler scenarios work implicitly.
*/
public void testGetStringDereferencesPlaceholderPropertiesForSimpleProperties() {
assertEquals("Property value for \"stringWithNestedPlaceholders\" not dereferenced",
"str1-str2-str3", serverConfigurationService.getString("stringWithNestedPlaceholders"));
}
/**
* Verifies that property placeholder dereferencing works as usual, even for properties
* having the special Sakai bean addressing syntax (propertyName@beanName). Note that this
* does not test bean property injection, only that these properties are given the
* same treatment as "simple" properties when accessed via
* {@link ServerConfigurationService#getString(String)}.
*/
public void testGetStringDereferencesPlaceholderPropertiesForBeanAddressingProperties() {
assertEquals("Property value for \"overrideString1@org.sakaiproject.component.test.ITestComponent2\" not dereferenced",
"str1-str2-str3", serverConfigurationService.getString("overrideString1@org.sakaiproject.component.test.ITestComponent2"));
}
/**
* Verifies that multi-valued parsing is working properly. There are two
* syntaxes that work: 1) traditional ".count" and ".1", ".2", etc., values,
* and 2) Comma-separated values directly on a property.
*/
public void testMultipleStrings() {
String[] countAndList = serverConfigurationService.getStrings("stringCountAndList");
assertEquals("Property with count not loaded properly.", 3, countAndList.length);
assertEquals("Property with count should not parse CSV", "this,will,not,split", countAndList[0]);
String splitError = "CSV strings should be split";
String[] stringList = serverConfigurationService.getStrings("stringList");
assertEquals(splitError, 3, stringList.length);
assertEquals(splitError, "this", stringList[0]);
assertEquals(splitError, "should", stringList[1]);
assertEquals(splitError, "split", stringList[2]);
String[] stringCsv = serverConfigurationService.getStrings("stringCsv");
assertEquals(splitError, 3, stringCsv.length);
assertEquals(splitError, "this", stringCsv[0]);
assertEquals(splitError, "should", stringCsv[1]);
assertEquals(splitError, "split", stringCsv[2]);
String[] stringMixedCsv = serverConfigurationService.getStrings("stringMixedCsv");
assertEquals(splitError, 3, stringMixedCsv.length);
assertEquals(splitError, "this", stringMixedCsv[0]);
assertEquals(splitError, "should", stringMixedCsv[1]);
assertEquals(splitError, "also,split", stringMixedCsv[2]);
String[] strings = serverConfigurationService.getStrings("stringLonelyCsv");
assertEquals(splitError, 1, strings.length);
assertEquals(splitError, "alone", strings[0]);
String invalidStr = serverConfigurationService.getString("stringInvalidCsv");
assertNotNull(invalidStr);
assertEquals("\"this\",\"is\",\"invalid", invalidStr);
String[] invalid = serverConfigurationService.getStrings("stringInvalidCsv");
assertNull(invalid);
// KNL-1032 - stringCountEmptyList, stringEmptyList
String[] stringsEmpty = serverConfigurationService.getStrings("stringCountEmptyList");
assertNotNull(stringsEmpty);
assertEquals(0, stringsEmpty.length);
stringsEmpty = serverConfigurationService.getStrings("stringEmptyList");
assertNotNull(stringsEmpty);
assertEquals(0, stringsEmpty.length);
// also quickly verify non-existent works correctly
String[] stringsNotExists = serverConfigurationService.getStrings("stringsNotExistsInTheConfigAnywhereXXXXXXXXXXXXXX");
assertNull(stringsNotExists);
}
/**
* Verifies that property placeholders are dereferenced appropriately for special
* "enumerated" properties.
*
* An example of a set of "enumerated" properties without any placeholder values:
*
* <p>
* <code>
* property.name.count=2
* property.name.1=val1
* property.name.2=val2
* </pre>
* </p>
*
* <p>Requesting the value of <code>property.name</code> will result in an array containing
* the values of <code>property.name.1</code> and <code>property.name.2</code></p>
*
* <p>As implemented (configured, actually), this test includes verifies that the property
* count value is correctly dereferenced.</p>
*/
public void testGetStringsDereferencesPlaceholderProperties() {
String[] expected = new String[] { "str1", "str1-str2", "str1-str2-str3" };
String[] actual = serverConfigurationService.getStrings("stringPlaceholderProps");
assertTrue("Expected \"stringPlaceholderProps.*\" property values in an array matching " + Arrays.toString(expected) + ", but was " + Arrays.toString(actual),
Arrays.equals(expected, actual));
}
/**
* Verifies that property placeholder dereferencing works when Sakai "promotes" certain
* properties into the system scope.
*/
public void testPropertyPromotionDereferencesPlaceholderProperties() {
assertEquals("Property value for \"content.upload.dir\" not dereferenced or not placed into \"sakai.content.upload.dir\" system property",
"/str1-str2-str3", System.getProperty("sakai.content.upload.dir"));
}
/**
* When combined with {@link #testGetStringDereferencesPlaceholderPropertiesForSimpleProperties()},
* ensures symmetry between bean property placeholder dereferencing and getters on
* {@link ServerConfigurationService}.
*
* @see #testStringArrayBeanPropertyOverridingDereferencesPlaceholderProperties()
*/
public void testBeanStringPropertyPlaceholderDereferencingRecursivelyDereferencesPlaceholderProperties() {
ITestComponent testComponent = (ITestComponent)getService(ITestComponent.class.getName() + "2");
assertEquals("Bean property placeholder ${stringWithNestedPlaceholders} not dereferenced",
"str1-str2-str3", testComponent.getPlaceholderString1());
}
/**
* When combined with {@link #testGetStringDereferencesPlaceholderPropertiesForBeanAddressingProperties()},
* ensures symmetry between bean property override behaviors and getters on
* {@link ServerConfigurationService}.
*/
public void testBeanStringPropertyOverridingDereferencesPlaceholderProperties() {
ITestComponent testComponent = (ITestComponent)getService(ITestComponent.class.getName() + "2");
assertEquals("Property value not dereferenced when overriding bean string property \"overrideString1\"",
"str1-str2-str3", testComponent.getOverrideString1());
}
/**
* Verifies that property dereferencing works as usual even for the special Sakai
* Spring bean list property override syntax (propertyName[index]@beanName=val)
*/
@SuppressWarnings("serial")
public void testBeanListPropertyOverridingDereferencesPlaceholderProperties() {
ITestComponent testComponent = (ITestComponent)getService(ITestComponent.class.getName() + "2");
List<String> expected = new ArrayList<String>() {{
add("str1");
add("str1-str2");
add("str1-str2-str3");
}};
assertEquals("Property values not dereferenced when overriding bean list property",
expected, testComponent.getListOverride1());
}
/**
* Verifies that property dereferencing works as usual even for String-encoded arrays
* set by properties having the special Sakai Spring bean addressing syntax
* (propertyName@beanName=val,val,val)
*/
public void testStringArrayBeanPropertyOverridingDereferencesPlaceholderProperties() {
ITestComponent testComponent = (ITestComponent)getService(ITestComponent.class.getName() + "2");
String[] expected = new String[] { "str1", "str1-str2", "str1-str2-str3" };
String[] actual = trim(testComponent.getStringArrayPlaceholder1());
assertTrue("Property values not dereferenced when overriding bean string array property as CSV list. Expected " + Arrays.toString(expected) + ", but was " + Arrays.toString(actual),
Arrays.equals(expected, actual));
}
public void testGetRawPropertyDoesNotDereferencePlaceholderPropertiesForSimpleProperties() {
assertEquals("Property value for \"stringWithNestedPlaceholders\" inappropriately dereferenced",
"${stringWithPlaceholder}-str3", serverConfigurationService.getRawProperty("stringWithNestedPlaceholders"));
}
// highly unlikely to vary by property key syntax
public void testGetStringAndGetRawPropertyReturnSameValueForUndefinedProperty() {
assertEquals("Mismatched representations of undefined properties",
serverConfigurationService.getString("this.property.is.not.defined"),
serverConfigurationService.getRawProperty("this.propertie.is.not.defined"));
}
public void testGetRawPropertyDoesNotDereferencePlaceholderPropertiesForBeanAddressingProperties() {
assertEquals("Property value for \"overrideString1@org.sakaiproject.component.test.ITestComponent2\" inappropriately dereferenced",
"${stringWithNestedPlaceholders}", serverConfigurationService.getRawProperty("overrideString1@org.sakaiproject.component.test.ITestComponent2"));
}
private String[] trim(String[] strArray) {
if ( strArray == null ) return null;
for (int p = 0; p < strArray.length; p++ ) {
if ( strArray[p] == null ) continue;
strArray[p] = strArray[p].trim();
}
return strArray;
}
}