diff options
author | Thomas Watson | 2011-03-18 19:37:21 +0000 |
---|---|---|
committer | Thomas Watson | 2011-03-18 19:37:21 +0000 |
commit | cc5c79613d14ea18d6c319094ad0bef0e528bf15 (patch) | |
tree | 88d56a573d6ac32a150a5c24b051c611de2aaf03 /bundles/org.eclipse.equinox.compendium.tests | |
parent | 0cfb13f0d0402260eae64b5b31846fc57c867c64 (diff) | |
download | rt.equinox.bundles-cc5c79613d14ea18d6c319094ad0bef0e528bf15.tar.gz rt.equinox.bundles-cc5c79613d14ea18d6c319094ad0bef0e528bf15.tar.xz rt.equinox.bundles-cc5c79613d14ea18d6c319094ad0bef0e528bf15.zip |
Bug 332161 - MetaType service trims whitespace from arguments passed to AttributeDefinition.validate(String).
Diffstat (limited to 'bundles/org.eclipse.equinox.compendium.tests')
9 files changed, 535 insertions, 103 deletions
diff --git a/bundles/org.eclipse.equinox.compendium.tests/.classpath b/bundles/org.eclipse.equinox.compendium.tests/.classpath index 26989dd44..de275be10 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/.classpath +++ b/bundles/org.eclipse.equinox.compendium.tests/.classpath @@ -6,5 +6,6 @@ <classpathentry kind="src" output="bundle_tests/metatype/tb1" path="bundles_src/metatype/tb1"/> <classpathentry kind="src" output="bundle_tests/metatype/tb2" path="bundles_src/metatype/tb2"/> <classpathentry kind="src" output="bundle_tests/metatype/tb3" path="bundles_src/metatype/tb3"/> + <classpathentry kind="src" output="bundle_tests/metatype/tb4" path="bundles_src/metatype/tb4"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/bundles/org.eclipse.equinox.compendium.tests/build.properties b/bundles/org.eclipse.equinox.compendium.tests/build.properties index 85b98a796..f03c3d77f 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/build.properties +++ b/bundles/org.eclipse.equinox.compendium.tests/build.properties @@ -11,7 +11,10 @@ source.bundle_tests/metatype.tb2.jar = bundles_src/metatype/tb2/ manifest.bundle_tests/metatype.tb2.jar = META-INF/MANIFEST.MF source.bundle_tests/metatype.tb3.jar = bundles_src/metatype/tb3/ manifest.bundle_tests/metatype.tb3.jar = META-INF/MANIFEST.MF +source.bundle_tests/metatype.tb4.jar = bundles_src/metatype/tb4/ +manifest.bundle_tests/metatype.tb4.jar = META-INF/MANIFEST.MF jars.compile.order = bundle_tests/metatype/metatype.tb1.jar,\ bundle_tests/metatype/metatype.tb2.jar,\ - bundle_tests/metatype/metatype.tb3.jar + bundle_tests/metatype/metatype.tb3.jar,\ + bundle_tests/metatype/metatype.tb4.jar diff --git a/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/META-INF/MANIFEST.MF new file mode 100644 index 000000000..7b5151c71 --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: MetaType TB4 +Bundle-SymbolicName: org.eclipse.equinox.metatype.tests.tb4 +Bundle-Version: 1.0.0 +Eclipse-LazyStart: true +Import-Package: org.osgi.framework;version="1.3.0", + org.osgi.service.metatype;version="1.2" +Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Bundle-Vendor: IBM diff --git a/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/OSGI-INF/metatype/metadata.xml b/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/OSGI-INF/metatype/metadata.xml new file mode 100644 index 000000000..eb836c719 --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/bundles_src/metatype/tb4/OSGI-INF/metatype/metadata.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:MetaData + xmlns:md="http://www.org.osgi/xmlns/metatype/v1.0.0/md" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.org.osgi/xmlns/metatype/v1.0.1/md metatype.xsd"> + <OCD id="ocd1" name="Object"> + <AD cardinality="0" default="\
" id="char1" type="Char"> + <Option label="Space" value="\ "/> + <Option label="Tab" value="\	"/> + <Option label="Line Feed" value="\
\"/> + <Option label="Carriage Return" value="\
"/> + <Option label="Capital A" value="A"/> + <Option label="Lowercase Z" value="z"/> + </AD> + <AD default="\
\
" id="string1" type="String"/> + <AD + cardinality="3" + default=" \\ Hello\, wo\rld! ,"Goodbye\, cruel world ..." \
\
 , To B\e\,\
\
Or not\ to be	\	 	" + id="string2" + type="String"> + <Option label="1" value=" \\ Hello\, wo\rld! \"/> + <Option label="2" value=""Goodbye\, cruel world ..." \
\
 "/> + <Option label="3" value=" To B\e\,\
\
Or not\ to be	\	 	"/> + </AD> + <AD id="string3" type="String"/> + <AD default="" id="string4" type="String"> + <Option label="Empty String" value=""/> + </AD> + <AD default="" id="integer1" type="Integer"> + <Option label="Empty String" value=""/> + </AD> + <AD cardinality="5" default="," id="string5" type="String"> + <Option label="Empty String" value=""/> + <Option label="2 Empty Strings" value=","/> + <Option label="3 Empty Strings" value=",,"/> + <Option label="4 Empty Strings" value=",,,"/> + <Option label="5 Empty Strings" value=",,,,"/> + <Option label="6 Empty Strings" value=",,,,,"/> + </AD> + <AD cardinality="1" default="A,B" id="char2" type="Char"> + <Option label="Capital A" value="A"/> + <Option label="Capital B" value="B"/> + <Option label="Capitals C and D" value="C,D"/> + <Option label="Capital E" value="E"/> + </AD> + <AD id="char3" max=" " min="	" type="Char"/> + </OCD> + <Designate pid="org.eclipse.equinox.metatype.tests.tb4"> + <Object ocdref="ocd1"/> + </Designate> +</md:MetaData> diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AbstractTest.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AbstractTest.java new file mode 100644 index 000000000..4490c02fa --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AbstractTest.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.metatype.tests; + +import junit.framework.TestCase; +import org.eclipse.equinox.compendium.tests.Activator; +import org.eclipse.osgi.tests.bundles.BundleInstaller; +import org.osgi.framework.ServiceReference; +import org.osgi.service.metatype.AttributeDefinition; +import org.osgi.service.metatype.MetaTypeService; + +public abstract class AbstractTest extends TestCase { + protected BundleInstaller bundleInstaller; + protected MetaTypeService metatype; + + private ServiceReference metaTypeReference; + + protected void assertValidationFail(String value, AttributeDefinition ad) { + String result = assertValidationPresent(value, ad); + assertTrue("Validation passed", result.length() > 0); //$NON-NLS-1$ + } + + protected void assertValidationPass(String value, AttributeDefinition ad) { + String result = assertValidationPresent(value, ad); + assertEquals("Validation failed", 0, result.length()); //$NON-NLS-1$ + } + + protected String assertValidationPresent(String value, AttributeDefinition ad) { + String result = ad.validate(value); + assertNotNull("No validation was present", result); //$NON-NLS-1$ + return result; + } + + protected String escape(String value) { + if (value == null || value.length() == 0) { + return value; + } + StringBuffer result = new StringBuffer(value.length() + 20); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == ',' || c == '\\' || Character.isWhitespace(c)) { + result.append('\\'); + } + result.append(c); + } + return result.toString(); + } + + protected AttributeDefinition findAttributeDefinitionById(String id, AttributeDefinition[] ads) { + if (id == null || ads == null) + return null; + for (int i = 0; i < ads.length; i++) { + if (ads[i] == null) + continue; + if (id.equals(ads[i].getID())) { + return ads[i]; + } + } + return null; + } + + protected String getFirstDefaultValue(String[] defaultValue) { + if (defaultValue == null || defaultValue.length == 0) + return null; + return defaultValue[0]; + } + + protected void setUp() throws Exception { + Activator.getBundle(Activator.BUNDLE_METATYPE).start(); + metaTypeReference = Activator.getBundleContext().getServiceReference(MetaTypeService.class.getName()); + assertNotNull("Metatype service reference not found", metaTypeReference); //$NON-NLS-1$ + metatype = (MetaTypeService) Activator.getBundleContext().getService(metaTypeReference); + assertNotNull("Metatype service not found", metatype); //$NON-NLS-1$ + bundleInstaller = new BundleInstaller("bundle_tests/metatype", Activator.getBundleContext()); //$NON-NLS-1$ + } + + protected void tearDown() throws Exception { + bundleInstaller.shutdown(); + Activator.getBundleContext().ungetService(metaTypeReference); + Activator.getBundle(Activator.BUNDLE_METATYPE).stop(); + } +} diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AllTests.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AllTests.java index 42d4091c1..d0854c321 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AllTests.java +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AllTests.java @@ -17,6 +17,7 @@ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Tests for Equinox MetaType"); //$NON-NLS-1$ suite.addTestSuite(AttributeTypePasswordTest.class); + suite.addTestSuite(Bug332161Test.class); suite.addTestSuite(BugTests.class); suite.addTestSuite(SameOcdPidFactoryPidTest.class); return suite; diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AttributeTypePasswordTest.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AttributeTypePasswordTest.java index fd661ebed..db4a2584d 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AttributeTypePasswordTest.java +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/AttributeTypePasswordTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 IBM Corporation and others + * Copyright (c) 2010, 2011 IBM Corporation and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,40 +10,28 @@ *******************************************************************************/ package org.eclipse.equinox.metatype.tests; -import junit.framework.TestCase; -import org.eclipse.equinox.compendium.tests.Activator; -import org.eclipse.osgi.tests.bundles.BundleInstaller; import org.osgi.framework.Bundle; -import org.osgi.framework.ServiceReference; import org.osgi.service.metatype.*; -public class AttributeTypePasswordTest extends TestCase { +public class AttributeTypePasswordTest extends AbstractTest { private Bundle bundle; - private BundleInstaller bundleInstaller; - private MetaTypeService metaType; - private ServiceReference metaTypeReference; protected void setUp() throws Exception { - Activator.getBundle(Activator.BUNDLE_METATYPE).start(); - metaTypeReference = Activator.getBundleContext().getServiceReference(MetaTypeService.class.getName()); - metaType = (MetaTypeService) Activator.getBundleContext().getService(metaTypeReference); - bundleInstaller = new BundleInstaller("bundle_tests/metatype", Activator.getBundleContext()); //$NON-NLS-1$ - bundleInstaller.refreshPackages(null); + super.setUp(); bundle = bundleInstaller.installBundle("tb1"); //$NON-NLS-1$ bundle.start(); } protected void tearDown() throws Exception { - bundleInstaller.shutdown(); - Activator.getBundleContext().ungetService(metaTypeReference); - Activator.getBundle(Activator.BUNDLE_METATYPE).stop(); + bundle.stop(); + super.tearDown(); } /* * Ensures the PASSWORD type is recognized. */ public void testAttributeTypePassword1() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); for (int i = 0; i < ads.length; i++) { @@ -55,36 +43,26 @@ public class AttributeTypePasswordTest extends TestCase { /* * Ensures the PASSWORD type is treated the same as the STRING type. - * Validation should not be present when min and max are not specified and - * their are no enumerated constraints. */ public void testAttributeTypePassword2() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); - for (int i = 0; i < ads.length; i++) { - if (ads[i].getID().equals("password1")) { //$NON-NLS-1$ - assertNull("Validation should not be present when min and max are not specified and their are no enumerated constraints", ads[i].validate("1234abcd")); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + AttributeDefinition ad = findAttributeDefinitionById("password1", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + assertValidationPass("1234abcd", ad); //$NON-NLS-1$ } /* * Ensures the PASSWORD type is treated the same as the STRING type. - * Validation should be present when min and max are not specified and - * their are enumerated constraints. */ public void testAttributeTypePassword3() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); - for (int i = 0; i < ads.length; i++) { - if (ads[i].getID().equals("password2")) { //$NON-NLS-1$ - assertNotNull("Validation should be present when min and max are not specified and their are enumerated constraints", ads[i].validate("password")); //$NON-NLS-1$ //$NON-NLS-2$ - assertEquals("Value 'password' should have been valid", 0, ads[i].validate("password").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue("Value '1234abcd' should not have been valid", ads[i].validate("1234abcd").length() > 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + AttributeDefinition ad = findAttributeDefinitionById("password2", ads); //$NON-NLS-1$ + assertValidationPass("password", ad); //$NON-NLS-1$ + assertValidationFail("1234abcd", ad); //$NON-NLS-1$ } /* @@ -92,16 +70,13 @@ public class AttributeTypePasswordTest extends TestCase { * PASSWORD length should be no less than min. */ public void testAttributeTypePassword4() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); - for (int i = 0; i < ads.length; i++) { - if (ads[i].getID().equals("password3")) { //$NON-NLS-1$ - assertEquals("Value '12345678' should have been valid", 0, ads[i].validate("12345678").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertEquals("Value '123456789' should have been valid", 0, ads[i].validate("123456789").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue("Value '1234567' should not have been valid", ads[i].validate("1234567").length() > 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + AttributeDefinition ad = findAttributeDefinitionById("password3", ads); //$NON-NLS-1$ + assertValidationPass("12345678", ad); //$NON-NLS-1$ + assertValidationPass("123456789", ad); //$NON-NLS-1$ + assertValidationFail("1234567", ad); //$NON-NLS-1$ } /* @@ -109,16 +84,13 @@ public class AttributeTypePasswordTest extends TestCase { * PASSWORD length should be no greater than max. */ public void testAttributeTypePassword5() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); - for (int i = 0; i < ads.length; i++) { - if (ads[i].getID().equals("password4")) { //$NON-NLS-1$ - assertEquals("Value '12345' should have been valid", 0, ads[i].validate("12345").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertEquals("Value '1234' should have been valid", 0, ads[i].validate("1234").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue("Value '123456' should not have been valid", ads[i].validate("123456").length() > 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + AttributeDefinition ad = findAttributeDefinitionById("password4", ads); //$NON-NLS-1$ + assertValidationPass("12345", ad); //$NON-NLS-1$ + assertValidationPass("1234", ad); //$NON-NLS-1$ + assertValidationFail("123456", ad); //$NON-NLS-1$ } /* @@ -126,16 +98,13 @@ public class AttributeTypePasswordTest extends TestCase { * PASSWORD length should be no less than min and no greater than max. */ public void testAttributeTypePassword6() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb1", null); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); - for (int i = 0; i < ads.length; i++) { - if (ads[i].getID().equals("password5")) { //$NON-NLS-1$ - assertEquals("Value '123' should have been valid", 0, ads[i].validate("123").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue("Value '12' should not have been valid", ads[i].validate("12").length() > 0); //$NON-NLS-1$ //$NON-NLS-2$ - assertEquals("Value '123456' should have been valid", 0, ads[i].validate("123456").length()); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue("Value '1234567' should not have been valid", ads[i].validate("1234567").length() > 0); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + AttributeDefinition ad = findAttributeDefinitionById("password5", ads); //$NON-NLS-1$ + assertValidationPass("123", ad); //$NON-NLS-1$ + assertValidationFail("12", ad); //$NON-NLS-1$ + assertValidationPass("123456", ad); //$NON-NLS-1$ + assertValidationFail("1234567", ad); //$NON-NLS-1$ } } diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/Bug332161Test.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/Bug332161Test.java new file mode 100644 index 000000000..00abe7042 --- /dev/null +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/Bug332161Test.java @@ -0,0 +1,337 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.metatype.tests; + +import java.util.Arrays; +import org.osgi.framework.Bundle; +import org.osgi.service.metatype.*; + +/* + * The main idea of this defect was support for the Char attribute definition + * type. The specification does not limit the Char type to non-whitespace + * characters only. However, the whitespace stripping rules imposed on + * implementations in terms of the 'default' XML attribute on the <AD> element + * and the AttributeDefinition.getDefaultValue() method made supporting + * whitespace characters impossible. + * + * CPEG did not want to remove the whitespace stripping rules out of concern + * for backwards compatibility. Consequently, it was decided that significant + * whitespace should be escaped with '\', like the comma must be when it should + * not be used as a delimiter. Furthermore, the same whitespace stripping and + * escape rules should apply to the AttributeDefinition.validate(String) method. + * This decision, of course, had ramifications extending beyond the resolution + * of the original issue, which is the reason for the complexity of this test. + * + * The Equinox Metatype implementation employs the following strategy. + * + * (1) Significant whitespace at the beginning or end of the 'default' XML + * attribute within the <AD> element must be escaped; otherwise, it will be + * stripped. + * (2) Significant whitespace at the beginning or end of each comma delimited + * token within the 'default' attribute must be escaped; otherwise, it will + * be stripped. + * (3) Significant whitespace at the beginning or end of the argument passed to + * the validate() method must be escaped; otherwise, it will be stripped. + * (4) Significant whitespace at the beginning or end of the 'value' XML + * attribute within the <Option> element must be escaped; otherwise, it + * will be stripped. + * (5) Escaping whitespace between two non-whitespace characters is permitted + * but not required. In other words, whitespace between two non-whitespace + * characters will never be stripped. + * (6) An escape character occurring as the last character in the sequence will + * be treated the same as insignificant whitespace. + * (7) Escape characters will not be preserved in the results of + * AttributeDefinition.getDefaultValue() or + * AttributeDefinition.getOptionValues(). This has the nonintuitive + * consequence that + * AttributeDefinition.validate(AttributeDefinition.getDefaultValue()[i]) + * and + * AttributeDefinition.validate(AttributeDefinition.getOptionValues()[i]) + * will not necessarily pass validation. However, preserving escape + * characters in the result would probably be even more nonintuitive. + * Moreover, this approach is not inconsistent with the requirement on + * clients to escape certain characters (',', '\', and leading or trailing + * significant whitespace) on other parameters to the validate() method. + * Finally, the two operations referenced above are completely superfluous + * since it must be the case that any declared default or option value is + * valid. + * (8) Null parameters passed to AttributeDefinition.validate(String) are + * always invalid. + * (9) Empty string parameters passed to AttributeDefinition.validate(String) + * are always valid for the String type, even for cardinality zero + * (required by the CT), unless restricted by options. + * Furthermore, a sequence of comma-delimited empty strings is valid for + * cardinality < -1 and cardinality > 1. For example, given a + * cardinality of 5, AttributeDefinition.validate(",,,,") would pass. + *(10) In order to be valid, a value must pass all of the following tests. + * (a) The value must not be null. + * (b) The value must be convertible into the attribute definition's + * type, unless it's an empty string and cardinality != 0. + * (c) The following relation must hold: min <= value <= max, if either + * min or max is specified. + * (d) If options were specified, the value must be equal to one of + * them. + * Note this approach means validation will always be present since the type + * compatibility check can always be performed (i.e. the Equinox + * implementation will never return null indicating no validation exists). + *(11) An invalid option value will simply be ignored and not result in the + * entire metadata being rejected (this is based on the previous behavior). + *(12) Similarly, an invalid default value will simply be ignored. + *(13) When specifying 'min' or 'max' values for type Char, escapes must not be + * used. For example, <AD id="1" max="" min="	" type="Char"/> + * not <AD id="1" max="\" min="\	" type="Char"/>. + */ +public class Bug332161Test extends AbstractTest { + private AttributeDefinition[] ads; + private Bundle bundle; + private MetaTypeInformation mti; + private ObjectClassDefinition ocd; + + /* + * Tests an enumerated Char type consisting of a mixture of whitespace and + * non-whitespace characters. A whitespace default value is used. + */ + public void test1() { + AttributeDefinition ad = findAttributeDefinitionById("char1", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String defaultValue = getFirstDefaultValue(ad.getDefaultValue()); + assertNotNull("Default value not found", defaultValue); //$NON-NLS-1$ + assertEquals("Wrong default value", "\r", defaultValue); //$NON-NLS-1$ //$NON-NLS-2$ + validateChar1Options(ad.getOptionLabels(), ad.getOptionValues()); + assertValidationPass("\\ ", ad); //$NON-NLS-1$ + assertValidationPass("\\\u0020", ad); //$NON-NLS-1$ + assertValidationPass("\\ ", ad); //$NON-NLS-1$ + assertValidationPass("\\\u0009", ad); //$NON-NLS-1$ + assertValidationPass("\\\n", ad); //$NON-NLS-1$ + assertValidationPass("\\\r", ad); //$NON-NLS-1$ + assertValidationPass("A", ad); //$NON-NLS-1$ + assertValidationPass("z", ad); //$NON-NLS-1$ + assertValidationFail("\\\u0008", ad); //$NON-NLS-1$ + assertValidationFail("a", ad); //$NON-NLS-1$ + assertValidationFail("Z", ad); //$NON-NLS-1$ + } + + /* + * Tests a String type with a default value of CRLF. + */ + public void test2() { + AttributeDefinition ad = findAttributeDefinitionById("string1", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String defaultValue = getFirstDefaultValue(ad.getDefaultValue()); + assertNotNull("Default value not found", defaultValue); //$NON-NLS-1$ + assertEquals("Wrong default value", "\r\n", defaultValue); //$NON-NLS-1$ //$NON-NLS-2$ + assertValidationPass("\\\r\\\n", ad); //$NON-NLS-1$ + } + + /* + * Tests a String type with a default value consisting of multiple tokens + * with a mixture of whitespace (significant and not significant), escapes, + * and non-whitespace characters. + */ + public void test3() { + AttributeDefinition ad = findAttributeDefinitionById("string2", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String[] defaultValue = ad.getDefaultValue(); + assertNotNull("Default value not found", defaultValue); //$NON-NLS-1$ + String[] expectedValue = new String[] {"\\ Hello, world!", //$NON-NLS-1$ + "\"Goodbye, cruel world ...\" \r\n", //$NON-NLS-1$ + "To Be,\r\nOr not to be\u0009\u0009" //$NON-NLS-1$ + }; + assertTrue("Wrong default value", Arrays.equals(defaultValue, expectedValue)); //$NON-NLS-1$ + assertValidationPass(escape(defaultValue[0]), ad); + assertValidationPass(escape(defaultValue[1]), ad); + assertValidationPass(escape(defaultValue[2]), ad); + assertValidationPass(escape(expectedValue[0]), ad); + assertValidationPass(escape(expectedValue[1]), ad); + assertValidationPass(escape(expectedValue[2]), ad); + String token1 = " \\\\ Hello\\, wo\\rld! "; //$NON-NLS-1$ + String token2 = "\"Goodbye\\, cruel world ...\" \\\r\\\n "; //$NON-NLS-1$ + String token3 = " To B\\e\\,\\\r\\\nOr not\\ to be \\ "; //$NON-NLS-1$ + String tokens = token1 + ',' + token2 + ',' + token3; + assertValidationPass(token1, ad); + assertValidationPass(token2, ad); + assertValidationPass(token3, ad); + assertValidationPass(tokens, ad); + assertValidationPass(" \\\\ Hello\\, wo\\rld! ", ad); //$NON-NLS-1$ + assertValidationFail(" Hello\\, wo\\rld! ", ad); //$NON-NLS-1$ + assertValidationPass("\"Goodbye\\, cruel world ...\" \\\r\\\n ", ad); //$NON-NLS-1$ + assertValidationFail("\"Goodbye, cruel world ...\" \\\r\\\n ", ad); //$NON-NLS-1$ + assertValidationPass(" To B\\e\\,\\\r\\\nOr not\\ to be \\ ", ad); //$NON-NLS-1$ + assertValidationFail(" To B\\e\\,\\\r\\\n Or not\\ to be \\ ", ad); //$NON-NLS-1$ + assertValidationFail("i,have,cardinality,4", ad); //$NON-NLS-1$ + } + + /* + * Make sure these changes still return null for the default value when + * unspecified. + */ + public void test4() { + AttributeDefinition ad = findAttributeDefinitionById("string3", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + assertNull("Default value was not null", ad.getDefaultValue()); //$NON-NLS-1$ + } + + /* + * Invalid default and option values should be logged and ignored. + */ + public void test5() { + AttributeDefinition ad = findAttributeDefinitionById("char2", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + assertNull("Default value was not null", ad.getDefaultValue()); //$NON-NLS-1$ + validateChar2Options(ad.getOptionLabels(), ad.getOptionValues()); + } + + /* + * Null validation parameters are always invalid. Empty string validation + * parameters are valid for type String. + */ + public void test6() { + AttributeDefinition ad = findAttributeDefinitionById("string3", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + assertValidationFail(null, ad); + assertValidationPass("", ad); //$NON-NLS-1$ + ad = findAttributeDefinitionById("string2", ads); //$NON-NLS-1$ + assertValidationFail(null, ad); + assertValidationFail("", ad); //$NON-NLS-1$ + } + + /* + * Test whitespace characters using min and max. No escapes on min or max. + */ + public void test7() { + AttributeDefinition ad = findAttributeDefinitionById("char3", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + assertValidationPass("\\\u0009", ad); //$NON-NLS-1$ + assertValidationPass("\\\u0020", ad); //$NON-NLS-1$ + assertValidationPass("\\ ", ad); //$NON-NLS-1$ + assertValidationPass("\\\u000b", ad); //$NON-NLS-1$ + assertValidationPass("\\ ", ad); //$NON-NLS-1$ + assertValidationPass("\\\r", ad); //$NON-NLS-1$ + assertValidationPass("\\\n", ad); //$NON-NLS-1$ + assertValidationFail("\\\u0008", ad); //$NON-NLS-1$ + assertValidationFail("\u0021", ad); //$NON-NLS-1$ + assertValidationFail("!", ad); //$NON-NLS-1$ + } + + /* + * Test that empty string is a valid default and option value when + * cardinality is zero. + */ + public void test8() { + AttributeDefinition ad = findAttributeDefinitionById("string4", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String[] defaultValue = ad.getDefaultValue(); + assertNotNull("Default value was null", defaultValue); //$NON-NLS-1$ + assertEquals("Wrong number of default values", 1, defaultValue.length); //$NON-NLS-1$ + assertEquals("Wrong default value", "", defaultValue[0]); //$NON-NLS-1$ //$NON-NLS-2$ + String[] optionValues = ad.getOptionValues(); + assertNotNull("Option values was null", optionValues); //$NON-NLS-1$ + assertEquals("Wrong number of option values", 1, optionValues.length); //$NON-NLS-1$ + assertEquals("Wrong option value", "", optionValues[0]); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* + * Test that empty string is an invalid default and option value when type + * is other than String. Also test that getOptionLabels() and + * getOptionValues() returns null if options were specified but all were + * invalid and removed. + */ + public void test9() { + AttributeDefinition ad = findAttributeDefinitionById("integer1", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String[] defaultValue = ad.getDefaultValue(); + assertNull("Default value was not null", defaultValue); //$NON-NLS-1$ + assertNull("Option labels was not null", ad.getOptionLabels()); //$NON-NLS-1$ + assertNull("Option values was not null", ad.getOptionValues()); //$NON-NLS-1$ + } + + /* + * Test that empty string is a valid default and option value when + * cardinality is other than zero. + */ + public void test10() { + AttributeDefinition ad = findAttributeDefinitionById("string5", ads); //$NON-NLS-1$ + assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ + String[] defaultValue = ad.getDefaultValue(); + assertNotNull("Default value was null", defaultValue); //$NON-NLS-1$ + assertEquals("Wrong number of default values", 2, defaultValue.length); //$NON-NLS-1$ + assertEquals("Wrong default value", "", defaultValue[0]); //$NON-NLS-1$ //$NON-NLS-2$ + assertEquals("Wrong default value", "", defaultValue[1]); //$NON-NLS-1$ //$NON-NLS-2$ + String[] optionValues = ad.getOptionValues(); + assertNotNull("Option values was null", optionValues); //$NON-NLS-1$ + assertEquals("Wrong number of option values", 5, optionValues.length); //$NON-NLS-1$ + assertEquals("Wrong option value", "", optionValues[0]); //$NON-NLS-1$ //$NON-NLS-2$ + assertEquals("Wrong option value", ",", optionValues[1]); //$NON-NLS-1$ //$NON-NLS-2$ + assertEquals("Wrong option value", ",,", optionValues[2]); //$NON-NLS-1$ //$NON-NLS-2$ + assertEquals("Wrong option value", ",,,", optionValues[3]); //$NON-NLS-1$ //$NON-NLS-2$ + assertEquals("Wrong option value", ",,,,", optionValues[4]); //$NON-NLS-1$ //$NON-NLS-2$ + } + + protected void setUp() throws Exception { + super.setUp(); + bundle = bundleInstaller.installBundle("tb4"); //$NON-NLS-1$ + bundle.start(); + mti = metatype.getMetaTypeInformation(bundle); + assertNotNull("Metatype information not found", mti); //$NON-NLS-1$ + ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb4", null); //$NON-NLS-1$ + assertNotNull("Object class definition not found", ocd); //$NON-NLS-1$ + ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); + assertNotNull("Attribute definitions not found", ads); //$NON-NLS-1$ + assertEquals("Wrong number of attribute definitions", 9, ads.length); //$NON-NLS-1$ + } + + protected void tearDown() throws Exception { + bundle.stop(); + super.tearDown(); + } + + private void validateChar1Options(String[] optionLabels, String[] optionValues) { + assertNotNull("Option labels not found", optionLabels); //$NON-NLS-1$ + assertEquals("Wrong number of option labels", 6, optionLabels.length); //$NON-NLS-1$ + assertNotNull("Option values not found", optionValues); //$NON-NLS-1$ + assertEquals("Wrong number of option values", 6, optionValues.length); //$NON-NLS-1$ + for (int i = 0; i < optionLabels.length; i++) { + if ("Space".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("\u0020", optionValues[i]); //$NON-NLS-1$ + } else if ("Tab".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("\u0009", optionValues[i]); //$NON-NLS-1$ + } else if ("Line Feed".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("\n", optionValues[i]); //$NON-NLS-1$ + } else if ("Carriage Return".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("\r", optionValues[i]); //$NON-NLS-1$ + } else if ("Capital A".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("A", optionValues[i]); //$NON-NLS-1$ + } else if ("Lowercase Z".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("z", optionValues[i]); //$NON-NLS-1$ + } else { + fail("Wrong number of option labels"); //$NON-NLS-1$ + } + } + } + + private void validateChar2Options(String[] optionLabels, String[] optionValues) { + assertNotNull("Option labels not found", optionLabels); //$NON-NLS-1$ + assertEquals("Wrong number of option labels", 3, optionLabels.length); //$NON-NLS-1$ + assertNotNull("Option values not found", optionValues); //$NON-NLS-1$ + assertEquals("Wrong number of option values", 3, optionValues.length); //$NON-NLS-1$ + for (int i = 0; i < optionLabels.length; i++) { + if ("Capital A".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("A", optionValues[i]); //$NON-NLS-1$ + } else if ("Capital B".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("B", optionValues[i]); //$NON-NLS-1$ + } else if ("Capital E".equals(optionLabels[i])) { //$NON-NLS-1$ + assertEquals("E", optionValues[i]); //$NON-NLS-1$ + } else { + fail("Wrong number of option labels"); //$NON-NLS-1$ + } + } + } +} diff --git a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/BugTests.java b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/BugTests.java index 932a1942e..35fa5887d 100644 --- a/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/BugTests.java +++ b/bundles/org.eclipse.equinox.compendium.tests/src/org/eclipse/equinox/metatype/tests/BugTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others + * Copyright (c) 2011 IBM Corporation and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,84 +10,54 @@ *******************************************************************************/ package org.eclipse.equinox.metatype.tests; -import junit.framework.TestCase; -import org.eclipse.equinox.compendium.tests.Activator; -import org.eclipse.osgi.tests.bundles.BundleInstaller; import org.osgi.framework.Bundle; -import org.osgi.framework.ServiceReference; import org.osgi.service.metatype.*; -public class BugTests extends TestCase { +public class BugTests extends AbstractTest { private Bundle bundle; - private BundleInstaller bundleInstaller; - private MetaTypeService metaType; - private ServiceReference metaTypeReference; /* * A cardinality of zero should not require a default value to be specified. */ public void test334642() { - MetaTypeInformation mti = metaType.getMetaTypeInformation(bundle); + MetaTypeInformation mti = metatype.getMetaTypeInformation(bundle); assertNotNull("Metatype information not found", mti); //$NON-NLS-1$ ObjectClassDefinition ocd = mti.getObjectClassDefinition("org.eclipse.equinox.metatype.tests.tb3", null); //$NON-NLS-1$ assertNotNull("Object class definition not found", ocd); //$NON-NLS-1$ AttributeDefinition[] ads = ocd.getAttributeDefinitions(ObjectClassDefinition.ALL); assertNotNull("Attribute definitions not found", ads); //$NON-NLS-1$ - assertEquals("Wrong numbder of attribute definitions", 3, ads.length); //$NON-NLS-1$ + assertEquals("Wrong number of attribute definitions", 3, ads.length); //$NON-NLS-1$ - AttributeDefinition ad = findAttributeDefinition("password1", ads); //$NON-NLS-1$ + AttributeDefinition ad = findAttributeDefinitionById("password1", ads); //$NON-NLS-1$ assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ assertEquals("Wrong cardinality", 0, ad.getCardinality()); //$NON-NLS-1$ assertNull("Default value should be null", ad.getDefaultValue()); //$NON-NLS-1$ assertNotNull("Validation should be present", ad.validate(getFirstDefaultValue(ad.getDefaultValue()))); //$NON-NLS-1$ assertTrue("Validation should fail", ad.validate(getFirstDefaultValue(ad.getDefaultValue())).length() > 0); //$NON-NLS-1$ - ad = findAttributeDefinition("password2", ads); //$NON-NLS-1$ + ad = findAttributeDefinitionById("password2", ads); //$NON-NLS-1$ assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ assertEquals("Wrong cardinality", 0, ad.getCardinality()); //$NON-NLS-1$ assertNull("Default value should be null", ad.getDefaultValue()); //$NON-NLS-1$ assertNotNull("Validation should be present", ad.validate(getFirstDefaultValue(ad.getDefaultValue()))); //$NON-NLS-1$ assertTrue("Validation should fail", ad.validate(getFirstDefaultValue(ad.getDefaultValue())).length() > 0); //$NON-NLS-1$ - ad = findAttributeDefinition("string1", ads); //$NON-NLS-1$ + ad = findAttributeDefinitionById("string1", ads); //$NON-NLS-1$ assertNotNull("Attribute definition not found", ad); //$NON-NLS-1$ assertEquals("Wrong cardinality", 0, ad.getCardinality()); //$NON-NLS-1$ assertEquals("Only one default value should exist", 1, ad.getDefaultValue().length); //$NON-NLS-1$ assertEquals("Wrong default value", "Hello, world!", getFirstDefaultValue(ad.getDefaultValue())); //$NON-NLS-1$ //$NON-NLS-2$ - assertNull("Validation should not be present", ad.validate(getFirstDefaultValue(ad.getDefaultValue()))); //$NON-NLS-1$ + assertValidationPass(escape(getFirstDefaultValue(ad.getDefaultValue())), ad); } protected void setUp() throws Exception { - Activator.getBundle(Activator.BUNDLE_METATYPE).start(); - metaTypeReference = Activator.getBundleContext().getServiceReference(MetaTypeService.class.getName()); - metaType = (MetaTypeService) Activator.getBundleContext().getService(metaTypeReference); - bundleInstaller = new BundleInstaller("bundle_tests/metatype", Activator.getBundleContext()); //$NON-NLS-1$ + super.setUp(); bundle = bundleInstaller.installBundle("tb3"); //$NON-NLS-1$ bundle.start(); } protected void tearDown() throws Exception { - bundleInstaller.shutdown(); - Activator.getBundleContext().ungetService(metaTypeReference); - Activator.getBundle(Activator.BUNDLE_METATYPE).stop(); - } - - private String getFirstDefaultValue(String[] defaultValues) { - if (defaultValues == null || defaultValues.length == 0) - return null; - return defaultValues[0]; - } - - private AttributeDefinition findAttributeDefinition(String id, AttributeDefinition[] ads) { - if (id == null || ads == null) - return null; - for (int i = 0; i < ads.length; i++) { - if (ads[i] == null) - continue; - if (id.equals(ads[i].getID())) { - return ads[i]; - } - } - return null; + bundle.stop(); + super.tearDown(); } } |