package org.glassfish.jdbc.devtests.v3.test; import java.io.PrintWriter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import org.glassfish.jdbc.devtests.v3.util.HtmlUtil; import org.glassfish.jdbc.devtests.v3.util.TablesUtil; /** * Devtest to test if application server removes a connection from pool * after using it for "maxconnectionusage" times. * * Assumes that steady-pool-size = 1, max-pool-size = 1, * max-connection-usage-count = 10 attributes are set on the pool. * * @author shalini */ public class MaxConnectionUsageTest implements SimpleTest { Map<String, Boolean> resultsMap = new HashMap<String, Boolean>(); /** * Tests max-connection-usage assuming pool size = 1 and * DataSource is of type : javax.sql.DataSource * @param ds * @param out * @return resultsMap */ public Map<String, Boolean> runTest(DataSource ds, PrintWriter out) { String tableName = "max_connection_usage"; createTables(ds, out, tableName); try { if (maxConnUsageTest1(ds, out)) { resultsMap.put("max-conn-usage-test1", true); }else{ resultsMap.put("max-conn-usage-test1", false); } } catch (Exception e) { resultsMap.put("max-conn-usage-test1", false); } try { if (connectionSharingTest(ds, out, 21112, tableName)) { resultsMap.put("max-conn-usage-connection-sharing-test", true); }else{ resultsMap.put("max-conn-usage-connection-sharing-test", false); } } catch (Exception e) { resultsMap.put("max-conn-usage-connection-sharing-test", false); } TablesUtil.deleteTables(ds, out, tableName); HtmlUtil.printHR(out); return resultsMap; } /** * Assuming pool has only one connection, calling maxConnUsageTest2(...) and * maxConnUsageTest3(...) 5 times each will ensure that "maxconnectionsusage=10" * is met. * Further call to maxConnUsageTest2(...) will return a different connection * * If they are different, connection was dropped and created and test passes. * * @param ds * @param out * @param value * @param tableName * @return boolean status */ private boolean connectionSharingTest(DataSource ds, PrintWriter out, int value, String tableName) { String[] results = new String[10]; out.println("<h4> Max Connection Usage - Connection Sharing Test </h4>"); out.println("<br> Invoking maxConnUsageTest2 and maxConnUsageTest3 methods"); for(int i=0; i<10; i++) { if(i % 2 == 0) { results[i] = maxConnUsageTest2(ds, out, value, tableName); } else { results[i] = maxConnUsageTest3(ds, out, (i/2)+1, value, tableName); } } boolean status = true; String tmpResult1 = results[0]; for(int i =0; i<results.length; i++) { if(!results[i].equalsIgnoreCase(tmpResult1)) { out.println("<br>Result 0 : " + tmpResult1); out.println("<br>Result [" + i + "] : " + results[i]); status = false; break; } } out.println("<br> Further call to maxConnUsageTest2"); String tmpResult2 = maxConnUsageTest2(ds, out, value, tableName); if(!tmpResult2.equalsIgnoreCase(tmpResult1) && status) { status = true; } else { out.println("<br>Marking status as false during verification"); out.println("<br>Value : " + value); out.println("<br>Result 1 : " + tmpResult1); out.println("<br>Result 2 : " + tmpResult2); status = false; } out.println("<br> Test result : " + status); return status; } /** * Creates table needed for the Max Connection Usage devtest. * * @param ds * @param out * @param tableName */ private void createTables(DataSource ds, PrintWriter out, String tableName) { Connection con = null; Statement stmt = null; try { con = ds.getConnection(); stmt = con.createStatement(); String query = "create table " + tableName + "(id " + "integer not null, value char(16))"; stmt.executeUpdate(query); } catch (Exception e) { HtmlUtil.printException(e, out); } finally { try { if (stmt != null) { stmt.close(); } } catch (Exception e) { HtmlUtil.printException(e, out); } try { if (con != null) { con.close(); } } catch (Exception e) { HtmlUtil.printException(e, out); } } } /** * Tests if the first and last physical connections are different. * Assuming maxconnectionusage property is 10 and connectionSharing ON, the * physical connections con-1 and con-11 must be different. * @param ds * @param out * @return boolean result */ private boolean maxConnUsageTest1(DataSource ds, PrintWriter out) { Connection firstConnection = null; Connection lastConnection = null; boolean result = false; com.sun.appserv.jdbc.DataSource ds1 = (com.sun.appserv.jdbc.DataSource) ds; out.println("<h4> Max Connection Usage - Test1 </h4>"); out.println("<br> Getting connections and physical connections..."); for(int i=0; i<11; i++) { Connection con = null; try { con = ds1.getConnection(); //Getting physical connection if(i==0) { firstConnection = ds1.getConnection(con); } else if(i==10) { lastConnection = ds1.getConnection(con); //Necessary for last connection to make subsequent tests pass ds1.markConnectionAsBad(con); } result = (firstConnection != lastConnection); } catch (Exception ex) { HtmlUtil.printException(ex, out); result = false; } finally { if(con != null) { try { con.close(); } catch (Exception ex) { HtmlUtil.printException(ex, out); } } } } out.println("<br> Test result : " + result); return result; } /** * Returns physical connection's ID after inserting entries into a table * @param ds * @param out * @param value * @param tableName * @return physicalConnectionString */ private String maxConnUsageTest2(DataSource ds, PrintWriter out, int value, String tableName) { Connection physicalConnection = null; Connection conn = null; String physicalConnectionString = null; com.sun.appserv.jdbc.DataSource ds1 = (com.sun.appserv.jdbc.DataSource) ds; Statement stmt = null; try { conn = ds1.getConnection(); stmt = conn.createStatement(); stmt.executeUpdate("insert into " + tableName + " values (" + value + ",'" + value + "')"); physicalConnection = ds1.getConnection(conn); physicalConnectionString = physicalConnection.toString(); } catch (Exception ex) { physicalConnection = null; return null; } finally { try { if (stmt != null) { stmt.close(); } } catch (Exception e) { HtmlUtil.printException(e, out); } try { if(conn != null) { conn.close(); } } catch(Exception ex) { HtmlUtil.printException(ex, out); } } return physicalConnectionString; } /** * Returns the physical connection's ID after testing if the entries inserted * using maxConnUsageTest2(....) method are persisted. * @param ds * @param out * @param count * @param value * @param tableName * @return physicalConnectionString */ private String maxConnUsageTest3(DataSource ds, PrintWriter out, int count, int value, String tableName) { Connection physicalConnection = null; Connection conn = null; com.sun.appserv.jdbc.DataSource ds1 = (com.sun.appserv.jdbc.DataSource) ds; Statement stmt = null; ResultSet rs = null; try { conn = ds1.getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery("select count(*) as COUNT from " + tableName + " where id=" + value); while(rs.next()) { int resultCount = rs.getInt("COUNT"); if(count == resultCount) { physicalConnection = ds1.getConnection(conn); } else { out.println("Expected count [" + count + "] does not match [" + resultCount + "]"); break; } } } catch (Exception ex) { physicalConnection = null; return null; } finally { try { if(rs != null) { rs.close(); } } catch(Exception ex) { HtmlUtil.printException(ex, out); } try { if(stmt != null) { stmt.close(); } } catch (Exception ex) { HtmlUtil.printException(ex, out); } try { if(conn != null) { conn.close(); } } catch(Exception ex) { HtmlUtil.printException(ex, out); } } return physicalConnection.toString(); } }