Index: java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SimpleDataSourceTest.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SimpleDataSourceTest.java	(revision 0)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/SimpleDataSourceTest.java	(revision 0)
@@ -0,0 +1,500 @@
+package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Hashtable;
+import javax.sql.DataSource;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.derby.jdbc.EmbeddedSimpleDataSource;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test the various embedded DataSource implementations of Derby.
+ * 
+ * Performs SecurityCheck analysis on the JDBC objects returned.
+ * This is because this test returns to the client a number of
+ * different implementations of Connection, Statement etc.
+ * 
+ * @see org.apache.derbyTesting.functionTests.util.SecurityCheck
+ *
+ */
+public class SimpleDataSourceTest extends BaseJDBCTestCase {
+
+    private static final String dbName = 
+        TestConfiguration.getCurrent().getDefaultDatabaseName();
+    
+    /**
+     * A hashtable of opened connections.  This is used when checking to
+     * make sure connection strings are unique; we need to make sure all
+     * the connections are closed when we are done, so they are stored
+     * in this hashtable
+     */
+    protected static Hashtable conns = new Hashtable();
+    
+    /**
+     * Hang onto the SecurityCheck class while running the
+     * tests so that it is not garbage collected during the
+     * test and lose the information it has collected,
+     * in case it should get printed out.
+     */
+    private final Object nogc = SecurityCheck.class;
+    
+    public SimpleDataSourceTest(String name) {
+        super(name);
+    }
+    
+    /**
+     * Return a suite of tests that are run with both client and embedded
+     * 
+     * @param postfix suite name postfix
+     * @return A suite of tests to be run
+     */
+    private static Test baseSuite(String postfix) {
+        TestSuite suite = new TestSuite("SimpleDataSourceTests" + postfix);
+        suite.addTest(new SimpleDataSourceTest("testBadConnectionAttributeSyntax"));
+        suite.addTest(new SimpleDataSourceTest("testDescriptionProperty"));
+        suite.addTest(new SimpleDataSourceTest("testAllDataSources"));
+        suite.addTest(new SimpleDataSourceTest("testDSRequestAuthentication"));
+        suite.addTest(new SimpleDataSourceTest("testJira95ds"));
+        return suite;
+    }
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite("SimpleDataSourceTest suite");
+        // Add tests that will run with both embedded
+        suite.addTest(baseSuite(":embedded"));
+        // wrap all in CleanDatabaseTestSetup that creates all database
+        // objects any fixture might need.
+        // Note that not all fixtures need (all of) these.
+        return new CleanDatabaseTestSetup(suite) {
+            /**
+             * Create and populate database objects
+             * 
+             * @see org.apache.derbyTesting.junit.CleanDatabaseTestSetup#decorateSQL(java.sql.Statement)
+             */
+            protected void decorateSQL(Statement s) throws SQLException {
+                s.executeUpdate("create table intTable(i int)");
+            }
+        };
+    }
+    
+    /* comment out. leaving in, just in case it's ever relevant.
+     * when uncommented, this will run when network server tests are
+     * started, and then reflect the results of the embedded checks.
+    // perform security analysis of the public api for the embedded engine
+    public void testDataSourceAPI() throws SQLException, ClassNotFoundException
+    {
+        SecurityCheck.report();
+    }
+     */
+    
+    public void testAllDataSources() throws SQLException, Exception
+    {
+        Connection dmc = getConnection();
+        
+        Object[] expectedValues = {
+            new Integer(ResultSet.HOLD_CURSORS_OVER_COMMIT), "XJ010",
+            new Integer(2), new Boolean(true), new Boolean(false)};
+
+        if (usingEmbedded())
+            assertTenConnectionsUnique();
+
+        DataSource dscs = JDBCDataSource.getDataSource();
+        if (usingEmbedded()) 
+                assertToString(dscs);
+
+        DataSource ds = dscs;
+        assertConnectionOK(expectedValues, "DataSource", ds.getConnection());
+        
+        DataSource dssimple = null;
+        // simple datasource is only supported with embedded
+        if (usingEmbedded())
+        {
+            EmbeddedSimpleDataSource realdssimple = 
+                new EmbeddedSimpleDataSource();
+            realdssimple.setDatabaseName(dbName);
+            ds = realdssimple;
+            dssimple = (DataSource)realdssimple;
+            assertConnectionOK(
+                expectedValues, "SimpleDataSource", ds.getConnection());
+        }
+    }            
+        
+    // test jira-derby 95 - a NullPointerException was returned when passing
+    // an incorrect database name, should now give error:
+    // XCY00 - invalid valid for property ...  
+    // with DataSource
+    public void testJira95ds() throws SQLException {
+        try {
+            DataSource ds = JDBCDataSource.getDataSource();
+            // non-existent database
+            JDBCDataSource.setBeanProperty(ds, "databaseName", "jdbc:derby:wombat");
+            ds.getConnection();
+            fail ("expected an SQLException!");
+        } catch (SQLException sqle) {
+            // DERBY-2498: with client, getting a NullPointerException.
+            // Note also: the NPE does not occur with XADataSource - see
+            // testJira95xads().
+            if (usingEmbedded())
+                assertSQLState("XCY00", sqle);
+        } catch (Exception e) {
+            // DERBY-2498, when fixed, remove 'if'
+            if (usingEmbedded())
+                fail ("unexpected exception: " + e.toString());
+        }
+    } 
+
+    public void testBadConnectionAttributeSyntax() throws SQLException {
+        
+        // DataSource - bad connattr syntax
+        DataSource ds = JDBCDataSource.getDataSource();
+        JDBCDataSource.setBeanProperty(ds, "ConnectionAttributes", "bad");
+        try {
+            ds.getConnection();
+            fail ("should have seen an error");
+        } catch (SQLException e) {
+            if (usingEmbedded())
+                assertSQLState("XJ028", e);
+            else if (usingDerbyNetClient())
+                assertSQLState("XJ212", e);
+        } 
+    } // End testBadConnectionAttributeSyntax
+            
+    // Following test is similar to testClientDSConnectionAttributes, but
+    // for embedded datasources.
+    // This subtest does not run for network server, it uses
+    // setAttributesAsPassword, which isn't supported for client datasources.
+    public void testDSRequestAuthentication() throws SQLException {
+
+        if (usingDerbyNetClient())
+            return;
+        
+        EmbeddedSimpleDataSource ds = new EmbeddedSimpleDataSource();
+
+        // DataSource - EMPTY
+        dsConnectionRequests(new String[] {  
+             "XJ004","XJ004","XJ004","XJ004",
+             "XJ004","XJ004","XJ004","XJ004","XJ004"}, ds);
+ 
+        // DataSource - connectionAttributes=databaseName=wombat");
+        ds.setConnectionAttributes("databaseName=" + dbName);
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ004",
+            "XJ004","XJ004","XJ004","XJ004","XJ004"}, ds);
+        ds.setConnectionAttributes(null);
+        
+        TestConfiguration.getCurrent().shutdownDatabase();
+    }
+
+    /**
+     * Check that messageText connection attribute functions correctly.
+     * retrievemessagetext was tested in checkdriver, and derbynet/testij
+     * (but not tested for datasources), and in datasourcepermissions_net,
+     * but as it has nothing to do with permissions/authentication,
+     * this test seems a better place for it. 
+     *  
+     * @throws SQLException
+     */
+    public void testDescriptionProperty() 
+    throws SQLException, Exception {
+        
+        // DataSource - setDescription
+        subTestDataSourceDescription(JDBCDataSource.getDataSource());
+    }
+    
+    /**
+     * Utility method for testing setting and fetching the description
+     * property on a data source.
+     */
+    private void subTestDataSourceDescription(DataSource ds) throws Exception
+    {
+        String setDescription = 
+            "Everything you ever wanted to know about this datasource";
+        
+        JDBCDataSource.setBeanProperty(ds, "description", setDescription);
+        ds.getConnection();
+        assertEquals(setDescription, JDBCDataSource.getBeanProperty(ds, "description"));
+        JDBCDataSource.clearStringBeanProperty(ds, "description");
+        assertNull(JDBCDataSource.getBeanProperty(ds, "description"));      
+    }
+
+    /* -------------------- Other Helper Methods -------------------- */
+    
+    private static void dsConnectionRequests(
+        String[] expectedValues, DataSource ds) {
+
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(ds, "javax.sql.DataSource");
+        }
+        
+        try {
+            ds.getConnection();
+            if (!expectedValues[0].equals("OK"))
+                fail (" expected connection to fail, but was OK");
+        } catch (SQLException sqle) {
+            assertSQLState(expectedValues[0], sqle);
+        }
+        dsConnectionRequest(expectedValues[1], ds, null, null);
+        dsConnectionRequest(expectedValues[2], ds, "fred", null);
+        dsConnectionRequest(expectedValues[3], ds, "fred", "wilma");
+        dsConnectionRequest(expectedValues[4], ds, null, "wilma");
+        dsConnectionRequest(
+            expectedValues[5], ds, null, "databaseName=wombat");
+        dsConnectionRequest(
+            expectedValues[6], ds, "fred", "databaseName=wombat");
+        dsConnectionRequest(expectedValues[7], 
+            ds, "fred", "databaseName=wombat;password=wilma");
+        dsConnectionRequest(expectedValues[8], 
+            ds, "fred", "databaseName=wombat;password=betty");
+    }
+
+    private static void dsConnectionRequest(
+        String expectedValue, DataSource ds, String user, String ConnAttr)
+    {
+        try {
+            ds.getConnection(user, ConnAttr);
+            if (!expectedValue.equals("OK"))
+                fail (" expected connection to fail, but was OK");
+        } catch (SQLException sqle) {
+            assertSQLState(expectedValue, sqle);
+        }
+    }
+
+    private void assertConnectionOK(
+        Object[] expectedValues, String dsName, Connection conn) 
+    throws SQLException { 
+        
+        assertEquals(
+            ((Integer)expectedValues[0]).intValue(), conn.getHoldability());
+
+        // check it's a 3.0 connection object by checking if 
+        // set & release Savepoint is ok.
+        try {
+            conn.releaseSavepoint(conn.setSavepoint());
+            if (conn.getAutoCommit())
+                fail("expected a SQLExpection (savepoint with autocommit on");
+            if (!((String)expectedValues[1]).equals("OK"))
+                fail("expected a SQLExpection (savepoint with autocommit on");
+        } catch (SQLException sqle) {
+            // we expect savepoints exceptions because either
+            // it's a global transaction, or it's in auto commit mode.
+            if (conn.getAutoCommit())
+                assertSQLState("XJ010", sqle);
+            else if (((String)expectedValues[1]).equals("OK"))
+                fail ("unexpected JDBC 3.0 savepoint SQL Exception");
+            else 
+                assertSQLState((String)expectedValues[1], sqle);
+        }
+
+        // Running connection checks
+        // connection checks currently only implemented for Embedded
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(conn, "java.sql.Connection");
+            SecurityCheck.assertSourceSecurity(
+                conn.getMetaData(), "java.sql.DatabaseMetaData");
+        }
+
+        assertEquals(((Integer)expectedValues[2]).intValue(), 
+            conn.getTransactionIsolation());
+        assertEquals(((Boolean)expectedValues[3]).booleanValue(), 
+            conn.getAutoCommit());
+        assertEquals(((Boolean)expectedValues[4]).booleanValue(), 
+            conn.isReadOnly());
+
+        if (dsName.endsWith("DataSource"))
+            assertNull(conn.getWarnings());
+
+        Statement s1 = conn.createStatement();
+        assertStatementOK(dsName, conn, s1);
+        assertStatementOK(dsName, conn, conn.createStatement
+            (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY));
+
+        Connection c1 = conn.getMetaData().getConnection();
+        // c1 and conn should be the same connection object.
+        if (!usingDerbyNetClient() && dsName.indexOf("DataSource")>=0)
+            assertEquals(c1, conn);
+
+        assertConnectionPreClose(dsName, conn);
+        conn.close();
+
+        // method calls on a closed connection
+        try {
+            conn.close(); // expect no error
+        } catch (SQLException sqle) {
+            fail(" unexpected exception on <closedconn>.close() ");
+        }
+        try {
+            conn.createStatement();
+            fail (dsName + " <closedconn>.createStatement(), " +
+                "expected 08003 - No current connection");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+        try {
+            s1.execute("values 1");
+            fail(dsName + " <closedstmt>.execute(), " +
+                "expected 08003 - No current connection");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+    }
+
+    private void assertConnectionPreClose(String dsName, Connection conn) 
+    throws SQLException {
+
+        // before closing the connection, attempt to change holdability
+        // and readOnly
+        conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+
+        if (!dsName.equals("Nested2"))
+        {
+            try {
+                conn.setReadOnly(true);
+            } catch (SQLException sqle) {
+                // cannot set read-only in an active transaction, & sometimes
+                // connections are active at this point.
+                assertSQLState("25501", sqle);
+            }
+        }
+    }
+    
+    private void assertStatementOK(String dsName, Connection conn, Statement s)
+    throws SQLException {
+
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(s, "java.sql.Statement");
+        }
+
+        Connection c1 = s.getConnection();
+        if (c1 != conn)
+        {
+            // with DerbyNetClient and any kind of DataSource, this goes wrong
+            if (!usingDerbyNetClient() && (dsName.indexOf("DataSource") >= 0))
+                fail ("incorrect connection object returned for Statement.getConnection()");
+        }
+
+        s.addBatch("insert into intTable values 1");
+        s.addBatch("insert into intTable values 2,3");
+        int[] states = s.executeBatch();
+        if (states[0] != 1)
+            fail ("invalid update count for first batch statement");
+        if (states[1] != 2)
+            fail ("invalid update count for second batch statement");
+
+        ResultSet rs = s.executeQuery("VALUES 1");
+        if (rs.getStatement() != s)
+            fail ("incorrect Statement object returned for ResultSet.getStatement for " + dsName);
+        rs.close();
+        s.close();
+    }
+
+    /**
+     * Make sure this connection's string is unique (DERBY-243)
+     */
+    private static void assertToString(Connection conn) throws Exception
+    {
+        assertStringFormat(conn);
+        String str = conn.toString();
+
+        if ( conns.containsKey(str))
+        {
+            throw new Exception("ERROR: Connection toString() is not unique: " 
+                    + str);
+        }
+        conns.put(str, conn);
+    }
+
+    /**
+     * Check the format of the connection string.  This is the default test
+     * to run if this is not a BrokeredConnection class
+     */
+    private static void assertStringFormat(Connection conn) //throws Exception
+    {
+        assertStringPrefix(conn);
+    }
+
+    /**
+     * Make sure the connection string starts with the right prefix, which
+     * is the classname@hashcode.
+     *
+     * @return the expected prefix string, this is used in further string
+     *   format checking
+     */
+    private static String assertStringPrefix(Object conn) //throws Exception
+    {
+        String connstr = conn.toString();
+        String prefix = conn.getClass().getName() + "@" + conn.hashCode();
+        // Connection class and has code for connection string should
+        // match prefix
+        assertTrue(connstr.startsWith(prefix));
+
+        return prefix;
+    }
+
+    /**
+     * Check uniqueness of connection strings coming from a
+     * DataSouce
+     */
+    private static void assertToString(DataSource ds) throws Exception
+    {
+        clearConnections();
+
+        int numConnections = 10;
+        for ( int i = 0 ; i < numConnections ; i++ )
+        {
+            Connection conn = ds.getConnection();
+            assertToString(conn);
+        }
+
+        clearConnections();
+    }
+
+    /**
+     * Clear out and close connections in the connections
+     * hashtable. 
+     */
+    private static void clearConnections() throws SQLException
+    {
+        java.util.Iterator it = conns.values().iterator();
+        while ( it.hasNext() )
+        {
+            Connection conn = (Connection)it.next();
+            conn.close();
+        }
+        conns.clear();
+    }
+
+    /**
+     * Get connections  using getConnection() and make sure
+     * they're unique
+     */
+    private void assertTenConnectionsUnique() throws Exception
+    {
+        clearConnections();
+        // Open ten connections rather than just two to
+        // try and catch any odd uniqueness bugs.  Still
+        // no guarantee but is better than just two.
+        int numConnections = 10;
+        for ( int i = 0 ; i < numConnections ; i++ )
+        {
+            Connection conn = openDefaultConnection();
+            assertToString(conn);
+        }
+
+        // Now close the connections
+        clearConnections();
+    }
+}

Property changes on: java\testing\org\apache\derbyTesting\functionTests\tests\jdbcapi\SimpleDataSourceTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

