FELIX-3087 Fix wrong Character/Char type conversion; add unit tests; refactor value conversion to do it during validation, which allows to fail value conversion on a component-level instead of a descriptor file level.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1180605 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
index f708538..3cd7ff3 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
@@ -19,6 +19,7 @@
package org.apache.felix.scr.impl.metadata;
+import java.lang.reflect.Array;
import junit.framework.TestCase;
import org.apache.felix.scr.impl.MockLogger;
@@ -265,8 +266,8 @@
final ComponentMetadata cm1 = createComponentMetadata11( Boolean.TRUE, null );
cm1.setName( null );
cm1.validate( logger );
- assertEquals( "Expected name to equal implementation class name", cm1.getImplementationClassName(), cm1
- .getName() );
+ assertEquals( "Expected name to equal implementation class name", cm1.getImplementationClassName(),
+ cm1.getName() );
}
@@ -355,8 +356,8 @@
{
final ComponentMetadata cm1 = createComponentMetadata( Boolean.TRUE, null );
cm1.validate( logger );
- assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL, cm1
- .getConfigurationPolicy() );
+ assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL,
+ cm1.getConfigurationPolicy() );
final ComponentMetadata cm2 = createComponentMetadata( Boolean.TRUE, null );
cm2.setConfigurationPolicy( ComponentMetadata.CONFIGURATION_POLICY_IGNORE );
@@ -380,26 +381,26 @@
{
final ComponentMetadata cm1 = createComponentMetadata11( Boolean.TRUE, null );
cm1.validate( logger );
- assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL, cm1
- .getConfigurationPolicy() );
+ assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL,
+ cm1.getConfigurationPolicy() );
final ComponentMetadata cm2 = createComponentMetadata11( Boolean.TRUE, null );
cm2.setConfigurationPolicy( ComponentMetadata.CONFIGURATION_POLICY_IGNORE );
cm2.validate( logger );
- assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_IGNORE, cm2
- .getConfigurationPolicy() );
+ assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_IGNORE,
+ cm2.getConfigurationPolicy() );
final ComponentMetadata cm3 = createComponentMetadata11( Boolean.TRUE, null );
cm3.setConfigurationPolicy( ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL );
cm3.validate( logger );
- assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL, cm3
- .getConfigurationPolicy() );
+ assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL,
+ cm3.getConfigurationPolicy() );
final ComponentMetadata cm4 = createComponentMetadata11( Boolean.TRUE, null );
cm4.setConfigurationPolicy( ComponentMetadata.CONFIGURATION_POLICY_REQUIRE );
cm4.validate( logger );
- assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_REQUIRE, cm4
- .getConfigurationPolicy() );
+ assertEquals( "Configuration policy", ComponentMetadata.CONFIGURATION_POLICY_REQUIRE,
+ cm4.getConfigurationPolicy() );
final ComponentMetadata cm5 = createComponentMetadata11( Boolean.TRUE, null );
cm5.setConfigurationPolicy( "undefined" );
@@ -432,8 +433,8 @@
cm2.addDependency( createReferenceMetadata( "name1" ) );
cm2.addDependency( createReferenceMetadata( "name1" ) );
cm2.validate( logger );
- assertTrue( "Expected warning for duplicate reference name", logger
- .messageContains( "Detected duplicate reference name" ) );
+ assertTrue( "Expected warning for duplicate reference name",
+ logger.messageContains( "Detected duplicate reference name" ) );
}
@@ -476,8 +477,8 @@
// validates fine (though logging a warning) and sets field to null
cm3.validate( logger );
- assertTrue( "Expected warning for unsupported updated method name", logger
- .messageContains( "Ignoring updated method definition" ) );
+ assertTrue( "Expected warning for unsupported updated method name",
+ logger.messageContains( "Ignoring updated method definition" ) );
assertNull( rm3.getUpdated() );
}
@@ -493,8 +494,8 @@
// validates fine (though logging a warning) and sets field to null
cm3.validate( logger );
- assertTrue( "Expected warning for unsupported updated method name", logger
- .messageContains( "Ignoring updated method definition" ) );
+ assertTrue( "Expected warning for unsupported updated method name",
+ logger.messageContains( "Ignoring updated method definition" ) );
assertNull( rm3.getUpdated() );
}
@@ -615,7 +616,7 @@
public void test_property_char_ds10() throws ComponentException
{
final ComponentMetadata cm = createComponentMetadata( null, null );
- PropertyMetadata prop = createPropertyMetadata( "x", "Char", "x" );
+ PropertyMetadata prop = createPropertyMetadata( "x", "Char", Integer.toString( 'x' ) );
cm.addProperty( prop );
cm.validate( logger );
assertTrue( prop.getValue() instanceof Character );
@@ -639,13 +640,55 @@
}
+ public void test_property_non_character()
+ {
+ final ComponentMetadata cm = createComponentMetadata( null, null );
+
+ assertProperty( "String", "Ein String", cm );
+ assertProperty( "Double", new Double( 2.5 ), cm );
+ assertProperty( "Float", new Float( 2.5 ), cm );
+ assertProperty( "Long", new Long( 2 ), cm );
+ assertProperty( "Integer", new Integer( 2 ), cm );
+ assertProperty( "Short", new Short( ( short ) 2 ), cm );
+ assertProperty( "Byte", new Byte( ( byte ) 2 ), cm );
+ assertProperty( "Boolean", Boolean.TRUE, cm );
+
+ assertPropertyFail( "Double", "x", cm );
+ assertPropertyFail( "Float", "x", cm );
+ assertPropertyFail( "Long", "x", cm );
+ assertPropertyFail( "Integer", "x", cm );
+ assertPropertyFail( "Short", "x", cm );
+ assertPropertyFail( "Byte", "x", cm );
+ }
+
+
+ public void test_property_array_non_character()
+ {
+ final ComponentMetadata cm = createComponentMetadata( null, null );
+ assertPropertyArray( "String", "Ein String", cm );
+ assertPropertyArray( "Double", new Double( 2.5 ), cm );
+ assertPropertyArray( "Float", new Float( 2.5 ), cm );
+ assertPropertyArray( "Long", new Long( 2 ), cm );
+ assertPropertyArray( "Integer", new Integer( 2 ), cm );
+ assertPropertyArray( "Short", new Short( ( short ) 2 ), cm );
+ assertPropertyArray( "Byte", new Byte( ( byte ) 2 ), cm );
+ assertPropertyArray( "Boolean", Boolean.TRUE, cm );
+
+ assertPropertyArrayFail( "Double", "x", cm );
+ assertPropertyArrayFail( "Float", "x", cm );
+ assertPropertyArrayFail( "Long", "x", cm );
+ assertPropertyArrayFail( "Integer", "x", cm );
+ assertPropertyArrayFail( "Short", "x", cm );
+ assertPropertyArrayFail( "Byte", "x", cm );
+ }
+
+
public void test_property_character_ds10()
{
final ComponentMetadata cm = createComponentMetadata( null, null );
- cm.addProperty( createPropertyMetadata( "x", "Character", "x" ) );
try
{
- cm.validate( logger );
+ createPropertyMetadata( "x", "Character", Integer.toString( 'x' ) ).validate( cm );
fail( "Expect validation failure for illegal property type Character" );
}
catch ( ComponentException ce )
@@ -658,7 +701,7 @@
public void test_property_character_ds11() throws ComponentException
{
final ComponentMetadata cm = createComponentMetadata11( null, null );
- PropertyMetadata prop = createPropertyMetadata( "x", "Character", "x" );
+ PropertyMetadata prop = createPropertyMetadata( "x", "Character", Integer.toString( 'x' ) );
cm.addProperty( prop );
cm.validate( logger );
assertTrue( prop.getValue() instanceof Character );
@@ -680,11 +723,13 @@
}
catch ( ComponentException ce )
{
- assertTrue( "Expected validation reason to contain '" + expectedValidationReason + "': actual: "
- + ce.getMessage(), ce.getMessage().indexOf( expectedValidationReason ) >= 0 );
+ assertTrue(
+ "Expected validation reason to contain '" + expectedValidationReason + "': actual: " + ce.getMessage(),
+ ce.getMessage().indexOf( expectedValidationReason ) >= 0 );
}
}
+
// Creates Component Metadata for the given namespace
private ComponentMetadata createComponentMetadata( int nameSpaceCode, Boolean immediate, String factory )
{
@@ -702,6 +747,7 @@
return meta;
}
+
// Creates DS 1.0 Component Metadata
private ComponentMetadata createComponentMetadata( Boolean immediate, String factory )
{
@@ -754,4 +800,99 @@
}
return meta;
}
+
+
+ private void assertProperty( String type, Object value, ComponentMetadata cmeta )
+ {
+ PropertyMetadata meta = createPropertyMetadata( "dummy", type, String.valueOf( value ) );
+ meta.validate( cmeta );
+ assertSame( value.getClass(), meta.getValue().getClass() );
+ assertEquals( value, meta.getValue() );
+ }
+
+
+ private void assertPropertyArray( String type, Object value, ComponentMetadata cmeta )
+ {
+ PropertyMetadata meta = createPropertyMetadata( "dummy", type, null );
+ meta.setValues( String.valueOf( value ) );
+ meta.validate( cmeta );
+
+ Object propVal = meta.getValue();
+ assertTrue( propVal.getClass().isArray() );
+ assertPrimitiveType( value.getClass(), propVal.getClass().getComponentType() );
+ assertEquals( 1, Array.getLength( propVal ) );
+ assertEquals( value, Array.get( propVal, 0 ) );
+ }
+
+
+ private void assertPropertyFail( String type, String value, ComponentMetadata cmeta )
+ {
+ try
+ {
+ PropertyMetadata meta = createPropertyMetadata( "dummy", type, value );
+ meta.validate( cmeta );
+ fail( "Expected validation failure for " + type + "=" + value );
+ }
+ catch ( ComponentException ce )
+ {
+ // expected
+ }
+ }
+
+
+ private void assertPropertyArrayFail( String type, String value, ComponentMetadata cmeta )
+ {
+ try
+ {
+ PropertyMetadata meta = createPropertyMetadata( "dummy", type, null );
+ meta.setValues( value );
+ meta.validate( cmeta );
+ fail( "Expected validation failure for " + type + "=" + value );
+ }
+ catch ( ComponentException ce )
+ {
+ // expected
+ }
+ }
+
+
+ private void assertPrimitiveType( final Class expectedBoxClass, final Class actualClass )
+ {
+ if ( expectedBoxClass == String.class )
+ {
+ assertEquals( expectedBoxClass, actualClass );
+ }
+ else if ( expectedBoxClass == Double.class )
+ {
+ assertEquals( Double.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Float.class )
+ {
+ assertEquals( Float.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Long.class )
+ {
+ assertEquals( Long.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Integer.class )
+ {
+ assertEquals( Integer.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Short.class )
+ {
+ assertEquals( Short.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Byte.class )
+ {
+ assertEquals( Byte.TYPE, actualClass );
+ }
+ else if ( expectedBoxClass == Boolean.class )
+ {
+ assertEquals( Boolean.TYPE, actualClass );
+ }
+ else
+ {
+ fail( "Unexpected box class " + expectedBoxClass );
+ }
+ }
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
index bc307cd..9fa9864 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
@@ -239,11 +239,13 @@
// property setting
final PropertyMetadata prop = getPropertyMetadata( cm10, "prop" );
+ prop.validate( cm10 ); // property value requires validation
assertNotNull( "prop exists", prop );
assertEquals( "prop type", "Integer", prop.getType() );
assertEquals( "prop value", 1234, ( ( Integer ) prop.getValue() ).intValue() );
final PropertyMetadata file_property = getPropertyMetadata( cm10, "file.property" );
+ file_property.validate( cm10 ); // property value requires validation
assertNotNull( "file.property exists", file_property );
assertEquals( "file.property type", "String", file_property.getType() );
assertEquals( "file.property value", "Property from File", file_property.getValue() );
@@ -447,12 +449,13 @@
final PropertyMetadata prop = getPropertyMetadata( cm11, "char_array_property" );
assertNotNull( "prop exists", prop );
assertEquals( "prop type", "Character", prop.getType() );
+ prop.validate( cm11 ); // property value conversion requires validation
Object value = prop.getValue();
- assertTrue( "prop arry", value instanceof char[] );
- char[] chars = (char[]) value;
- assertEquals( "prop number of values", 2, chars.length);
- assertEquals( "prop value 0", 'a', chars[0] );
- assertEquals( "prop value 1", 'b', chars[1] );
+ assertTrue( "prop array", value instanceof char[] );
+ char[] chars = ( char[] ) value;
+ assertEquals( "prop number of values", 2, chars.length );
+ assertEquals( "prop value 0", 'A', chars[0] );
+ assertEquals( "prop value 1", 'B', chars[1] );
}
}
diff --git a/scr/src/test/resources/components_properties_11.xml b/scr/src/test/resources/components_properties_11.xml
index f4de438..d16d49c 100644
--- a/scr/src/test/resources/components_properties_11.xml
+++ b/scr/src/test/resources/components_properties_11.xml
@@ -20,7 +20,7 @@
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="DummyClass" />
<property name="char_array_property" type="Character">
- a
- b
+ 65
+ 66
</property>
</scr:component>