You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2008/02/05 10:29:49 UTC
svn commit: r618587 -
/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java
Author: kristwaa
Date: Tue Feb 5 01:29:48 2008
New Revision: 618587
URL: http://svn.apache.org/viewvc?rev=618587&view=rev
Log:
DERBY-3369: Extend jdbcapi.DataSourceReferenceTest to handle data sources with differing property sets. This version of the test should test a little bit more than the previous version, but in general the approach is the same.
Patch file: derby-3369-1a.diff
Modified:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java?rev=618587&r1=618586&r2=618587&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java Tue Feb 5 01:29:48 2008
@@ -27,7 +27,8 @@
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Properties;
import javax.naming.Reference;
import javax.naming.Referenceable;
@@ -44,298 +45,443 @@
/**
- * Test obtaining a javax.naming.Reference from a Derby data source
- * and recreating a Derby data source from it. Tests that the recreated
- * value has the same value for all the properties the data source supports.
- * The list of properties is obtained dynamically from the getXXX methods
- * that return int, String, boolean, short, long. Should Derby data sources
- * support any other bean property types then this test should be modified
- * to pick them up and handle them. Hopefully the test should fail when such
- * a property is added.
- *
+ * Test obtaining a <code>javax.naming.Reference</code> from a Derby data
+ * source and recreating a Derby data source from it.
+ * <p>
+ * Tests that the recreated value has the same value for all the properties
+ * the data source supports. The list of properties is obtained
+ * dynamically from the getter methods that return int, String, boolean,
+ * short and long. Should Derby data sources support any other bean
+ * property types then this test should be modified to pick them up and
+ * handle them. The test will fail when such a property is added.
+ * <p>
+ * Default values of the properties are also tested. Default and set
+ * values of the properties must be specified by creating a data source
+ * descriptor.
+ * <p>
* At no point does this test attempt to connect using these data sources.
*/
-public class DataSourceReferenceTest extends BaseJDBCTestCase {
+public class DataSourceReferenceTest
+ extends BaseJDBCTestCase {
- private static String[][][] expectedValues = {
- // org.apache.derby.jdbc.Embedded*DataSource
- {{"attributesAsPassword", "false"}, null, null, null, null, null,
- {"loginTimeout", "0"}, null, null, null},
- {{"attributesAsPassword", "true"},
- {"connectionAttributes", "XX_connectionAttributes_2135"},
- {"createDatabase", "create"},
- {"dataSourceName", "XX_dataSourceName_1420"},
- {"databaseName", "XX_databaseName_1206"},
- {"description", "XX_description_1188"},
- {"loginTimeout", "1280"},
- {"password", "XX_password_883"},
- {"shutdownDatabase", "shutdown"},
- {"user", "XX_user_447"}},
- // org.apache.derby.jdbc.Client*DataSource
- { null, null, null, null, null, {"loginTimeout", "0"}, null,
- {"portNumber", "tmpportno"},
- {"retrieveMessageText", "true"},
- {"securityMechanism", "4"},
- {"serverName", "tmphostName"}, null,
- {"ssl","off"}, null, null,
- {"traceFileAppend", "false"},
- {"traceLevel", "-1"},
- {"user", "tmpUserName"}},
- {{"connectionAttributes", "XX_connectionAttributes_2135"},
- {"createDatabase", "create"},
- {"dataSourceName", "XX_dataSourceName_1420"},
- {"databaseName", "XX_databaseName_1206"},
- {"description", "XX_description_1188"},
- {"loginTimeout", "1280"},
- {"password", "XX_password_883"},
- {"portNumber", "1070"},
- {"retrieveMessageText", "false"},
- {"securityMechanism", "1805"},
- {"serverName", "XX_serverName_1048"},
- {"shutdownDatabase", "shutdown"},
- {"ssl","basic"},
- {"traceDirectory", "XX_traceDirectory_1476"},
- {"traceFile", "XX_traceFile_911"},
- {"traceFileAppend", "true"},
- {"traceLevel", "1031"},
- {"user", "XX_user_447"}}
- };
-
+ /** Lookup constant for the descriptor array. */
+ private static final int BASE_DS = 0;
+ /** Lookup constant for the descriptor array. */
+ private static final int POOL_DS = 1;
+ /** Lookup constant for the descriptor array. */
+ private static final int XA_DS = 2;
+
+ /** Descriptor for the basic embedded data source. */
+ private static final DataSourceDescriptor BASE_EMBEDDED_DS =
+ new DataSourceDescriptor("Basic embedded data source");
+
+ static {
+ BASE_EMBEDDED_DS.addProperty("attributesAsPassword", "true", "false");
+ BASE_EMBEDDED_DS.addProperty("connectionAttributes",
+ "XX_connectionAttributes_2135");
+ BASE_EMBEDDED_DS.addProperty("createDatabase", "create");
+ BASE_EMBEDDED_DS.addProperty("dataSourceName",
+ "XX_dataSourceName_1420");
+ BASE_EMBEDDED_DS.addProperty("databaseName", "XX_databaseName_1206");
+ BASE_EMBEDDED_DS.addProperty("description", "XX_description_1188");
+ BASE_EMBEDDED_DS.addProperty("loginTimeout", "1280", "0");
+ BASE_EMBEDDED_DS.addProperty("password", "XX_password_883");
+ BASE_EMBEDDED_DS.addProperty("shutdownDatabase", "shutdown");
+ BASE_EMBEDDED_DS.addProperty("user", "XX_user_447");
+ }
+
+ /** Descriptor for the basic client data source. */
+ private static final DataSourceDescriptor BASE_CLIENT_DS =
+ new DataSourceDescriptor("Basic client data source");
+
+ static {
+ // Properties with default values
+ BASE_CLIENT_DS.addProperty("loginTimeout", "1280", "0");
+ BASE_CLIENT_DS.addProperty("portNumber", "1070", "1527");
+ BASE_CLIENT_DS.addProperty("retrieveMessageText", "false", "true");
+ BASE_CLIENT_DS.addProperty("securityMechanism", "1851", "4");
+ BASE_CLIENT_DS.addProperty("serverName", "tmpHostName", "localhost");
+ BASE_CLIENT_DS.addProperty("ssl", "basic", "off");
+ BASE_CLIENT_DS.addProperty("user", "XX_user_447", "APP");
+ // Properties without default values.
+ BASE_CLIENT_DS.addProperty("connectionAttributes",
+ "XX_connectionAttributes_2135");
+ BASE_CLIENT_DS.addProperty("createDatabase", "create");
+ BASE_CLIENT_DS.addProperty("databaseName", "XX_databaseName_1206");
+ BASE_CLIENT_DS.addProperty("dataSourceName", "XX_dataSourceName_1420");
+ BASE_CLIENT_DS.addProperty("description", "XX_description_1188");
+ BASE_CLIENT_DS.addProperty("password", "XX_password_883");
+ BASE_CLIENT_DS.addProperty("shutdownDatabase", "shutdown");
+ BASE_CLIENT_DS.addProperty("traceFile", "XX_traceFile_911");
+ BASE_CLIENT_DS.addProperty("traceFileAppend", "true", "false");
+ BASE_CLIENT_DS.addProperty("traceLevel", "1031", "-1");
+ BASE_CLIENT_DS.addProperty("traceDirectory", "XX_traceDirectory_1476");
+ }
+
+
+ /**
+ * Creates a new fixture.
+ *
+ * @param name fixture name
+ */
public DataSourceReferenceTest(String name) {
super(name);
}
-
+
+ /**
+ * Creates a suite with tests for both embedded and client data sources.
+ *
+ * @return A suite with the appropriate tests.
+ */
public static Test suite() {
- if (JDBC.vmSupportsJSR169())
- {
- // Referencable is not supported with JSR169
- TestSuite suite =
- new TestSuite("DatasourceTest cannot run with JSR169");
- return suite;
- }
- else
- {
- return
- TestConfiguration.defaultSuite(DataSourceReferenceTest.class);
- }
- }
-
- /**
- * Test a data source
- * <OL>
- * <LI> Create an empty one from the class name
- * <LI> Discover the property list
- * <LI> Create a reference and recreate a data source
- * <LI> Compare the two
- * <LI> Serialize the data source and recreate
- * <LI> Compare the two
- * <LI> Set every property for the data source
- * <LI> Create a reference and recreate a data source
- * <LI> Compare the two
- * </OL>
- * @throws Exception
- */
- public static void testDSReference() throws Exception
- {
- String ds;
- ds = JDBCDataSource.getDataSource().getClass().getName();
- int expectedArray=0;
- if (usingDerbyNetClient())
- expectedArray = 2;
- assertDataSourceReference(expectedArray, ds);
- ds = J2EEDataSource.getConnectionPoolDataSource().getClass().getName();
- assertDataSourceReference(expectedArray, ds);
- ds = J2EEDataSource.getXADataSource().getClass().getName();
- assertDataSourceReference(expectedArray, ds);
- }
-
- public static void assertDataSourceReference(
- int expectedArrayIndex, String dsName) throws Exception {
-
- if (usingDerbyNetClient())
- {
- expectedValues[expectedArrayIndex][7][1] =
- String.valueOf(TestConfiguration.getCurrent().getPort());
- expectedValues[expectedArrayIndex][10][1] =
- TestConfiguration.getCurrent().getHostName();
- expectedValues[expectedArrayIndex][17][1] =
- TestConfiguration.getCurrent().getUserName();
- }
-
- Object ds = Class.forName(dsName).newInstance();
-
- println("DataSource class " + dsName);
- String[] properties = getPropertyBeanList(ds);
- assertEquals(
- expectedValues[expectedArrayIndex+1].length, properties.length);
- println(" property list");
-
- for (int i = 0; i < properties.length; i++)
- {
- assertEquals(
- expectedValues[expectedArrayIndex+1][i][0], properties[i]);
- println(" " + properties[i]);
- }
-
- Referenceable refDS = (Referenceable) ds;
-
- Reference dsAsReference = refDS.getReference();
-
+ Test suite;
+ if (JDBC.vmSupportsJSR169()) {
+ // Referenceable is not supported with JSR169
+ suite = new TestSuite("DatasourceTest cannot run with JSR169");
+ } else {
+ suite = TestConfiguration.defaultSuite(
+ DataSourceReferenceTest.class);
+ }
+ return suite;
+ }
+
+ /**
+ * Tests a data source, with focus on serialization/deserialization.
+ * <p>
+ * For each data source, the following actions are performed:
+ * <ol> <li>Create an empty data source from the class name.
+ * <li>Discover and validate the bean property list.
+ * <li>Create a reference and recreate the data source.
+ * <li>Compare the original and the empty recreated data source.
+ * <li>Serialize the data source and recreate.
+ * <li>Compare the original and the deserialized data source.
+ * <li>Set a value for every property of the data source.
+ * <li>Create a reference and recreate the data source.
+ * <li>Compare the populated original and the recreated data source.
+ * <li>Serialize the populated data source and recreate.
+ * <li>Compare the populated original and the deserialized data source.
+ * </ol>
+ *
+ * @throws Exception on a wide variety of error conditions...
+ */
+ public void testDataSourceReference()
+ throws Exception {
+ DataSourceDescriptor[] descriptors;
+ if (usingDerbyNetClient()) {
+ // Specify client data source descriptors.
+ descriptors = new DataSourceDescriptor[] {
+ BASE_CLIENT_DS, // Base
+ BASE_CLIENT_DS, // Pool
+ BASE_CLIENT_DS // XA
+ };
+ } else {
+ // Specify embedded data source descriptors.
+ descriptors = new DataSourceDescriptor[] {
+ BASE_EMBEDDED_DS, // Base
+ BASE_EMBEDDED_DS, // Pool
+ BASE_EMBEDDED_DS // XA
+ };
+ }
+ // Test basic data source.
+ String className = JDBCDataSource.getDataSource().getClass().getName();
+ println("Testing base data source: " + className);
+ assertDataSourceReference(descriptors[BASE_DS], className);
+
+ // Test connection pool data source.
+ className =
+ J2EEDataSource.getConnectionPoolDataSource().getClass().getName();
+ println("Testing connection pool data source: " + className);
+ assertDataSourceReference(descriptors[POOL_DS], className);
+
+ // Test XA data source.
+ className = J2EEDataSource.getXADataSource().getClass().getName();
+ println("Testing XA data source: " + className);
+ assertDataSourceReference(descriptors[XA_DS], className);
+ }
+
+
+ /**
+ * Performs the test sequence in the data source.
+ *
+ * @param dsDesc data source descriptor
+ * @param className class name of the data source
+ * @throws Exception on a wide variety of error conditions...
+ *
+ * @see #testDataSourceReference
+ */
+ private void assertDataSourceReference(
+ DataSourceDescriptor dsDesc,
+ String className)
+ throws Exception {
+ // Instantiate a new data source object and get all its properties.
+ Object dsObj = Class.forName(className).newInstance();
+ String[] properties = getPropertyBeanList(dsObj);
+ // Validate property set (existence and naming).
+ assertDataSourceProperties(dsDesc, properties);
+ // Test recreating the data source
+ assertDataSourceReferenceEmpty(dsDesc, className);
+ assertDataSourceReferencePopulated(dsDesc, className);
+ }
+
+ /**
+ * Asserts that the properties that are in the data source descriptor are
+ * found in the list of data source properties, and that the data source
+ * does not contain properties that are not in the descriptor.
+ * <p>
+ * No property values are verified in this assert method.
+ *
+ * @param dsDesc data source descriptor
+ * @param properties list of actual data source properties
+ */
+ private void assertDataSourceProperties(
+ DataSourceDescriptor dsDesc,
+ String[] properties) {
+ println("Testing data source bean properties.");
+ // Validate the identified property names.
+ for (int i=0; i < properties.length; i++) {
+ assertTrue("Property '" + properties[i] + "' not in descriptor '" +
+ dsDesc.getName() + "'",
+ dsDesc.hasProperty(properties[i]));
+ }
+ // Check that all keys defined by the descriptor is found, and that
+ // there is only one of each in the data source property list.
+ Iterator descPropIter = dsDesc.getPropertyIterator();
+ while (descPropIter.hasNext()) {
+ String descProp = (String)descPropIter.next();
+ boolean match = false;
+ // Iterate through all the data source properties.
+ for (int i=0; i < properties.length; i++) {
+ if (properties[i].equals(descProp)) {
+ if (match) {
+ fail("Duplicate entry '" + descProp + "' in data " +
+ "source property list");
+ }
+ // Don't break, continue to look for duplicates.
+ match = true;
+ }
+ }
+ assertTrue("Property '" + descProp + "' not found in data source " +
+ "property list", match);
+ }
+ // Check if the expected number of properties are found.
+ // Do this last to hopefully get a more descriptive failure
+ // message which includes the property name above.
+ assertEquals(dsDesc.getPropertyCount(), properties.length);
+ }
+
+ /**
+ * Make sure it is possible to create a new data source using
+ * <code>Referencable</code>, that the new instance has the correct
+ * default values set for the bean properties and finally that the
+ * data source can be serialized/deserialized.
+ *
+ * @param dsDesc data source descriptor
+ * @param className data source class name
+ * @throws Exception on a wide variety of error conditions...
+ */
+ private void assertDataSourceReferenceEmpty(DataSourceDescriptor dsDesc,
+ String className)
+ throws Exception {
+ println("Testing recreated empty data source.");
+ // Create an empty data source.
+ Object ds = Class.forName(className).newInstance();
+ Referenceable refDs = (Referenceable)ds;
+ Reference dsAsReference = refDs.getReference();
String factoryClassName = dsAsReference.getFactoryClassName();
-
- ObjectFactory factory =
- (ObjectFactory) Class.forName(factoryClassName).newInstance();
-
- Object recreatedDS =
+ ObjectFactory factory =
+ (ObjectFactory)Class.forName(factoryClassName).newInstance();
+ Object recreatedDs =
factory.getObjectInstance(dsAsReference, null, null, null);
-
- println(" empty DataSource recreated using Reference as " +
- recreatedDS.getClass().getName());
- // empty DataSource recreated using Reference should not be
- // the same as the original
- assertNotSame(recreatedDS, ds);
-
- compareDS(expectedArrayIndex, properties, ds, recreatedDS);
-
- // now serialize and recreate
+ // Empty, recreated data source should not be the same as the one we
+ // created earlier on.
+ assertNotNull("Recreated datasource is <null>", recreatedDs);
+ assertNotSame(recreatedDs, ds);
+ compareDataSources(dsDesc, ds, recreatedDs, true);
+
+ // Serialize and recreate data source with default values.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(ds);
oos.flush();
oos.close();
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
- recreatedDS = ois.readObject();
- println(" empty DataSource recreated using serialization");
- compareDS(expectedArrayIndex, properties, ds, recreatedDS);
-
- // now populate the data source
- for (int i = 0; i < properties.length; i++)
- {
- String property = properties[i];
+ recreatedDs = ois.readObject();
+ compareDataSources(dsDesc, ds, recreatedDs, true);
+ }
+
+ /**
+ * Make sure it is possible to recreate and serialize/deserialize a
+ * populated data source.
+ * <p>
+ * Populated means the various bean properties have non-default
+ * values set.
+ *
+ * @param dsDesc data source descriptor
+ * @param className data source class name
+ * @throws Exception on a wide variety of error conditions...
+ */
+ private void assertDataSourceReferencePopulated(
+ DataSourceDescriptor dsDesc,
+ String className)
+ throws Exception {
+ println("Testing recreated populated data source.");
+ Object ds = Class.forName(className).newInstance();
+ // Populate the data source.
+ Iterator propIter = dsDesc.getPropertyIterator();
+ while (propIter.hasNext()) {
+ String property = (String)propIter.next();
+ String value = dsDesc.getPropertyValue(property);
Method getMethod = getGet(property, ds);
-
Method setMethod = getSet(getMethod, ds);
-
- Class pt = getMethod.getReturnType();
-
- // generate a somewhat unique value for a property
- int val = 0;
- for (int j = 0; j < property.length(); j++)
- val += property.charAt(j);
-
- if (pt.equals(Integer.TYPE))
- {
- setMethod.invoke(ds, new Object[] {new Integer(val)});
- continue;
- }
- if (pt.equals(String.class))
- {
- String value;
- if (property.equals("createDatabase"))
- value = "create";
- else if (property.equals("shutdownDatabase"))
- value = "shutdown";
- else if (property.equals("ssl"))
- value = "basic";
- else
- value = "XX_" + property + "_" + val;
-
+ Class paramType = getMethod.getReturnType();
+
+ if (paramType.equals(Integer.TYPE)) {
+ setMethod.invoke(ds, new Object[] {Integer.valueOf(value)});
+ } else if (paramType.equals(String.class)) {
setMethod.invoke(ds, new Object[] {value});
- continue;
+ } else if (paramType.equals(Boolean.TYPE)) {
+ setMethod.invoke(ds, new Object[] {Boolean.valueOf(value)});
+ } else if (paramType.equals(Short.TYPE)) {
+ setMethod.invoke(ds, new Object[] {Short.valueOf(value)});
+ } else if (paramType.equals(Long.TYPE)) {
+ setMethod.invoke(ds, new Object[] {Long.valueOf(value)});
+ } else {
+ fail("'" + property + "' not settable - update test!!");
}
- if (pt.equals(Boolean.TYPE))
- {
- // set the opposite value
- Object gbv = getMethod.invoke(ds, null);
- Boolean sbv =
- Boolean.FALSE.equals(gbv) ? Boolean.TRUE : Boolean.FALSE;
- setMethod.invoke(ds, new Object[] {sbv});
- continue;
- }
- if (pt.equals(Short.TYPE))
- {
- setMethod.invoke(ds, new Object[] {new Short((short)val)});
- continue;
- }
- if (pt.equals(Long.TYPE))
- {
- setMethod.invoke(ds, new Object[] {new Long(val)});
- continue;
- }
- fail ( property + " not settable - update test!!");
}
-
- dsAsReference = refDS.getReference();
- recreatedDS =
+
+ Referenceable refDs = (Referenceable)ds;
+ Reference dsAsReference = refDs.getReference();
+ String factoryClassName = dsAsReference.getFactoryClassName();
+ ObjectFactory factory =
+ (ObjectFactory)Class.forName(factoryClassName).newInstance();
+ Object recreatedDs =
factory.getObjectInstance(dsAsReference, null, null, null);
- println(" populated DataSource recreated using Reference as "
- + recreatedDS.getClass().getName());
- // again, recreated should not be same instance
- assertNotSame(recreatedDS, ds);
-
- compareDS(expectedArrayIndex+1, properties, ds, recreatedDS);
-
- // now serialize and recreate
- baos = new ByteArrayOutputStream();
- oos = new ObjectOutputStream(baos);
+ // Recreated should not be same instance as original.
+ assertNotSame(recreatedDs, ds);
+ compareDataSources(dsDesc, ds, recreatedDs, false);
+
+ // Serialize and recreate.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(ds);
oos.flush();
oos.close();
- bais = new ByteArrayInputStream(baos.toByteArray());
- ois = new ObjectInputStream(bais);
- recreatedDS = ois.readObject();
- println(" populated DataSource recreated using serialization");
- compareDS(expectedArrayIndex+1, properties, ds, recreatedDS);
- }
-
- private static String[] getPropertyBeanList(Object ds) throws Exception
- {
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ recreatedDs = ois.readObject();
+ compareDataSources(dsDesc, ds, recreatedDs, false);
+ }
+
+ /**
+ * Compares two data sources expected to be equal.
+ * <p>
+ * The data source descriptor is expected to contain both default values
+ * and set values for the relevant bean properties of the data source(s).
+ *
+ * @param dsDesc data source descriptor
+ * @param ds original data source
+ * @param rds recreated data source
+ * @param useDefaultsForComparison <code>true</code> if the default values
+ * should be verified, <code>false</code> if the set values should be
+ * used for verification
+ * @throws Exception on a wide variety of error conditions...
+ * @throws AssertionFailedError if the data sources are not equal
+ */
+ private void compareDataSources(DataSourceDescriptor dsDesc,
+ Object ds, Object rds,
+ boolean useDefaultsForComparison)
+ throws Exception {
+ Iterator propIter = dsDesc.getPropertyIterator();
+ while (propIter.hasNext()) {
+ String property = (String)propIter.next();
+ Method getMethod = getGet(property, ds);
+
+ // Obtain value from original data source, then the recreated one.
+ Object dsValue = getMethod.invoke(ds, null);
+ Object rdsValue = getMethod.invoke(rds, null);
+
+ if (dsValue == null) {
+ assertNull(rdsValue);
+ } else {
+ assertEquals(dsValue, rdsValue);
+ }
+ // Make sure the value is correct.
+ if (useDefaultsForComparison) {
+ if (dsValue != null) {
+ assertEquals("Wrong default value for '" + property + "'",
+ dsDesc.getPropertyDefault(property),
+ dsValue.toString());
+ } else {
+ assertNull(dsDesc.getPropertyDefault(property));
+ }
+ } else if (dsValue != null) {
+ assertEquals("'" + property + "' has incorrect value",
+ dsDesc.getPropertyValue(property),
+ dsValue.toString());
+ } else {
+ // We got null from the data source, and we should have set all
+ // values to something else than null.
+ fail("Test does not handle this situation...");
+ }
+ }
+ }
+
+ /**
+ * Obtains a list of bean properties through reflection.
+ *
+ * @param ds the data source to investigate
+ * @return A list of bean property names.
+ */
+ private static String[] getPropertyBeanList(Object ds) {
Method[] allMethods = ds.getClass().getMethods();
-
ArrayList properties = new ArrayList();
- for (int i = 0; i < allMethods.length; i++)
- {
- Method m = allMethods[i];
- String methodName = m.getName();
+
+ for (int i = 0; i < allMethods.length; i++) {
+ Method method = allMethods[i];
+ String methodName = method.getName();
// Need at least getXX
- if (methodName.length() < 5)
- continue;
- if (!methodName.startsWith("get"))
- continue;
- if (m.getParameterTypes().length != 0)
+ if (methodName.length() < 5 || !methodName.startsWith("get") ||
+ method.getParameterTypes().length != 0) {
continue;
+ }
- Class rt = m.getReturnType();
-
- if (rt.equals(Integer.TYPE) || rt.equals(String.class) ||
- rt.equals(Boolean.TYPE) || rt.equals(Short.TYPE) ||
- rt.equals(Long.TYPE))
- {
- // valid Java Bean property
- String beanName = methodName.substring(3,4).toLowerCase()
- + methodName.substring(4);
+ Class rt = method.getReturnType();
+ if (rt.equals(Integer.TYPE) || rt.equals(String.class) ||
+ rt.equals(Boolean.TYPE) || rt.equals(Short.TYPE) ||
+ rt.equals(Long.TYPE)) {
+ // Valid Java Bean property.
+ // Convert name:
+ // getPassword -> password
+ // getRetrieveMessageText -> retrieveMessageText
+ String beanName = methodName.substring(3,4).toLowerCase()
+ + methodName.substring(4);
properties.add(beanName);
- continue;
+ } else {
+ assertFalse("Method '" + methodName + "' with primitive " +
+ "return type not supported - update test!!",
+ rt.isPrimitive());
}
-
-
- assertFalse(rt.isPrimitive());
- println("if rt.isPrimitive, method " + methodName +
- " not supported - update test!!");
-
- }
-
- String[] propertyList = (String[]) properties.toArray(new String[0]);
-
- Arrays.sort(propertyList);
-
- return propertyList;
- }
-
- private static Method getGet(String property, Object ds) throws Exception
- {
+ }
+
+ return (String[])properties.toArray(new String[properties.size()]);
+ }
+
+ /**
+ * Obtains the specified get method.
+ *
+ * @param property property/method name
+ * @param ds data source object
+ * @return A method object.
+ *
+ * @throws NoSuchMethodException if the method does not exist
+ */
+ private static Method getGet(String property, Object ds)
+ throws NoSuchMethodException {
String methodName =
"get" + property.substring(0,1).toUpperCase()
+ property.substring(1);
@@ -343,43 +489,186 @@
return m;
}
- private static Method getSet(Method getMethod, Object ds) throws Exception
- {
+ /**
+ * Obtains the specified set method.
+ *
+ * @param getMethod the corresponding get method
+ * @param ds data source object
+ * @return A method object.
+ *
+ * @throws NoSuchMethodException if the method does not exist
+ */private static Method getSet(Method getMethod, Object ds)
+ throws NoSuchMethodException {
String methodName = "s" + getMethod.getName().substring(1);
Method m = ds.getClass().getMethod(
methodName, new Class[] {getMethod.getReturnType()});
return m;
- }
+ }
- private static void compareDS(int expectedValuesArrayIndex,
- String[] properties, Object ds, Object rds) throws Exception
- {
- println(" Start compare recreated");
- for (int i = 0; i < properties.length; i++)
- {
- Method getMethod = getGet(properties[i], ds);
-
- Object dsValue = getMethod.invoke(ds, null);
- Object rdsValue = getMethod.invoke(rds, null);
-
- if (dsValue == null)
- {
- // properties[i] originally null, should be recreated as null.
- assertNull(rdsValue);
- }
- else
- {
- // properties[i] originally dsValue, should be recreated as
- // rdsValue
- assertEquals(dsValue, rdsValue);
+ /**
+ * A class describing the bean properties of a data source.
+ * <p>
+ * A data source is a class implementing
+ * <code>javax.sql.CommonDataSource</code>.
+ * <p>
+ * The data source description consists of the following:
+ * <ul> <li>A list of property names.
+ * <li>A list of default values for the properties that have a default.
+ * <li>A list of set values for properties.
+ * </ul>
+ * In addition it has a name for convenience.
+ */
+ private static class DataSourceDescriptor {
+
+ /** Name of the description. */
+ private final String dsName;
+ /**
+ * Set values for the data source being described.
+ * <p>
+ * Note that the keys of this property object describe which bean
+ * properties exist for the data source.
+ */
+ private final Properties propertyValues;
+ /**
+ * Default values for bean properties having a default.
+ * <p>
+ * Note that not all properties have a default, and the data source
+ * may therefore have more properties than there entries in this
+ * list of properties.
+ */
+ private final Properties propertyDefaults;
+
+ /**
+ * Creates a new data source description.
+ *
+ * @param dsName convenience name for the description/source
+ */
+ DataSourceDescriptor(String dsName) {
+ this.dsName = dsName;
+ this.propertyValues = new Properties();
+ this.propertyDefaults = new Properties();
+ }
+
+ /**
+ * Creates a new data source description, based off an existing
+ * description.
+ * <p>
+ * All properties and values defined in the existing descriptor will
+ * also be defined in the new descriptor.
+ *
+ * @param dsName convenience name for the description/source
+ * @param copyFrom existing descriptor to copy properties/values from
+ */
+ DataSourceDescriptor(String dsName, DataSourceDescriptor copyFrom) {
+ this.dsName = dsName;
+ this.propertyValues = new Properties();
+ this.propertyValues.putAll(copyFrom.propertyValues);
+ this.propertyDefaults = new Properties(copyFrom.propertyDefaults);
+ this.propertyDefaults.putAll(copyFrom.propertyDefaults);
+ }
+
+ /**
+ * Returns the convenience name of this descriptor.
+ *
+ * @return A convenience name.
+ */
+ String getName() {
+ return this.dsName;
+ }
+
+ /**
+ * Adds a property to the description, with a value and no associated
+ * default value.
+ *
+ * @param name property name
+ * @param value property value
+ * @throws NullPointerException if <code>name</code> or
+ * <code>value</code> is <code>null</code>
+ */
+ void addProperty(String name, String value) {
+ this.propertyValues.setProperty(name, value);
+ }
+
+ /**
+ * Adds a property to the description, with a value and an associated
+ * default value.
+ *
+ * @param name property name
+ * @param value property value
+ * @param defaultValue default property value
+ * @throws NullPointerException if <code>name</code>, <code>value</code>
+ * or <code>defaultValue</code> is <code>null</code>
+ */
+ void addProperty(String name, String value, String defaultValue) {
+ this.propertyValues.setProperty(name, value);
+ this.propertyDefaults.setProperty(name, defaultValue);
+ }
+
+ /**
+ * Returns the value of the specified property.
+ *
+ * @param name property name
+ * @return The value set for this property.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>
+ * @throws AssertionFailedError if the property name is not defined by
+ * this descriptor
+ */
+ String getPropertyValue(String name) {
+ if (!this.propertyValues.containsKey(name)) {
+ fail("Property '" + name + "' not in data source descriptor '" +
+ dsName + "'");
}
- if (dsValue != null)
- {
- assertEquals(expectedValues[expectedValuesArrayIndex][i][0],
- properties[i]);
- assertEquals(expectedValues[expectedValuesArrayIndex][i][1],
- dsValue.toString());
+ return this.propertyValues.getProperty(name);
+ }
+
+ /**
+ * Returns the default value for the specified property.
+ *
+ * @param name property name
+ * @return The default value if specified, <code>null<code> if a default
+ * value is not specified.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>
+ * @throws AssertionFailedError if the property name is not defined by
+ * this descriptor
+ */
+ String getPropertyDefault(String name) {
+ if (!this.propertyValues.containsKey(name)) {
+ fail("Property '" + name + "' not in data source descriptor '" +
+ dsName + "'");
}
+ return this.propertyDefaults.getProperty(name, null);
}
- }
+
+ /**
+ * Returns an iterator over all bean property names.
+ *
+ * @return An iterator.
+ */
+ Iterator getPropertyIterator() {
+ return this.propertyValues.keySet().iterator();
+ }
+
+ /**
+ * Tells if the specified property is defined by this descriptor.
+ *
+ * @param name property name
+ * @return <code>true</code> if defined, <code>false</code> if not.
+ */
+ boolean hasProperty(String name) {
+ return this.propertyValues.containsKey(name);
+ }
+
+ /**
+ * Returns the number of bean properties defined by this descriptor.
+ *
+ * @return The number of bean properties.
+ */
+ int getPropertyCount() {
+ return this.propertyValues.size();
+ }
+ } // End class DataSourceDescriptor
}