/* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. The MySQL Connector/J is licensed under the terms of the GPLv2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors. There are special exceptions to the terms and conditions of the GPLv2 as it is applied to this software, see the FOSS License Exception <http://www.mysql.com/about/legal/licensing/foss-exception.html>. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package testsuite.regression.jdbc4; import java.io.ObjectInputStream.GetField; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLNonTransientException; import java.sql.SQLTransientException; import java.sql.Statement; import java.util.Properties; import java.util.concurrent.Callable; import com.mysql.jdbc.Messages; import com.mysql.jdbc.MysqlErrorNumbers; import com.mysql.jdbc.SQLError; import com.mysql.jdbc.Util; import javax.sql.PooledConnection; import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; import com.mysql.jdbc.jdbc2.optional.JDBC4MysqlPooledConnection; import com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection; import com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection; import testsuite.BaseTestCase; import testsuite.regression.ConnectionRegressionTest.Bug72712StatementInterceptor; import testsuite.regression.ConnectionRegressionTest.Bug75168LoadBalanceExceptionChecker; public class ConnectionRegressionTest extends BaseTestCase { /** * Creates a new ConnectionRegressionTest. * * @param name * the name of the test */ public ConnectionRegressionTest(String name) { super(name); } /** * Runs all test cases in this test suite * * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(ConnectionRegressionTest.class); } /** * Tests fix for Bug#75168 - loadBalanceExceptionChecker interface cannot work using JDBC4/JDK7 * * Bug observed only with JDBC4 classes. This test is duplicated in testsuite.regression.ConnectionRegressionTest#testBug75168(). * The two nested static classes, Bug75168LoadBalanceExceptionChecker and Bug75168StatementInterceptor are shared between the two tests. * * @throws Exception */ public void testBug75168() throws Exception { final Properties props = new Properties(); props.setProperty("loadBalanceExceptionChecker", Bug75168LoadBalanceExceptionChecker.class.getName()); props.setProperty("statementInterceptors", testsuite.regression.ConnectionRegressionTest.Bug75168StatementInterceptor.class.getName()); Connection connTest = getLoadBalancedConnection(2, null, props); // get a load balancing connection with two default servers for (int i = 0; i < 3; i++) { Statement stmtTest = null; try { stmtTest = connTest.createStatement(); stmtTest.execute("SELECT * FROM nonexistent_table"); fail("'Table doesn't exist' exception was expected."); } catch (SQLException e) { assertTrue("'Table doesn't exist' exception was expected.", e.getMessage().endsWith("nonexistent_table' doesn't exist")); } finally { if (stmtTest != null) { stmtTest.close(); } } } connTest.close(); boolean stop = false; do { connTest = getLoadBalancedConnection(2, null, props); // get a load balancing connection with two default servers for (int i = 0; i < 3; i++) { PreparedStatement pstmtTest = null; try { pstmtTest = connTest.prepareStatement("SELECT * FROM nonexistent_table"); pstmtTest.execute(); fail("'Table doesn't exist' exception was expected."); } catch (SQLException e) { assertTrue("'Table doesn't exist' exception was expected.", e.getMessage().endsWith("nonexistent_table' doesn't exist")); } finally { if (pstmtTest != null) { pstmtTest.close(); } } } connTest.close(); // do it again with server prepared statements props.setProperty("useServerPrepStmts", "true"); } while (stop = !stop); } /** * Tests fix for BUG#20685022 - SSL CONNECTION TO MYSQL 5.7.6 COMMUNITY SERVER FAILS * * This test is duplicated in testuite.regression.ConnectionRegressionTest.testBug20685022(). * * @throws Exception * if the test fails. */ public void testBug20685022() throws Exception { if (!isCommunityEdition()) { return; } final Properties props = new Properties(); /* * case 1: non verifying server certificate */ props.clear(); props.setProperty("useSSL", "true"); props.setProperty("requireSSL", "true"); props.setProperty("verifyServerCertificate", "false"); getConnectionWithProps(props); /* * case 2: verifying server certificate using key store provided by connection properties */ props.clear(); props.setProperty("useSSL", "true"); props.setProperty("requireSSL", "true"); props.setProperty("verifyServerCertificate", "true"); props.setProperty("trustCertificateKeyStoreUrl", "file:src/testsuite/ssl-test-certs/ca-truststore"); props.setProperty("trustCertificateKeyStoreType", "JKS"); props.setProperty("trustCertificateKeyStorePassword", "password"); getConnectionWithProps(props); /* * case 3: verifying server certificate using key store provided by system properties */ props.clear(); props.setProperty("useSSL", "true"); props.setProperty("requireSSL", "true"); props.setProperty("verifyServerCertificate", "true"); String trustStorePath = "src/testsuite/ssl-test-certs/ca-truststore"; System.setProperty("javax.net.ssl.keyStore", trustStorePath); System.setProperty("javax.net.ssl.keyStorePassword", "password"); System.setProperty("javax.net.ssl.trustStore", trustStorePath); System.setProperty("javax.net.ssl.trustStorePassword", "password"); getConnectionWithProps(props); } /** * Tests fix for BUG#62452 - NPE thrown in JDBC4MySQLPooledException when statement is closed. * * @throws Exception */ public void testBug62452() throws Exception { PooledConnection con = null; MysqlConnectionPoolDataSource pds = new MysqlConnectionPoolDataSource(); pds.setUrl(dbUrl); con = pds.getPooledConnection(); assertTrue(con instanceof JDBC4MysqlPooledConnection); testBug62452WithConnection(con); MysqlXADataSource xads = new MysqlXADataSource(); xads.setUrl(dbUrl); xads.setPinGlobalTxToPhysicalConnection(false); con = xads.getXAConnection(); assertTrue(con instanceof JDBC4MysqlXAConnection); testBug62452WithConnection(con); xads.setPinGlobalTxToPhysicalConnection(true); con = xads.getXAConnection(); assertTrue(con instanceof JDBC4SuspendableXAConnection); testBug62452WithConnection(con); } private void testBug62452WithConnection(PooledConnection con) throws Exception { this.pstmt = con.getConnection().prepareStatement("SELECT 1"); this.rs = this.pstmt.executeQuery(); con.close(); // If PooledConnection is already closed by some reason a NullPointerException was thrown on the next line // because the closed connection has nulled out the list that it synchronises on when the closed event is fired. this.pstmt.close(); } /** * Tests fix for Bug#16634180 - LOCK WAIT TIMEOUT EXCEEDED CAUSES SQLEXCEPTION, SHOULD CAUSE SQLTRANSIENTEXCEPTION * * @throws Exception * if the test fails. */ public void testBug16634180() throws Exception { createTable("testBug16634180", "(pk integer primary key, val integer)", "InnoDB"); this.stmt.executeUpdate("insert into testBug16634180 values(0,0)"); Connection c1 = null; Connection c2 = null; try { c1 = getConnectionWithProps(new Properties()); c1.setAutoCommit(false); Statement s1 = c1.createStatement(); s1.executeUpdate("update testBug16634180 set val=val+1 where pk=0"); c2 = getConnectionWithProps(new Properties()); c2.setAutoCommit(false); Statement s2 = c2.createStatement(); try { s2.executeUpdate("update testBug16634180 set val=val+1 where pk=0"); fail("ER_LOCK_WAIT_TIMEOUT should be thrown."); } catch (SQLTransientException ex) { assertEquals(MysqlErrorNumbers.ER_LOCK_WAIT_TIMEOUT, ex.getErrorCode()); assertEquals(SQLError.SQL_STATE_ROLLBACK_SERIALIZATION_FAILURE, ex.getSQLState()); assertEquals("Lock wait timeout exceeded; try restarting transaction", ex.getMessage()); } } finally { if (c1 != null) { c1.close(); } if (c2 != null) { c2.close(); } } } /** * Tests fix for Bug#56122 - JDBC4 functionality failure when using replication connections. */ public void testBug56122() throws Exception { for (final Connection testConn : new Connection[] { this.conn, getFailoverConnection(), getLoadBalancedConnection(), getMasterSlaveReplicationConnection() }) { testConn.createClob(); testConn.createBlob(); testConn.createNClob(); testConn.createSQLXML(); testConn.isValid(12345); testConn.setClientInfo(new Properties()); testConn.setClientInfo("NAME", "VALUE"); testConn.getClientInfo(); testConn.getClientInfo("CLIENT"); assertThrows(SQLFeatureNotSupportedException.class, new Callable<Void>() { public Void call() throws Exception { testConn.createArrayOf("A_TYPE", null); return null; } }); assertThrows(SQLFeatureNotSupportedException.class, new Callable<Void>() { public Void call() throws Exception { testConn.createStruct("A_TYPE", null); return null; } }); } } }