~ubuntu-branches/ubuntu/trusty/mysql-connector-java/trusty

« back to all changes in this revision

Viewing changes to src/testsuite/regression/ConnectionRegressionTest.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Miguel Landaeta
  • Date: 2013-07-02 17:07:51 UTC
  • mfrom: (1.1.8) (3.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20130702170751-f4rszjabxg0391fr
Tags: 5.1.25-1
* New upstream release
* Refreshed the patches
* Added a patch to build with one JDK and removed the build
  dependency on java-gcj-compat-dev
* Updated Standards-Version to 3.9.4 (no changes)
* Use canonical URLs for the Vcs-* fields
* debian/rules: Improved the clean target to allow rebuilds
* Updated the watch file
* Renamed debian/README.Debian-source to README.source

[ Miguel Landaeta ] 
* Fix FTBFS with OpenJDK 7 (Closes: #706668)
* Remove Michael Koch from Uploaders list.
  Thanks for your work on this package. (Closes: #654122).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
  Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 
2
  Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3
3
 
4
4
  The MySQL Connector/J is licensed under the terms of the GPLv2
5
5
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
22
22
 */
23
23
package testsuite.regression;
24
24
 
 
25
import java.io.BufferedOutputStream;
25
26
import java.io.ByteArrayOutputStream;
 
27
import java.io.File;
 
28
import java.io.FileOutputStream;
26
29
import java.io.IOException;
27
30
import java.io.PrintStream;
28
31
import java.lang.reflect.InvocationTargetException;
29
32
import java.lang.reflect.Method;
 
33
import java.lang.reflect.Proxy;
30
34
import java.net.Socket;
31
35
import java.net.SocketException;
32
36
import java.sql.Connection;
36
40
import java.sql.ResultSet;
37
41
import java.sql.SQLException;
38
42
import java.sql.Statement;
 
43
import java.util.Date;
39
44
import java.util.Enumeration;
40
45
import java.util.HashMap;
41
46
import java.util.HashSet;
42
 
import java.util.Iterator;
43
47
import java.util.LinkedList;
44
48
import java.util.List;
45
49
import java.util.Locale;
46
50
import java.util.Map;
47
51
import java.util.Properties;
48
52
import java.util.Set;
49
 
import java.util.StringTokenizer;
 
53
import java.util.concurrent.Executor;
 
54
import java.util.concurrent.Executors;
 
55
import java.util.concurrent.ScheduledExecutorService;
 
56
import java.util.concurrent.ScheduledFuture;
 
57
import java.util.concurrent.TimeUnit;
50
58
import java.util.regex.Matcher;
51
59
import java.util.regex.Pattern;
52
60
 
57
65
import testsuite.BaseTestCase;
58
66
import testsuite.UnreliableSocketFactory;
59
67
 
 
68
import com.mysql.jdbc.AuthenticationPlugin;
 
69
import com.mysql.jdbc.Buffer;
 
70
import com.mysql.jdbc.CharsetMapping;
60
71
import com.mysql.jdbc.ConnectionImpl;
61
72
import com.mysql.jdbc.Driver;
62
73
import com.mysql.jdbc.LoadBalancingConnectionProxy;
63
74
import com.mysql.jdbc.Messages;
64
75
import com.mysql.jdbc.MySQLConnection;
65
76
import com.mysql.jdbc.MysqlDataTruncation;
 
77
import com.mysql.jdbc.MysqlErrorNumbers;
66
78
import com.mysql.jdbc.NonRegisteringDriver;
67
79
import com.mysql.jdbc.RandomBalanceStrategy;
68
80
import com.mysql.jdbc.ReplicationConnection;
69
81
import com.mysql.jdbc.SQLError;
70
82
import com.mysql.jdbc.StandardSocketFactory;
 
83
import com.mysql.jdbc.StringUtils;
 
84
import com.mysql.jdbc.TimeUtil;
 
85
import com.mysql.jdbc.exceptions.MySQLNonTransientException;
 
86
import com.mysql.jdbc.exceptions.MySQLSyntaxErrorException;
71
87
import com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker;
72
88
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
73
89
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
237
253
         */
238
254
        public void testCollation41() throws Exception {
239
255
                if (versionMeetsMinimum(4, 1) && isAdminConnectionConfigured()) {
240
 
                        Map charsetsAndCollations = getCharacterSetsAndCollations();
 
256
                        Map<String, String> charsetsAndCollations = getCharacterSetsAndCollations();
241
257
                        charsetsAndCollations.remove("latin7"); // Maps to multiple Java
242
258
                        // charsets
243
259
                        charsetsAndCollations.remove("ucs2"); // can't be used as a
244
260
                        // connection charset
245
261
 
246
 
                        Iterator charsets = charsetsAndCollations.keySet().iterator();
247
 
 
248
 
                        while (charsets.hasNext()) {
 
262
                        for (String charsetName : charsetsAndCollations.keySet()) {
249
263
                                Connection charsetConn = null;
250
264
                                Statement charsetStmt = null;
251
265
 
252
266
                                try {
253
 
                                        String charsetName = charsets.next().toString();
254
 
                                        String collationName = charsetsAndCollations.get(
255
 
                                                        charsetName).toString();
 
267
                                        //String collationName = charsetsAndCollations.get(charsetName);
 
268
                                        
256
269
                                        Properties props = new Properties();
257
270
                                        props.put("characterEncoding", charsetName);
258
271
 
373
386
                assertTrue(reconnectableConn.isReadOnly() == isReadOnly);
374
387
        }
375
388
 
376
 
        private Map getCharacterSetsAndCollations() throws Exception {
377
 
                Map charsetsToLoad = new HashMap();
 
389
        private Map<String, String> getCharacterSetsAndCollations() throws Exception {
 
390
                Map<String, String> charsetsToLoad = new HashMap<String, String>();
378
391
 
379
392
                try {
380
393
                        this.rs = this.stmt.executeQuery("SHOW character set");
544
557
 
545
558
                                Connection failoverConn = DriverManager.getConnection(
546
559
                                                newUrlToTestFailover.toString(), autoReconnectProps);
547
 
                                Statement failoverStmt = portNumConn.createStatement();
 
560
                                Statement failoverStmt = failoverConn.createStatement();
548
561
                                this.rs = failoverStmt.executeQuery("SELECT connection_id()");
549
562
                                this.rs.next();
550
563
 
583
596
                props.setProperty("autoReconnect", "true");
584
597
                props.setProperty("socketFactory", "testsuite.UnreliableSocketFactory");
585
598
 
586
 
                Properties urlProps = new NonRegisteringDriver().parseURL(this.dbUrl,
 
599
                Properties urlProps = new NonRegisteringDriver().parseURL(dbUrl,
587
600
                                null);
588
601
 
589
602
                String host = urlProps.getProperty(Driver.HOST_PROPERTY_KEY);
1399
1412
                                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1400
1413
                                System.setErr(new PrintStream(bOut));
1401
1414
 
1402
 
                                HashMap methodsToSkipMap = new HashMap();
 
1415
                                HashMap<String, String> methodsToSkipMap = new HashMap<String, String>();
1403
1416
 
1404
1417
                                // Needs an actual URL
1405
1418
                                methodsToSkipMap.put("getURL", null);
1417
1430
 
1418
1431
                                                if (methodName.startsWith("get")
1419
1432
                                                                && !methodsToSkipMap.containsKey(methodName)) {
1420
 
                                                        Class[] parameterTypes = getMethods[i]
 
1433
                                                        Class<?>[] parameterTypes = getMethods[i]
1421
1434
                                                                        .getParameterTypes();
1422
1435
 
1423
1436
                                                        if (parameterTypes.length == 1
1805
1818
         * @throws Exception
1806
1819
         */
1807
1820
        public void testBug23626() throws Exception {
1808
 
                Class clazz = this.conn.getClass();
 
1821
                Class<?> clazz = this.conn.getClass();
1809
1822
 
1810
1823
                DriverPropertyInfo[] dpi = new NonRegisteringDriver().getPropertyInfo(
1811
1824
                                dbUrl, null);
1812
1825
                StringBuffer missingSettersBuf = new StringBuffer();
1813
1826
                StringBuffer missingGettersBuf = new StringBuffer();
1814
1827
 
1815
 
                Class[][] argTypes = { new Class[] { String.class },
 
1828
                Class<?>[][] argTypes = { new Class[] { String.class },
1816
1829
                                new Class[] { Integer.TYPE }, new Class[] { Long.TYPE },
1817
1830
                                new Class[] { Boolean.TYPE } };
1818
1831
 
1911
1924
        }
1912
1925
 
1913
1926
        /**
 
1927
         * Tests fix for BUG#36948 - Trying to use trustCertificateKeyStoreUrl
 
1928
         * causes an IllegalStateException.
 
1929
         * 
 
1930
         * Requires test certificates from testsuite/ssl-test-certs to be installed
 
1931
         * on the server being tested.
 
1932
         * 
 
1933
         * @throws Exception
 
1934
         *             if the test fails.
 
1935
         */
 
1936
        public void testBug36948() throws Exception {
 
1937
 
 
1938
                Connection _conn = null;
 
1939
 
 
1940
                try {
 
1941
                        
 
1942
                        Properties props = new NonRegisteringDriver().parseURL(dbUrl, null);
 
1943
                        String host = props.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, "localhost");
 
1944
                        String port = props.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306");
 
1945
                        String db = props.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY, "test");
 
1946
 
 
1947
                        String hostSpec = host;
 
1948
 
 
1949
                        if (!NonRegisteringDriver.isHostPropertiesList(host)) {
 
1950
                                hostSpec = host + ":" + port;
 
1951
                        }
 
1952
                        
 
1953
                        final String url = "jdbc:mysql://"+hostSpec+"/"+db+"?"
 
1954
                    + "useSSL=true"
 
1955
                    + "&requireSSL=true"
 
1956
                    + "&verifyServerCertificate=true"
 
1957
                    + "&trustCertificateKeyStoreUrl=file:src/testsuite/ssl-test-certs/test-cert-store"
 
1958
                    + "&trustCertificateKeyStoreType=JKS"
 
1959
                    + "&trustCertificateKeyStorePassword=password";
 
1960
                        
 
1961
            _conn = DriverManager.getConnection(url,
 
1962
                        (String) this.getPropertiesFromTestsuiteUrl().get("user"),
 
1963
                        (String) this.getPropertiesFromTestsuiteUrl().get("password"));
 
1964
            
 
1965
            assertTrue(true);
 
1966
                } finally {
 
1967
                        if (_conn != null) {
 
1968
                                _conn.close();
 
1969
                        }
 
1970
                }
 
1971
 
 
1972
        }
 
1973
 
 
1974
        /**
1914
1975
         * Tests fix for BUG#27655 - getTransactionIsolation() uses
1915
1976
         * "SHOW VARIABLES LIKE" which is very inefficient on MySQL-5.0+
1916
1977
         * 
2049
2110
 
2050
2111
        public void testBug29106() throws Exception {
2051
2112
                ClassLoader cl = Thread.currentThread().getContextClassLoader();
2052
 
                Class checkerClass = cl
 
2113
                Class<?> checkerClass = cl
2053
2114
                                .loadClass("com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker");
2054
2115
                ((MysqlValidConnectionChecker) checkerClass.newInstance())
2055
2116
                                .isValidConnection(this.conn);
2197
2258
                Properties props = getMasterSlaveProps();
2198
2259
                String key = null;
2199
2260
 
2200
 
                Enumeration keyEnum = props.keys();
 
2261
                Enumeration<Object> keyEnum = props.keys();
2201
2262
 
2202
2263
                while (keyEnum.hasMoreElements()) {
2203
2264
                        key = (String) keyEnum.nextElement();
2361
2422
        }
2362
2423
 
2363
2424
        public void testBug45171() throws Exception {
2364
 
                List statementsToTest = new LinkedList();
 
2425
                List<Statement> statementsToTest = new LinkedList<Statement>();
2365
2426
                statementsToTest.add(this.conn.createStatement());
2366
2427
                statementsToTest.add(((com.mysql.jdbc.Connection) this.conn)
2367
2428
                                .clientPrepareStatement("SELECT 1"));
2382
2443
                statementsToTest.add(((com.mysql.jdbc.Connection) this.conn)
2383
2444
                                .serverPrepareStatement("SELECT 1", new String[0]));
2384
2445
 
2385
 
                Iterator iter = statementsToTest.iterator();
2386
 
 
2387
 
                while (iter.hasNext()) {
2388
 
                        Statement toTest = (Statement) iter.next();
 
2446
                for (Statement toTest : statementsToTest) {
2389
2447
                        assertEquals(toTest.getResultSetType(), ResultSet.TYPE_FORWARD_ONLY);
2390
2448
                        assertEquals(toTest.getResultSetConcurrency(),
2391
2449
                                        ResultSet.CONCUR_READ_ONLY);
2442
2500
 
2443
2501
                try {
2444
2502
                        Connection noConn = getConnectionWithProps("socketFactory=testsuite.UnreliableSocketFactory");
 
2503
                        noConn.close();
2445
2504
                } catch (SQLException sqlEx) {
2446
2505
                        assertTrue(sqlEx.getMessage().indexOf("has not received") != -1);
2447
2506
                } finally {
2650
2709
                                                                                                                        // in reported bug,
2651
2710
                                                                                                                        // it's removed by
2652
2711
                                                                                                                        // the driver
2653
 
                Set downedHosts = new HashSet();
 
2712
                Set<String> downedHosts = new HashSet<String>();
2654
2713
                downedHosts.add("first");
2655
2714
 
2656
2715
                // this loop will hang on the first unreliable host if the bug isn't
2778
2837
                }
2779
2838
 
2780
2839
                public com.mysql.jdbc.ConnectionImpl pickConnection(
2781
 
                                LoadBalancingConnectionProxy proxy, List configuredHosts,
2782
 
                                Map liveConnections, long[] responseTimes, int numRetries)
 
2840
                                LoadBalancingConnectionProxy proxy, List<String> configuredHosts,
 
2841
                                Map<String, ConnectionImpl> liveConnections, long[] responseTimes, int numRetries)
2783
2842
                                throws SQLException {
2784
2843
                        if (forcedFutureServer == null || forceFutureServerTimes == 0) {
2785
2844
                                return super.pickConnection(proxy, configuredHosts,
2788
2847
                        if (forceFutureServerTimes > 0) {
2789
2848
                                forceFutureServerTimes--;
2790
2849
                        }
2791
 
                        ConnectionImpl conn = (ConnectionImpl) liveConnections
 
2850
                        ConnectionImpl conn = liveConnections
2792
2851
                                        .get(forcedFutureServer);
2793
2852
 
2794
2853
                        if (conn == null) {
2890
2949
                }
2891
2950
 
2892
2951
                public com.mysql.jdbc.ConnectionImpl pickConnection(
2893
 
                                LoadBalancingConnectionProxy proxy, List configuredHosts,
2894
 
                                Map liveConnections, long[] responseTimes, int numRetries)
 
2952
                                LoadBalancingConnectionProxy proxy, List<String> configuredHosts,
 
2953
                                Map<String, ConnectionImpl> liveConnections, long[] responseTimes, int numRetries)
2895
2954
                                throws SQLException {
2896
2955
                        rebalancedTimes++;
2897
2956
                        return super.pickConnection(proxy, configuredHosts,
3009
3068
                props.setProperty("useOldUTF8Behavior", "true");
3010
3069
 
3011
3070
                Connection c = getConnectionWithProps(props);
3012
 
                ResultSet rs = c.createStatement().executeQuery(
 
3071
                ResultSet r = c.createStatement().executeQuery(
3013
3072
                                "SHOW SESSION VARIABLES LIKE 'character_set_connection'");
3014
 
                rs.next();
3015
 
                assertEquals("latin1", rs.getString(2));
 
3073
                r.next();
 
3074
                assertEquals("latin1", r.getString(2));
3016
3075
        }
3017
3076
        
3018
3077
        public void testBug58706() throws Exception {
3020
3079
                props.setProperty("autoReconnect", "true");
3021
3080
                props.setProperty("socketFactory", "testsuite.UnreliableSocketFactory");
3022
3081
 
3023
 
                Properties urlProps = new NonRegisteringDriver().parseURL(this.dbUrl,
 
3082
                Properties urlProps = new NonRegisteringDriver().parseURL(dbUrl,
3024
3083
                                null);
3025
3084
 
3026
3085
                String host = urlProps.getProperty(Driver.HOST_PROPERTY_KEY);
3131
3190
                rConn2.prepareStatement("SELECT 1").executeQuery();
3132
3191
                
3133
3192
        }
 
3193
        
 
3194
        public void testBug61201() throws Exception {
 
3195
                Properties props = new Properties();
 
3196
                props.setProperty("sessionVariables", "FOREIGN_KEY_CHECKS=0");
 
3197
                props.setProperty("characterEncoding", "latin1");
 
3198
                props.setProperty("profileSQL", "true");
 
3199
 
 
3200
                Connection varConn = getConnectionWithProps(props);
 
3201
                varConn.close();
 
3202
        }
 
3203
        
 
3204
        public void testChangeUser() throws Exception {
 
3205
                Properties props = getPropertiesFromTestsuiteUrl();
 
3206
                
 
3207
                for (int i = 0; i < 500; i++) {
 
3208
                        ((com.mysql.jdbc.Connection) this.conn).changeUser(props.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY), props.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY));
 
3209
                        
 
3210
                        if (i % 10 == 0) {
 
3211
                                try {
 
3212
                                        ((com.mysql.jdbc.Connection) this.conn).changeUser("bubba", props.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY));
 
3213
                                } catch (SQLException sqlEx) {
 
3214
                                        // expect
 
3215
                                }
 
3216
                        }
 
3217
                        
 
3218
                        this.stmt.executeQuery("SELECT 1");
 
3219
                }
 
3220
        }
 
3221
        
 
3222
        public void testChangeUserClosedConn() throws Exception {
 
3223
                Properties props = getPropertiesFromTestsuiteUrl();
 
3224
                Connection newConn = getConnectionWithProps((Properties)null);
 
3225
                
 
3226
                try {
 
3227
                        newConn.close();
 
3228
                        ((com.mysql.jdbc.Connection) newConn).changeUser(props.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY), props.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY));
 
3229
                        fail("Expected SQL Exception");
 
3230
                } catch (MySQLNonTransientException ex) {
 
3231
                        // expected
 
3232
                } finally {
 
3233
                        newConn.close();
 
3234
                }
 
3235
        }
 
3236
 
 
3237
        public void testBug63284() throws Exception {
 
3238
                Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
 
3239
                props.setProperty("autoReconnect", "true");
 
3240
                props.setProperty("socketFactory", "testsuite.UnreliableSocketFactory");
 
3241
 
 
3242
                Properties urlProps = new NonRegisteringDriver().parseURL(
 
3243
            BaseTestCase.dbUrl, null);
 
3244
 
 
3245
                String host = urlProps.getProperty(Driver.HOST_PROPERTY_KEY);
 
3246
                String port = urlProps.getProperty(Driver.PORT_PROPERTY_KEY);
 
3247
 
 
3248
                props.remove(Driver.HOST_PROPERTY_KEY);
 
3249
                props.remove(Driver.NUM_HOSTS_PROPERTY_KEY);
 
3250
                props.remove(Driver.HOST_PROPERTY_KEY + ".1");
 
3251
                props.remove(Driver.PORT_PROPERTY_KEY + ".1");
 
3252
 
 
3253
                props.setProperty("queriesBeforeRetryMaster", "50");
 
3254
                props.setProperty("maxReconnects", "1");
 
3255
 
 
3256
                UnreliableSocketFactory.mapHost("master", host);
 
3257
                UnreliableSocketFactory.mapHost("slave", host);
 
3258
 
 
3259
                Connection failoverConnection1 = null;
 
3260
                Connection failoverConnection2 = null;
 
3261
        
 
3262
                try{
 
3263
                        failoverConnection1 = getConnectionWithProps("jdbc:mysql://master:"
 
3264
                + port + ",slave:" + port + "/", props);
 
3265
 
 
3266
                        failoverConnection2 = getConnectionWithProps("jdbc:mysql://master:"
 
3267
                + port + ",slave:" + port + "/", props);
 
3268
       
 
3269
                        assert(((com.mysql.jdbc.Connection)failoverConnection1).isMasterConnection());
 
3270
 
 
3271
                        // Two different Connection objects should not equal each other:
 
3272
                        assert(!failoverConnection1.equals(failoverConnection2));
 
3273
 
 
3274
                        int hc = failoverConnection1.hashCode();
 
3275
       
 
3276
                        UnreliableSocketFactory.downHost("master");
 
3277
       
 
3278
                        for(int i = 0; i < 3; i++ ){
 
3279
                                try{
 
3280
                                        failoverConnection1.createStatement().execute("SELECT 1");
 
3281
                                } catch (SQLException e){
 
3282
                // do nothing, expect SQLException when failing over initially
 
3283
                // goal here is to ensure valid connection against a slave
 
3284
                                }
 
3285
                        }
 
3286
                        // ensure we're now connected to the slave
 
3287
                        assert(!((com.mysql.jdbc.Connection)failoverConnection1).isMasterConnection());
 
3288
       
 
3289
                        // ensure that hashCode() result is persistent across failover events when proxy state changes
 
3290
                        assert(failoverConnection1.hashCode() == hc);
 
3291
                } finally {
 
3292
                        if (failoverConnection1 != null) {
 
3293
                                failoverConnection1.close();
 
3294
                        }
 
3295
                        if (failoverConnection2 != null) {
 
3296
                                failoverConnection2.close();
 
3297
                        }
 
3298
                }
 
3299
        }
 
3300
        
 
3301
        public void testDefaultPlugin() throws Exception {
 
3302
                if (versionMeetsMinimum(5, 5, 7)) {
 
3303
 
 
3304
                        Connection testConn = null;
 
3305
                        Properties props = new Properties();
 
3306
 
 
3307
                        props.setProperty("defaultAuthenticationPlugin", "");
 
3308
                        try {
 
3309
                                testConn = getConnectionWithProps(props);
 
3310
                                assertTrue("Exception is expected due to incorrect defaultAuthenticationPlugin value", false);
 
3311
                        } catch (SQLException sqlEx) {
 
3312
                                assertTrue(true);
 
3313
                        } finally {
 
3314
                                if (testConn != null) testConn.close();
 
3315
                        }
 
3316
 
 
3317
                        props.setProperty("defaultAuthenticationPlugin", "mysql_native_password");
 
3318
                        try {
 
3319
                                testConn = getConnectionWithProps(props);
 
3320
                                assertTrue("Exception is expected due to incorrect defaultAuthenticationPlugin value (mechanism name instead of class name)", false);
 
3321
                        } catch (SQLException sqlEx) {
 
3322
                                assertTrue(true);
 
3323
                        } finally {
 
3324
                                if (testConn != null) testConn.close();
 
3325
                        }
 
3326
 
 
3327
                        props.setProperty("defaultAuthenticationPlugin", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3328
                        try {
 
3329
                                testConn = getConnectionWithProps(props);
 
3330
                                assertTrue("Exception is expected due to defaultAuthenticationPlugin value is not listed", false);
 
3331
                        } catch (SQLException sqlEx) {
 
3332
                                assertTrue(true);
 
3333
                        } finally {
 
3334
                                if (testConn != null) testConn.close();
 
3335
                        }
 
3336
 
 
3337
                        props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3338
                        props.setProperty("defaultAuthenticationPlugin", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3339
                        try {
 
3340
                                testConn = getConnectionWithProps(props);
 
3341
                                assertTrue(true);
 
3342
                        } catch (SQLException sqlEx) {
 
3343
                                assertTrue("Exception is not expected due to defaultAuthenticationPlugin value is correctly listed", false);
 
3344
                        } finally {
 
3345
                                if (testConn != null) testConn.close();
 
3346
                        }
 
3347
                }
 
3348
        }
 
3349
 
 
3350
        public void testDisabledPlugins() throws Exception {
 
3351
                if (versionMeetsMinimum(5, 5, 7)) {
 
3352
 
 
3353
                        Connection testConn = null;
 
3354
                        Properties props = new Properties();
 
3355
 
 
3356
                        props.setProperty("disabledAuthenticationPlugins", "mysql_native_password");
 
3357
                        try {
 
3358
                                testConn = getConnectionWithProps(props);
 
3359
                                assertTrue("Exception is expected due to disabled defaultAuthenticationPlugin", false);
 
3360
                        } catch (SQLException sqlEx) {
 
3361
                                assertTrue(true);
 
3362
                        } finally {
 
3363
                                if (testConn != null) testConn.close();
 
3364
                        }
 
3365
 
 
3366
                        props.setProperty("disabledAuthenticationPlugins", "com.mysql.jdbc.authentication.MysqlNativePasswordPlugin");
 
3367
                        try {
 
3368
                                testConn = getConnectionWithProps(props);
 
3369
                                assertTrue("Exception is expected due to disabled defaultAuthenticationPlugin", false);
 
3370
                        } catch (SQLException sqlEx) {
 
3371
                                assertTrue(true);
 
3372
                        } finally {
 
3373
                                if (testConn != null) testConn.close();
 
3374
                        }
 
3375
 
 
3376
                        props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3377
                        props.setProperty("defaultAuthenticationPlugin", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3378
                        props.setProperty("disabledAuthenticationPlugins", "auth_test_plugin");
 
3379
                        try {
 
3380
                                testConn = getConnectionWithProps(props);
 
3381
                                assertTrue("Exception is expected due to disabled defaultAuthenticationPlugin", false);
 
3382
                        } catch (SQLException sqlEx) {
 
3383
                                assertTrue(true);
 
3384
                        } finally {
 
3385
                                if (testConn != null) testConn.close();
 
3386
                        }
 
3387
 
 
3388
                        props.setProperty("defaultAuthenticationPlugin", "com.mysql.jdbc.authentication.MysqlNativePasswordPlugin");
 
3389
                        props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3390
                        props.setProperty("disabledAuthenticationPlugins", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3391
                        try {
 
3392
                                testConn = getConnectionWithProps(props);
 
3393
                                assertTrue(true);
 
3394
                        } catch (SQLException sqlEx) {
 
3395
                                assertTrue("Exception is not expected due to disabled plugin is not default", false);
 
3396
                        } finally {
 
3397
                                if (testConn != null) testConn.close();
 
3398
                        }
 
3399
                }
 
3400
        }
 
3401
 
 
3402
        public void testAuthTestPlugin() throws Exception {
 
3403
                if (versionMeetsMinimum(5, 5, 7)) {
 
3404
 
 
3405
                        boolean install_plugin_in_runtime = false;
 
3406
                        try {
 
3407
 
 
3408
                                // install plugin if required
 
3409
                                this.rs = this.stmt.executeQuery(
 
3410
                                                "select (PLUGIN_LIBRARY LIKE 'auth_test_plugin%') as `TRUE`" +
 
3411
                                                " FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='test_plugin_server'");
 
3412
                                if (rs.next()) {
 
3413
                                        if (!rs.getBoolean(1)) install_plugin_in_runtime = true;
 
3414
                                } else {
 
3415
                                        install_plugin_in_runtime = true;
 
3416
                                }
 
3417
 
 
3418
                                if (install_plugin_in_runtime) {
 
3419
                                        String ext = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1 ? ".dll" : ".so";
 
3420
                                        this.stmt.executeUpdate("INSTALL PLUGIN test_plugin_server SONAME 'auth_test_plugin"+ext+"'");
 
3421
                                }
 
3422
 
 
3423
                                String dbname = null;
 
3424
                                this.rs = this.stmt.executeQuery("select database() as dbname");
 
3425
                                if(this.rs.first()) {
 
3426
                                        dbname = this.rs.getString("dbname");
 
3427
                                }
 
3428
                                if (dbname == null) assertTrue("No database selected", false);
 
3429
                                
 
3430
                                // create proxy users
 
3431
                                this.stmt.executeUpdate("grant usage on *.* to 'wl5851user'@'%' identified WITH test_plugin_server AS 'plug_dest'");
 
3432
                                this.stmt.executeUpdate("grant usage on *.* to 'plug_dest'@'%' IDENTIFIED BY 'foo'");
 
3433
                                this.stmt.executeUpdate("GRANT PROXY ON 'plug_dest'@'%' TO 'wl5851user'@'%'");
 
3434
                                this.stmt.executeUpdate("delete from mysql.db where user='plug_dest'");
 
3435
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'plug_dest', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3436
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'plug_dest', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3437
                                this.stmt.executeUpdate("flush privileges");
 
3438
                                
 
3439
                                Properties props = new Properties();
 
3440
                                props.setProperty("user", "wl5851user");
 
3441
                                props.setProperty("password", "plug_dest");
 
3442
                                props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$AuthTestPlugin");
 
3443
 
 
3444
                                Connection testConn = null;
 
3445
                                Statement testSt = null;
 
3446
                                ResultSet testRs = null;
 
3447
                                try {
 
3448
                                        testConn = getConnectionWithProps(props);
 
3449
                                        testSt = testConn.createStatement();
 
3450
                                        testRs = testSt.executeQuery("select USER(),CURRENT_USER()");
 
3451
                                        testRs.next();
 
3452
                                        assertEquals("wl5851user", testRs.getString(1).split("@")[0]);
 
3453
                                        assertEquals("plug_dest", testRs.getString(2).split("@")[0]);
 
3454
                                        
 
3455
                                } finally {
 
3456
                                        if (testRs != null) testRs.close();
 
3457
                                        if (testSt != null) testSt.close();
 
3458
                                        if (testConn != null) testConn.close();
 
3459
                                }
 
3460
 
 
3461
                        } finally {
 
3462
                                this.stmt.executeUpdate("drop user 'wl5851user'@'%'");
 
3463
                                this.stmt.executeUpdate("drop user 'plug_dest'@'%'");
 
3464
                                if (install_plugin_in_runtime) {
 
3465
                                        this.stmt.executeUpdate("UNINSTALL PLUGIN test_plugin_server");
 
3466
                                }
 
3467
                        }
 
3468
                }
 
3469
        }
 
3470
 
 
3471
        public void testTwoQuestionsPlugin() throws Exception {
 
3472
                if (versionMeetsMinimum(5, 5, 7)) {
 
3473
 
 
3474
                        boolean install_plugin_in_runtime = false;
 
3475
                        try {
 
3476
 
 
3477
                                // install plugin if required
 
3478
                                this.rs = this.stmt.executeQuery(
 
3479
                                                "select (PLUGIN_LIBRARY LIKE 'two_questions%') as `TRUE`" +
 
3480
                                                " FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='two_questions'");
 
3481
                                if (rs.next()) {
 
3482
                                        if (!rs.getBoolean(1)) install_plugin_in_runtime = true;
 
3483
                                } else {
 
3484
                                        install_plugin_in_runtime = true;
 
3485
                                }
 
3486
 
 
3487
                                if (install_plugin_in_runtime) {
 
3488
                                        String ext = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1 ? ".dll" : ".so";
 
3489
                                        this.stmt.executeUpdate("INSTALL PLUGIN two_questions SONAME 'auth"+ext+"'");
 
3490
                                }
 
3491
 
 
3492
                                String dbname = null;
 
3493
                                this.rs = this.stmt.executeQuery("select database() as dbname");
 
3494
                                if(this.rs.first()) {
 
3495
                                        dbname = this.rs.getString("dbname");
 
3496
                                }
 
3497
                                if (dbname == null) assertTrue("No database selected", false);
 
3498
                                
 
3499
                                this.stmt.executeUpdate("grant usage on *.* to 'wl5851user2'@'%' identified WITH two_questions AS 'two_questions_password'");
 
3500
                                this.stmt.executeUpdate("delete from mysql.db where user='wl5851user2'");
 
3501
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'wl5851user2', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3502
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'wl5851user2', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3503
                                this.stmt.executeUpdate("flush privileges");
 
3504
                                
 
3505
                                Properties props = new Properties();
 
3506
                                props.setProperty("user", "wl5851user2");
 
3507
                                props.setProperty("password", "two_questions_password");
 
3508
                                props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$TwoQuestionsPlugin");
 
3509
 
 
3510
                                Connection testConn = null;
 
3511
                                Statement testSt = null;
 
3512
                                ResultSet testRs = null;
 
3513
                                try {
 
3514
                                        testConn = getConnectionWithProps(props);
 
3515
                                        testSt = testConn.createStatement();
 
3516
                                        testRs = testSt.executeQuery("select USER(),CURRENT_USER()");
 
3517
                                        testRs.next();
 
3518
                                        assertEquals("wl5851user2", testRs.getString(1).split("@")[0]);
 
3519
                                        
 
3520
                                } finally {
 
3521
                                        if (testRs != null) testRs.close();
 
3522
                                        if (testSt != null) testSt.close();
 
3523
                                        if (testConn != null) testConn.close();
 
3524
                                }
 
3525
 
 
3526
                        } finally {
 
3527
                                this.stmt.executeUpdate("drop user 'wl5851user2'@'%'");
 
3528
                                if (install_plugin_in_runtime) {
 
3529
                                        this.stmt.executeUpdate("UNINSTALL PLUGIN two_questions");
 
3530
                                }
 
3531
                        }
 
3532
                }
 
3533
        }
 
3534
 
 
3535
        public void testThreeAttemptsPlugin() throws Exception {
 
3536
                if (versionMeetsMinimum(5, 5, 7)) {
 
3537
 
 
3538
                        boolean install_plugin_in_runtime = false;
 
3539
                        try {
 
3540
 
 
3541
                                // install plugin if required
 
3542
                                this.rs = this.stmt.executeQuery(
 
3543
                                                "select (PLUGIN_LIBRARY LIKE 'three_attempts%') as `TRUE`" +
 
3544
                                                " FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='three_attempts'");
 
3545
                                if (rs.next()) {
 
3546
                                        if (!rs.getBoolean(1)) install_plugin_in_runtime = true;
 
3547
                                } else {
 
3548
                                        install_plugin_in_runtime = true;
 
3549
                                }
 
3550
 
 
3551
                                if (install_plugin_in_runtime) {
 
3552
                                        String ext = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1 ? ".dll" : ".so";
 
3553
                                        this.stmt.executeUpdate("INSTALL PLUGIN three_attempts SONAME 'auth"+ext+"'");
 
3554
                                }
 
3555
 
 
3556
                                String dbname = null;
 
3557
                                this.rs = this.stmt.executeQuery("select database() as dbname");
 
3558
                                if(this.rs.first()) {
 
3559
                                        dbname = this.rs.getString("dbname");
 
3560
                                }
 
3561
                                if (dbname == null) assertTrue("No database selected", false);
 
3562
                                
 
3563
                                this.stmt.executeUpdate("grant usage on *.* to 'wl5851user3'@'%' identified WITH three_attempts AS 'three_attempts_password'");
 
3564
                                this.stmt.executeUpdate("delete from mysql.db where user='wl5851user3'");
 
3565
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'wl5851user3', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3566
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'wl5851user3', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3567
                                this.stmt.executeUpdate("flush privileges");
 
3568
                                
 
3569
                                Properties props = new Properties();
 
3570
                                props.setProperty("user", "wl5851user3");
 
3571
                                props.setProperty("password", "three_attempts_password");
 
3572
                                props.setProperty("authenticationPlugins", "testsuite.regression.ConnectionRegressionTest$ThreeAttemptsPlugin");
 
3573
 
 
3574
                                Connection testConn = null;
 
3575
                                Statement testSt = null;
 
3576
                                ResultSet testRs = null;
 
3577
                                try {
 
3578
                                        testConn = getConnectionWithProps(props);
 
3579
                                        testSt = testConn.createStatement();
 
3580
                                        testRs = testSt.executeQuery("select USER(),CURRENT_USER()");
 
3581
                                        testRs.next();
 
3582
                                        assertEquals("wl5851user3", testRs.getString(1).split("@")[0]);
 
3583
                                        
 
3584
                                } finally {
 
3585
                                        if (testRs != null) testRs.close();
 
3586
                                        if (testSt != null) testSt.close();
 
3587
                                        if (testConn != null) testConn.close();
 
3588
                                }
 
3589
 
 
3590
                        } finally {
 
3591
                                this.stmt.executeUpdate("drop user 'wl5851user3'@'%'");
 
3592
                                if (install_plugin_in_runtime) {
 
3593
                                        this.stmt.executeUpdate("UNINSTALL PLUGIN three_attempts");
 
3594
                                }
 
3595
                        }
 
3596
                }
 
3597
        }
 
3598
 
 
3599
        public static class AuthTestPlugin implements AuthenticationPlugin {
 
3600
                
 
3601
                private String password = null;
 
3602
 
 
3603
                public void init(com.mysql.jdbc.Connection conn1, Properties props) throws SQLException {
 
3604
                }
 
3605
 
 
3606
                public void destroy() {
 
3607
                        this.password = null;
 
3608
                }
 
3609
 
 
3610
                public String getProtocolPluginName() {
 
3611
                        return "auth_test_plugin";
 
3612
                }
 
3613
 
 
3614
                public boolean requiresConfidentiality() {
 
3615
                        return false;
 
3616
                }
 
3617
 
 
3618
                public boolean isReusable() {
 
3619
                        return true;
 
3620
                }
 
3621
 
 
3622
                public void setAuthenticationParameters(String user, String password) {
 
3623
                        this.password = password;
 
3624
                }
 
3625
 
 
3626
                public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer) throws SQLException {
 
3627
                                toServer.clear();
 
3628
                                Buffer bresp = new Buffer(StringUtils.getBytes(this.password));
 
3629
                                toServer.add(bresp);
 
3630
                        return true;
 
3631
                }
 
3632
 
 
3633
        }
 
3634
 
 
3635
        public static class TwoQuestionsPlugin implements AuthenticationPlugin {
 
3636
                
 
3637
                private String password = null;
 
3638
 
 
3639
                public void init(com.mysql.jdbc.Connection conn1, Properties props) throws SQLException {
 
3640
                }
 
3641
 
 
3642
                public void destroy() {
 
3643
                        this.password = null;
 
3644
                }
 
3645
 
 
3646
                public String getProtocolPluginName() {
 
3647
                        return "dialog";
 
3648
                }
 
3649
 
 
3650
                public boolean requiresConfidentiality() {
 
3651
                        return false;
 
3652
                }
 
3653
 
 
3654
                public boolean isReusable() {
 
3655
                        return true;
 
3656
                }
 
3657
 
 
3658
                public void setAuthenticationParameters(String user, String password) {
 
3659
                        this.password = password;
 
3660
                }
 
3661
 
 
3662
                public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer) throws SQLException {
 
3663
                                toServer.clear();
 
3664
                                if ((fromServer.getByteBuffer()[0] & 0xff) == 4) {
 
3665
                                        Buffer bresp = new Buffer(StringUtils.getBytes(this.password));
 
3666
                                        toServer.add(bresp);
 
3667
                                } else {
 
3668
                                        Buffer bresp = new Buffer(StringUtils.getBytes("yes, of course"));
 
3669
                                        toServer.add(bresp);
 
3670
                                }
 
3671
                        return true;
 
3672
                }
 
3673
 
 
3674
        }
 
3675
 
 
3676
        public static class ThreeAttemptsPlugin implements AuthenticationPlugin {
 
3677
                
 
3678
                private String password = null;
 
3679
                private int counter = 0;
 
3680
 
 
3681
                public void init(com.mysql.jdbc.Connection conn1, Properties props) throws SQLException {
 
3682
                        this.counter = 0;
 
3683
                }
 
3684
 
 
3685
                public void destroy() {
 
3686
                        this.password = null;
 
3687
                        this.counter = 0;
 
3688
                }
 
3689
 
 
3690
                public String getProtocolPluginName() {
 
3691
                        return "dialog";
 
3692
                }
 
3693
 
 
3694
                public boolean requiresConfidentiality() {
 
3695
                        return false;
 
3696
                }
 
3697
 
 
3698
                public boolean isReusable() {
 
3699
                        return true;
 
3700
                }
 
3701
 
 
3702
                public void setAuthenticationParameters(String user, String password) {
 
3703
                        this.password = password;
 
3704
                }
 
3705
 
 
3706
                public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer) throws SQLException {
 
3707
                        toServer.clear();
 
3708
                        this.counter++;
 
3709
                        if ((fromServer.getByteBuffer()[0] & 0xff) == 4) {
 
3710
                                Buffer bresp = new Buffer(StringUtils.getBytes(counter>2 ? this.password : "wrongpassword"+counter));
 
3711
                                toServer.add(bresp);
 
3712
                        } else {
 
3713
                                Buffer bresp = new Buffer(fromServer.getByteBuffer());
 
3714
                                toServer.add(bresp);
 
3715
                        }
 
3716
                        return true;
 
3717
                }
 
3718
 
 
3719
        }
 
3720
 
 
3721
        public void testOldPasswordPlugin() throws Exception {
 
3722
 
 
3723
                boolean secure_auth = false;
 
3724
                this.rs = this.stmt.executeQuery("SHOW VARIABLES LIKE 'secure_auth'");
 
3725
                while (this.rs.next()) {
 
3726
                        secure_auth = "ON".equalsIgnoreCase(this.rs.getString(2));
 
3727
                }
 
3728
 
 
3729
                if (versionMeetsMinimum(5, 5, 7) && !secure_auth) {
 
3730
 
 
3731
                        String dbname = null;
 
3732
                        this.rs = this.stmt.executeQuery("select database() as dbname");
 
3733
                        if(this.rs.first()) {
 
3734
                                dbname = this.rs.getString("dbname");
 
3735
                        }
 
3736
                        if (dbname == null) assertTrue("No database selected", false);
 
3737
                        
 
3738
                        Connection adminConn = null;
 
3739
                        Statement adminStmt = null;
 
3740
 
 
3741
                        try {
 
3742
                                testOldPasswordPlugin_createUsers(this.stmt, dbname);
 
3743
                        } catch (Exception e) {
 
3744
                                adminConn = getAdminConnection();
 
3745
                                if (adminConn == null) {
 
3746
                                        assertTrue("Lack of grant permissions. Change default user or set com.mysql.jdbc.testsuite.admin-url property.", false);
 
3747
                                } else {
 
3748
                                        adminStmt = adminConn.createStatement();
 
3749
                                        testOldPasswordPlugin_createUsers(adminStmt, dbname);
 
3750
                                }
 
3751
                                
 
3752
                        }
 
3753
                        
 
3754
                        Properties props = new Properties();
 
3755
                        props.setProperty("user", "bug64983user1");
 
3756
                        props.setProperty("password", "pwd");
 
3757
                        props.setProperty("defaultAuthenticationPlugin", "com.mysql.jdbc.authentication.MysqlOldPasswordPlugin");
 
3758
 
 
3759
                        Connection testConn = null;
 
3760
                        Statement testSt = null;
 
3761
                        ResultSet testRs = null;
 
3762
 
 
3763
                        try {
 
3764
                                testConn = getConnectionWithProps(props);
 
3765
                                testSt = testConn.createStatement();
 
3766
                                testRs = testSt.executeQuery("select USER()");
 
3767
                                testRs.next();
 
3768
                                assertEquals("bug64983user1", testRs.getString(1).split("@")[0]);
 
3769
                                
 
3770
                                ((MySQLConnection)testConn).changeUser("bug64983user2", "");
 
3771
                                testRs = testSt.executeQuery("select USER()");
 
3772
                                testRs.next();
 
3773
                                assertEquals("bug64983user2", testRs.getString(1).split("@")[0]);
 
3774
                                
 
3775
                        } finally {
 
3776
                                if (testRs != null) {
 
3777
                                        testRs.close();
 
3778
                                }
 
3779
                                if (testSt != null) {
 
3780
                                        testSt.close();
 
3781
                                }
 
3782
                                if (testConn != null) {
 
3783
                                        testConn.close();
 
3784
                                }
 
3785
                                if (adminStmt != null) {
 
3786
                                        adminStmt.executeUpdate("drop user 'bug64983user1'@'%'");
 
3787
                                        adminStmt.executeUpdate("drop user 'bug64983user2'@'%'");
 
3788
                                        adminStmt.close();
 
3789
                                } else {
 
3790
                                        this.stmt.executeUpdate("drop user 'bug64983user1'@'%'");
 
3791
                                        this.stmt.executeUpdate("drop user 'bug64983user2'@'%'");
 
3792
                                }
 
3793
                                if (adminConn != null) {
 
3794
                                        adminConn.close();
 
3795
                                }
 
3796
                        }
 
3797
 
 
3798
                }
 
3799
        }
 
3800
 
 
3801
        public void testOldPasswordPlugin_createUsers(Statement adminStmt, String dbname) throws Exception {
 
3802
                
 
3803
                adminStmt.executeUpdate("grant usage on *.* to 'bug64983user1'@'%'");
 
3804
                adminStmt.executeUpdate("set password for 'bug64983user1'@'%' = OLD_PASSWORD('pwd')");
 
3805
                adminStmt.executeUpdate("delete from mysql.db where user='bug64983user1'");
 
3806
                adminStmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'bug64983user1', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3807
                adminStmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'bug64983user1', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3808
 
 
3809
                adminStmt.executeUpdate("grant usage on *.* to 'bug64983user2'@'%'");
 
3810
                adminStmt.executeUpdate("set password for 'bug64983user2'@'%' = OLD_PASSWORD('')");
 
3811
                adminStmt.executeUpdate("delete from mysql.db where user='bug64983user2'");
 
3812
                adminStmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'bug64983user2', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3813
                adminStmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'bug64983user2', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3814
 
 
3815
                adminStmt.executeUpdate("flush privileges");
 
3816
        }
 
3817
 
 
3818
        public void testAuthCleartextPlugin() throws Exception {
 
3819
                if (versionMeetsMinimum(5, 5, 7)) {
 
3820
 
 
3821
                        boolean install_plugin_in_runtime = false;
 
3822
                        try {
 
3823
 
 
3824
                                // install plugin if required
 
3825
                                this.rs = this.stmt.executeQuery(
 
3826
                                                "select (PLUGIN_LIBRARY LIKE 'auth_test_plugin%') as `TRUE`" +
 
3827
                                                " FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='cleartext_plugin_server'");
 
3828
                                if (rs.next()) {
 
3829
                                        if (!rs.getBoolean(1)) install_plugin_in_runtime = true;
 
3830
                                } else {
 
3831
                                        install_plugin_in_runtime = true;
 
3832
                                }
 
3833
 
 
3834
                                if (install_plugin_in_runtime) {
 
3835
                                        String ext = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1 ? ".dll" : ".so";
 
3836
                                        this.stmt.executeUpdate("INSTALL PLUGIN cleartext_plugin_server SONAME 'auth_test_plugin"+ext+"'");
 
3837
                                }
 
3838
 
 
3839
                                String dbname = null;
 
3840
                                this.rs = this.stmt.executeQuery("select database() as dbname");
 
3841
                                if(this.rs.first()) {
 
3842
                                        dbname = this.rs.getString("dbname");
 
3843
                                }
 
3844
                                if (dbname == null) assertTrue("No database selected", false);
 
3845
                                
 
3846
                                // create proxy users
 
3847
                                this.stmt.executeUpdate("grant usage on *.* to 'wl5735user'@'%' identified WITH cleartext_plugin_server AS ''");
 
3848
                                this.stmt.executeUpdate("delete from mysql.db where user='wl5735user'");
 
3849
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'wl5735user', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3850
                                this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'wl5735user', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3851
                                this.stmt.executeUpdate("flush privileges");
 
3852
                                
 
3853
                                Properties props = new Properties();
 
3854
                                props.setProperty("user", "wl5735user");
 
3855
                                props.setProperty("password", "");
 
3856
 
 
3857
                                Connection testConn = null;
 
3858
                                Statement testSt = null;
 
3859
                                ResultSet testRs = null;
 
3860
                                try {
 
3861
                                        try {
 
3862
                                                testConn = getConnectionWithProps(props);
 
3863
                                                assertFalse("SQLException expected due to SSL connection is required", true);
 
3864
                                        } catch (SQLException e) {
 
3865
                                                String trustStorePath = "src/testsuite/ssl-test-certs/test-cert-store";
 
3866
                                                System.setProperty("javax.net.ssl.keyStore", trustStorePath);
 
3867
                                                System.setProperty("javax.net.ssl.keyStorePassword", "password");
 
3868
                                                System.setProperty("javax.net.ssl.trustStore", trustStorePath);
 
3869
                                                System.setProperty("javax.net.ssl.trustStorePassword", "password");
 
3870
                                                props.setProperty("useSSL", "true");
 
3871
                                                props.setProperty("requireSSL", "true");
 
3872
                                                testConn = getConnectionWithProps(props);
 
3873
                                        }
 
3874
                                        
 
3875
                                        testSt = testConn.createStatement();
 
3876
                                        testRs = testSt.executeQuery("select USER(),CURRENT_USER()");
 
3877
                                        testRs.next();
 
3878
                                        
 
3879
                                        assertEquals("wl5735user", testRs.getString(1).split("@")[0]);
 
3880
                                        assertEquals("wl5735user", testRs.getString(2).split("@")[0]);
 
3881
                                        
 
3882
                                } finally {
 
3883
                                        if (testRs != null) testRs.close();
 
3884
                                        if (testSt != null) testSt.close();
 
3885
                                        if (testConn != null) testConn.close();
 
3886
                                }
 
3887
 
 
3888
                        } finally {
 
3889
                                this.stmt.executeUpdate("drop user 'wl5735user'@'%'");
 
3890
                                if (install_plugin_in_runtime) {
 
3891
                                        this.stmt.executeUpdate("UNINSTALL PLUGIN cleartext_plugin_server");
 
3892
                                }
 
3893
                        }
 
3894
                }
 
3895
        }
 
3896
 
 
3897
        public void testSha256PasswordPlugin() throws Exception {
 
3898
                if (versionMeetsMinimum(5, 6, 5)) {
 
3899
 
 
3900
                        // check that sha256_password plugin is available
 
3901
                        boolean plugin_is_active = false;
 
3902
                        this.rs = this.stmt.executeQuery("select (PLUGIN_STATUS='ACTIVE') as `TRUE` from INFORMATION_SCHEMA.PLUGINS where PLUGIN_NAME='sha256_password'");
 
3903
                        if (rs.next()) {
 
3904
                                plugin_is_active = rs.getBoolean(1);
 
3905
                        }
 
3906
 
 
3907
                        if (plugin_is_active) {
 
3908
                                try {
 
3909
                                        String dbname = null;
 
3910
                                        this.rs = this.stmt.executeQuery("select database() as dbname");
 
3911
                                        if(this.rs.first()) {
 
3912
                                                dbname = this.rs.getString("dbname");
 
3913
                                        }
 
3914
                                        if (dbname == null) assertTrue("No database selected", false);
 
3915
                                        
 
3916
                                        // create proxy users
 
3917
                                        this.stmt.executeUpdate("SET @current_old_passwords = @@global.old_passwords");
 
3918
                                        
 
3919
                                        this.stmt.executeUpdate("grant usage on *.* to 'wl5602user'@'%' identified WITH sha256_password");
 
3920
                                        this.stmt.executeUpdate("SET GLOBAL old_passwords= 2");
 
3921
                                        this.stmt.executeUpdate("SET SESSION old_passwords= 2");
 
3922
                                        this.stmt.executeUpdate("set password for 'wl5602user'@'%' = PASSWORD('pwd')");
 
3923
                                        this.stmt.executeUpdate("delete from mysql.db where user='wl5602user'");
 
3924
                                        this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', '"+dbname+"', 'wl5602user', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3925
                                        this.stmt.executeUpdate("insert into mysql.db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv,Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv,Show_view_priv, Create_routine_priv, Alter_routine_priv, Execute_priv, Event_priv, Trigger_priv) VALUES ('%', 'information\\_schema', 'wl5602user', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N')");
 
3926
                                        this.stmt.executeUpdate("flush privileges");
 
3927
                                        
 
3928
                                        Properties props = new Properties();
 
3929
                                        props.setProperty("user", "wl5602user");
 
3930
                                        props.setProperty("password", "pwd");
 
3931
 
 
3932
                                        Connection testConn = null;
 
3933
                                        Statement testSt = null;
 
3934
                                        ResultSet testRs = null;
 
3935
                                        try {
 
3936
                                                try {
 
3937
                                                        testConn = getConnectionWithProps(props);
 
3938
                                                        assertFalse("SQLException expected due to SSL connection is required", true);
 
3939
                                                } catch (SQLException e) {
 
3940
                                                        String trustStorePath = "src/testsuite/ssl-test-certs/test-cert-store";
 
3941
                                                        System.setProperty("javax.net.ssl.keyStore", trustStorePath);
 
3942
                                                        System.setProperty("javax.net.ssl.keyStorePassword", "password");
 
3943
                                                        System.setProperty("javax.net.ssl.trustStore", trustStorePath);
 
3944
                                                        System.setProperty("javax.net.ssl.trustStorePassword", "password");
 
3945
                                                        props.setProperty("useSSL", "true");
 
3946
                                                        props.setProperty("requireSSL", "true");
 
3947
                                                        testConn = getConnectionWithProps(props);
 
3948
                                                }
 
3949
                                                
 
3950
                                                testSt = testConn.createStatement();
 
3951
                                                testRs = testSt.executeQuery("select USER(),CURRENT_USER()");
 
3952
                                                testRs.next();
 
3953
                                                
 
3954
                                                assertEquals("wl5602user", testRs.getString(1).split("@")[0]);
 
3955
                                                assertEquals("wl5602user", testRs.getString(2).split("@")[0]);
 
3956
                                                
 
3957
                                        } finally {
 
3958
                                                if (testRs != null) testRs.close();
 
3959
                                                if (testSt != null) testSt.close();
 
3960
                                                if (testConn != null) testConn.close();
 
3961
                                        }
 
3962
 
 
3963
                                } finally {
 
3964
                                        this.stmt.executeUpdate("drop user 'wl5602user'@'%'");
 
3965
                                        this.stmt.executeUpdate("flush privileges");
 
3966
                                        this.stmt.executeUpdate("SET GLOBAL old_passwords = @current_old_passwords");
 
3967
                                }
 
3968
                        }
 
3969
                }
 
3970
        }
 
3971
 
 
3972
        public void testBug36662() throws Exception {
 
3973
 
 
3974
                try {
 
3975
                        String tz1 = TimeUtil.getCanoncialTimezone("MEST", null);
 
3976
                        assertNotNull(tz1);
 
3977
                } catch (Exception e1) {
 
3978
                        String mes1 = e1.getMessage();
 
3979
                        mes1 = mes1.substring(mes1.lastIndexOf("The timezones that 'MEST' maps to are:")+39);
 
3980
                        try {
 
3981
                                String tz2 = TimeUtil.getCanoncialTimezone("CEST", null);
 
3982
                                assertEquals(mes1, tz2);
 
3983
                        } catch (Exception e2) {
 
3984
                                String mes2 = e2.getMessage();
 
3985
                                mes2 = mes2.substring(mes2.lastIndexOf("The timezones that 'CEST' maps to are:")+39);
 
3986
                                assertEquals(mes1, mes2);
 
3987
                        }
 
3988
                }
 
3989
        }
 
3990
 
 
3991
        public void testBug37931() throws Exception {
 
3992
 
 
3993
                Connection _conn = null;
 
3994
                Properties props = new Properties();
 
3995
                props.setProperty("characterSetResults", "ISO8859-1");
 
3996
 
 
3997
                try {
 
3998
                        _conn = getConnectionWithProps(props);
 
3999
                        assertTrue("This point should not be reached.", false);
 
4000
                } catch (Exception e) {
 
4001
                        assertEquals(
 
4002
                                        "Can't map ISO8859-1 given for characterSetResults to a supported MySQL encoding.",
 
4003
                                        e.getMessage());
 
4004
                } finally {
 
4005
                        if (_conn != null) {
 
4006
                                _conn.close();
 
4007
                        }
 
4008
                }
 
4009
 
 
4010
                props.setProperty("characterSetResults", "null");
 
4011
 
 
4012
                try {
 
4013
                        _conn = getConnectionWithProps(props);
 
4014
 
 
4015
                        Statement _stmt = _conn.createStatement();
 
4016
                        ResultSet _rs = _stmt.executeQuery("show variables where variable_name='character_set_results'");
 
4017
                        if (_rs.next()) {
 
4018
                                String res = _rs.getString(2);
 
4019
                                if (res == null || "NULL".equalsIgnoreCase(res) || res.length() == 0) {
 
4020
                                        assertTrue(true);
 
4021
                                } else {
 
4022
                                        assertTrue(false);
 
4023
                                }
 
4024
                        }
 
4025
                } finally {
 
4026
                        if (_conn != null) {
 
4027
                                _conn.close();
 
4028
                        }
 
4029
                }
 
4030
        }
 
4031
 
 
4032
        public void testBug64205() throws Exception {
 
4033
                if (versionMeetsMinimum(5, 5, 0)) {
 
4034
                        String dbname = null;
 
4035
                        this.rs = this.stmt.executeQuery("select database() as dbname");
 
4036
                        if(this.rs.first()) {
 
4037
                                dbname = this.rs.getString("dbname");
 
4038
                        }
 
4039
                        if (dbname == null) assertTrue("No database selected", false);
 
4040
 
 
4041
                        Properties props = new Properties();
 
4042
                        props.setProperty("characterEncoding", "EUC_JP");
 
4043
 
 
4044
                        Connection testConn = null;
 
4045
                        Statement testSt = null;
 
4046
                        ResultSet testRs = null;
 
4047
                        try {
 
4048
                                testConn = getConnectionWithProps(props);
 
4049
                                testSt = testConn.createStatement();
 
4050
                                testRs = testSt.executeQuery("SELECT * FROM `"+dbname+"`.`ほげほげ`");
 
4051
                        } catch (SQLException e1) {
 
4052
                                if (e1 instanceof MySQLSyntaxErrorException) {
 
4053
                                        assertEquals("Table '"+dbname+".ほげほげ' doesn't exist", e1.getMessage());
 
4054
                                } else if (e1.getErrorCode() == MysqlErrorNumbers.ER_FILE_NOT_FOUND) {
 
4055
                                        // this could happen on Windows with 5.5 and 5.6 servers where BUG#14642248 exists
 
4056
                                        assertTrue(e1.getMessage().contains("Can't find file"));
 
4057
                                } else {
 
4058
                                        throw e1;
 
4059
                                }
 
4060
 
 
4061
                                try {
 
4062
                                        props.setProperty("characterSetResults", "SJIS");
 
4063
                                        testConn = getConnectionWithProps(props);
 
4064
                                        testSt = testConn.createStatement();
 
4065
                                        testSt.execute("SET lc_messages = 'ru_RU'");
 
4066
                                        testRs = testSt.executeQuery("SELECT * FROM `"+dbname+"`.`ほげほげ`");
 
4067
                                } catch (SQLException e2) {
 
4068
                                        if (e2 instanceof MySQLSyntaxErrorException) {
 
4069
                                                assertEquals("\u0422\u0430\u0431\u043b\u0438\u0446\u0430 '"+dbname+".ほげほげ' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442", e2.getMessage());
 
4070
                                        } else if (e2.getErrorCode() == MysqlErrorNumbers.ER_FILE_NOT_FOUND) {
 
4071
                                                // this could happen on Windows with 5.5 and 5.6 servers where BUG#14642248 exists
 
4072
                                                assertTrue("File not found error message should be russian but is this one: "+e2.getMessage(), e2.getMessage().indexOf("\u0444\u0430\u0439\u043b") > -1);
 
4073
                                        } else {
 
4074
                                                throw e2;
 
4075
                                        }
 
4076
                                }                       
 
4077
 
 
4078
                        } finally {
 
4079
                                if (testRs != null) testRs.close();
 
4080
                                if (testSt != null) testSt.close();
 
4081
                                if (testConn != null) testConn.close();
 
4082
                        }
 
4083
                }
 
4084
        }
 
4085
        
 
4086
        public void testIsLocal() throws Exception {
 
4087
                boolean normalState = ((ConnectionImpl) conn).isServerLocal();
 
4088
                
 
4089
                if (normalState) {
 
4090
                        boolean isNotLocal = ((ConnectionImpl) getConnectionWithProps(StandardSocketFactory.IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME + "=www.oracle.com:3306")).isServerLocal();
 
4091
                        
 
4092
                        assertFalse(isNotLocal == normalState);
 
4093
                }
 
4094
        }
 
4095
 
 
4096
        /**
 
4097
         * Tests fix for BUG#57662, Incorrect Query Duration When useNanosForElapsedTime Enabled
 
4098
         * 
 
4099
         * @throws Exception
 
4100
         *             if the test fails.
 
4101
         */
 
4102
        public void testBug57662() throws Exception {
 
4103
 
 
4104
                createTable("testBug57662", "(x VARCHAR(10) NOT NULL DEFAULT '')");
 
4105
                Connection conn_is = null;
 
4106
                try {
 
4107
                        Properties props = new Properties();
 
4108
                        props.setProperty("profileSQL", "true");
 
4109
                        props.setProperty("useNanosForElapsedTime", "true");
 
4110
                        props.setProperty("logger", "testsuite.simple.TestBug57662Logger");
 
4111
                        conn_is = getConnectionWithProps(props);
 
4112
                        this.rs = conn_is.getMetaData().getColumns(null, null,
 
4113
                                        "testBug57662", "%");
 
4114
                        
 
4115
                        assertFalse(((testsuite.simple.TestBug57662Logger)((ConnectionImpl) conn_is).getLog()).hasNegativeDurations);
 
4116
 
 
4117
                } finally {
 
4118
                        if (conn_is != null) {
 
4119
                                conn_is.close();
 
4120
                        }
 
4121
                }
 
4122
 
 
4123
        }
 
4124
        
 
4125
        public void testBug14563127() throws Exception {
 
4126
                Properties props = new Properties();
 
4127
                props.setProperty("loadBalanceStrategy",
 
4128
                                ForcedLoadBalanceStrategy.class.getName());
 
4129
                props.setProperty("loadBalanceBlacklistTimeout", "5000");
 
4130
                props.setProperty("loadBalancePingTimeout", "100");
 
4131
                props.setProperty("loadBalanceValidateConnectionOnSwapServer", "true");
 
4132
 
 
4133
                String portNumber = new NonRegisteringDriver().parseURL(dbUrl, null)
 
4134
                                .getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY);
 
4135
 
 
4136
                if (portNumber == null) {
 
4137
                        portNumber = "3306";
 
4138
                }
 
4139
 
 
4140
                ForcedLoadBalanceStrategy.forceFutureServer("first:" + portNumber, -1);
 
4141
                Connection conn2 = this.getUnreliableLoadBalancedConnection(
 
4142
                                new String[] { "first", "second" }, props);
 
4143
                conn2.setAutoCommit(false);
 
4144
                conn2.createStatement().execute("SELECT 1");
 
4145
                
 
4146
                // make sure second is added to active connections cache:
 
4147
                ForcedLoadBalanceStrategy.forceFutureServer("second:" + portNumber, -1);
 
4148
                conn2.commit();
 
4149
                
 
4150
                // switch back to first:
 
4151
                ForcedLoadBalanceStrategy.forceFutureServer("first:" + portNumber, -1);
 
4152
                conn2.commit();
 
4153
                
 
4154
                // kill second while still in cache:
 
4155
                UnreliableSocketFactory.downHost("second");
 
4156
                
 
4157
                // force second host to be selected next time:
 
4158
                ForcedLoadBalanceStrategy.forceFutureServer("second:" + portNumber, 1);
 
4159
                
 
4160
                try {
 
4161
                        conn2.commit(); // will be on second after this
 
4162
                        assertTrue("Connection should not be closed", !conn2.isClosed());
 
4163
                } catch (SQLException e) {
 
4164
                        fail("Should not error because failure to select another server.");
 
4165
                }
 
4166
                conn2.close();
 
4167
 
 
4168
                
 
4169
        }
 
4170
 
 
4171
        /**
 
4172
         * Tests fix for BUG#11237 useCompression=true and LOAD DATA LOCAL INFILE SQL Command
 
4173
         * 
 
4174
         * @throws Exception
 
4175
         *             if any errors occur
 
4176
         */
 
4177
        public void testBug11237() throws Exception {
 
4178
                this.rs = this.stmt.executeQuery("SHOW VARIABLES LIKE 'max_allowed_packet'");
 
4179
                this.rs.next();
 
4180
                if (this.rs.getInt(2) < 4+1024*1024*16-1) {
 
4181
                        fail("You need to increase max_allowed_packet to at least "+(4+1024*1024*16-1)+" before running this test!");
 
4182
                }
 
4183
 
 
4184
                int requiredSize = 1024*1024*300;
 
4185
                int fieldLength = 1023;
 
4186
                int loops = requiredSize / 2 / (fieldLength + 1);
 
4187
                
 
4188
                File testFile = File.createTempFile("cj-testloaddata", ".dat");
 
4189
                testFile.deleteOnExit();
 
4190
                cleanupTempFiles(testFile, "cj-testloaddata");
 
4191
 
 
4192
                BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(testFile));
 
4193
 
 
4194
                for (int i = 0; i < loops; i++) {
 
4195
                        for (int j = 0; j < fieldLength; j++) {
 
4196
                                bOut.write("a".getBytes()[0]);
 
4197
                        }
 
4198
                        bOut.write("\t".getBytes()[0]);
 
4199
                        for (int j = 0; j < fieldLength; j++) {
 
4200
                                bOut.write("b".getBytes()[0]);
 
4201
                        }
 
4202
                        bOut.write("\n".getBytes()[0]);
 
4203
                }
 
4204
 
 
4205
                bOut.flush();
 
4206
                bOut.close();
 
4207
 
 
4208
                createTable("testBug11237", "(field1 VARCHAR(1024), field2 VARCHAR(1024))");
 
4209
 
 
4210
                StringBuffer fileNameBuf = null;
 
4211
 
 
4212
                if (File.separatorChar == '\\') {
 
4213
                        fileNameBuf = new StringBuffer();
 
4214
 
 
4215
                        String fileName = testFile.getAbsolutePath();
 
4216
                        int fileNameLength = fileName.length();
 
4217
 
 
4218
                        for (int i = 0; i < fileNameLength; i++) {
 
4219
                                char c = fileName.charAt(i);
 
4220
 
 
4221
                                if (c == '\\') {
 
4222
                                        fileNameBuf.append("/");
 
4223
                                } else {
 
4224
                                        fileNameBuf.append(c);
 
4225
                                }
 
4226
                        }
 
4227
                } else {
 
4228
                        fileNameBuf = new StringBuffer(testFile.getAbsolutePath());
 
4229
                }
 
4230
 
 
4231
                Properties props = new Properties();
 
4232
                props.put("useCompression", "true");
 
4233
                Connection conn1 = getConnectionWithProps(props);
 
4234
                Statement stmt1 = conn1.createStatement();
 
4235
 
 
4236
                int updateCount = stmt1
 
4237
                                .executeUpdate("LOAD DATA LOCAL INFILE '"
 
4238
                                                + fileNameBuf.toString()
 
4239
                                                + "' INTO TABLE testBug11237" +
 
4240
                                                " CHARACTER SET " + CharsetMapping.getMysqlEncodingForJavaEncoding(((MySQLConnection)this.conn).getEncoding(), (com.mysql.jdbc.Connection) conn1));
 
4241
 
 
4242
                assertTrue(updateCount == loops);
 
4243
 
 
4244
        }
 
4245
        
 
4246
        public void testStackOverflowOnMissingInterceptor() throws Exception {
 
4247
                try {
 
4248
                        Properties props = new Properties();
 
4249
                        props.setProperty("statementInterceptors", "fooBarBaz");
 
4250
                        
 
4251
                        getConnectionWithProps(props).close();
 
4252
                } catch (Exception e) {
 
4253
                }
 
4254
        }
 
4255
 
 
4256
        public void testExpiredPassword() throws Exception {
 
4257
                if (versionMeetsMinimum(5, 6, 10)) {
 
4258
                        Connection testConn = null;
 
4259
                        Statement testSt = null;
 
4260
                        ResultSet testRs = null;
 
4261
 
 
4262
                        Properties urlProps = new NonRegisteringDriver().parseURL(dbUrl, null);
 
4263
                        String dbname = urlProps.getProperty(Driver.DBNAME_PROPERTY_KEY);
 
4264
 
 
4265
                        try {
 
4266
 
 
4267
                                this.stmt.executeUpdate("grant all on `"+dbname+"`.* to 'must_change1'@'%' IDENTIFIED BY 'aha'");
 
4268
                                this.stmt.executeUpdate("grant all on `"+dbname+"`.* to 'must_change2'@'%' IDENTIFIED BY 'aha'");
 
4269
                                this.stmt.executeUpdate("ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
 
4270
 
 
4271
                                Properties props = new Properties();
 
4272
 
 
4273
                                // ALTER USER can be prepared as of 5.6.8 (BUG#14646014)
 
4274
                                if (versionMeetsMinimum(5, 6, 8)) {
 
4275
                                        props.setProperty("useServerPrepStmts", "true");
 
4276
                                        testConn = getConnectionWithProps(props);
 
4277
 
 
4278
                                        this.pstmt = testConn.prepareStatement("ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
 
4279
                                        this.pstmt.executeUpdate();
 
4280
                                        this.pstmt.close();
 
4281
 
 
4282
                                        this.pstmt = testConn.prepareStatement("ALTER USER ? PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
 
4283
                                        this.pstmt.setString(1, "must_change1");
 
4284
                                        this.pstmt.executeUpdate();
 
4285
                                        this.pstmt.close();
 
4286
 
 
4287
                                        testConn.close();
 
4288
                                }
 
4289
 
 
4290
                                props.setProperty("user", "must_change1");
 
4291
                                props.setProperty("password", "aha");
 
4292
 
 
4293
                                try {
 
4294
                                        testConn = getConnectionWithProps(props);
 
4295
                                        fail("SQLException expected due to password expired");
 
4296
                                } catch (SQLException e1) {
 
4297
                                        
 
4298
                                        if (e1.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD ||
 
4299
                                                e1.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) {
 
4300
 
 
4301
                                                props.setProperty("disconnectOnExpiredPasswords", "false");
 
4302
                                                try {
 
4303
                                                        testConn = getConnectionWithProps(props);
 
4304
                                                        testSt = testConn.createStatement();
 
4305
                                                        testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
 
4306
                                                        fail("SQLException expected due to password expired");
 
4307
 
 
4308
                                                } catch (SQLException e3) {
 
4309
                                                        if (e3.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) {
 
4310
                                                                testConn = getConnectionWithProps(props);
 
4311
                                                                testSt = testConn.createStatement();
 
4312
                                                        }
 
4313
                                                        testSt.executeUpdate("SET PASSWORD = PASSWORD('newpwd')");
 
4314
                                                        testConn.close();
 
4315
                                                        
 
4316
                                                        props.setProperty("user", "must_change1");
 
4317
                                                        props.setProperty("password", "newpwd");
 
4318
                                                        props.setProperty("disconnectOnExpiredPasswords", "true");
 
4319
                                                        testConn = getConnectionWithProps(props);
 
4320
                                                        testSt = testConn.createStatement();
 
4321
                                                        testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
 
4322
                                                        assertTrue(testRs.next());
 
4323
                                                        
 
4324
                                                        // change user
 
4325
                                                        try {
 
4326
                                                                ((MySQLConnection) testConn).changeUser("must_change2", "aha");
 
4327
                                                                fail("SQLException expected due to password expired");
 
4328
 
 
4329
                                                        } catch (SQLException e4) {
 
4330
                                                                if (e4.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD ||
 
4331
                                                                        e4.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) {
 
4332
                                                                        props.setProperty("disconnectOnExpiredPasswords", "false");
 
4333
                                                                        testConn = getConnectionWithProps(props);
 
4334
                                                                        
 
4335
                                                                        try {
 
4336
                                                                                ((MySQLConnection) testConn).changeUser("must_change2", "aha");
 
4337
                                                                                testSt = testConn.createStatement();
 
4338
                                                                                testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
 
4339
                                                                                fail("SQLException expected due to password expired");
 
4340
 
 
4341
                                                                        } catch (SQLException e5) {
 
4342
                                                                                if (e5.getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) {
 
4343
                                                                                        testConn = getConnectionWithProps(props);
 
4344
                                                                                        testSt = testConn.createStatement();
 
4345
                                                                                }
 
4346
                                                                                testSt.executeUpdate("SET PASSWORD = PASSWORD('newpwd')");
 
4347
                                                                                testConn.close();
 
4348
 
 
4349
                                                                                props.setProperty("user", "must_change2");
 
4350
                                                                                props.setProperty("password", "newpwd");
 
4351
                                                                                props.setProperty("disconnectOnExpiredPasswords", "true");
 
4352
                                                                                testConn = getConnectionWithProps(props);
 
4353
                                                                                testSt = testConn.createStatement();
 
4354
                                                                                testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
 
4355
                                                                                assertTrue(testRs.next());
 
4356
                                                                                
 
4357
                                                                        }                                                                       
 
4358
 
 
4359
                                                                } else {
 
4360
                                                                        throw e4;
 
4361
                                                                }
 
4362
                                                        }
 
4363
                                                        
 
4364
                                                }
 
4365
                                        
 
4366
                                        
 
4367
                                        } else {
 
4368
                                                throw e1;
 
4369
                                        }
 
4370
                                        
 
4371
                                }
 
4372
 
 
4373
                        } finally {
 
4374
                                if (testRs != null) testRs.close();
 
4375
                                if (testSt != null) testSt.close();
 
4376
                                if (testConn != null) testConn.close();
 
4377
                                this.stmt.executeUpdate("drop user 'must_change1'@'%'");
 
4378
                                this.stmt.executeUpdate("drop user 'must_change2'@'%'");
 
4379
                        }
 
4380
                        
 
4381
                }
 
4382
 
 
4383
        }
 
4384
 
 
4385
        public void testBug68011() throws Exception {
 
4386
 
 
4387
                Connection c = null;
 
4388
                try {
 
4389
                        Properties props = new Properties();
 
4390
                        props.setProperty("noDatetimeStringSync", "true");
 
4391
                        props.setProperty("useTimezone", "true");
 
4392
                        c = getConnectionWithProps(props);
 
4393
                } catch (SQLException e) {
 
4394
                        assertTrue(e.getMessage().contains("noDatetimeStringSync"));
 
4395
                } finally {
 
4396
                        if (c != null) {
 
4397
                                c.close();
 
4398
                        }
 
4399
                }
 
4400
        }
 
4401
        
 
4402
        /**
 
4403
         * Tests connection attributes
 
4404
         *
 
4405
         * @throws Exception
 
4406
         */
 
4407
        public void testConnectionAttributes() throws Exception {
 
4408
                if(!versionMeetsMinimum(5, 6)){
 
4409
                        return;
 
4410
                }
 
4411
                Properties props = new Properties();
 
4412
                props.setProperty("connectionAttributes", "first:one,again:two");
 
4413
                props.setProperty("user", "root");
 
4414
                Connection attConn = super.getConnectionWithProps(props);
 
4415
                ResultSet rslt = attConn.createStatement().executeQuery(
 
4416
                                "SELECT * FROM performance_schema.session_connect_attrs WHERE processlist_id = CONNECTION_ID()"
 
4417
                                );
 
4418
                Map<String, Integer> matchedCounts = new HashMap<String, Integer>();
 
4419
                
 
4420
//              disabling until standard values are defined and implemented
 
4421
//              matchedCounts.put("_os", 0);
 
4422
//              matchedCounts.put("_platform", 0);
 
4423
                matchedCounts.put("_runtime_version", 0);
 
4424
                matchedCounts.put("_runtime_vendor", 0);
 
4425
                matchedCounts.put("_client_version", 0);
 
4426
                matchedCounts.put("_client_license", 0);
 
4427
                matchedCounts.put("_client_name", 0);
 
4428
                matchedCounts.put("first", 0);
 
4429
                matchedCounts.put("again", 0);
 
4430
                                
 
4431
                
 
4432
                
 
4433
                while (rslt.next()){
 
4434
                        String key = rslt.getString(2);
 
4435
                        String val = rslt.getString(3);
 
4436
                        if(!matchedCounts.containsKey(key)) {
 
4437
                                fail("Unexpected connection attribute key:  " + key);
 
4438
                        }
 
4439
                        matchedCounts.put(key, matchedCounts.get(key) + 1);
 
4440
                        if (key.equals("_runtime_version")) {
 
4441
                                assertEquals(System.getProperty("java.version"), val);
 
4442
                        } else if (key.equals("_os")) {
 
4443
                                assertEquals(NonRegisteringDriver.OS, val);
 
4444
                        } else if (key.equals("_platform")) {
 
4445
                                assertEquals(NonRegisteringDriver.PLATFORM, val);
 
4446
                        } else if (key.equals("_runtime_vendor")) {
 
4447
                                assertEquals(System.getProperty("java.vendor"), val);
 
4448
                        } else if (key.equals("_client_version")) {
 
4449
                                assertEquals(NonRegisteringDriver.VERSION, val);
 
4450
                        } else if (key.equals("_client_license")) {
 
4451
                                assertEquals(NonRegisteringDriver.LICENSE, val);
 
4452
                        } else if (key.equals("_client_name")) {
 
4453
                                assertEquals(NonRegisteringDriver.NAME, val);
 
4454
                        } else if (key.equals("first")) {
 
4455
                                assertEquals("one", val);
 
4456
                        } else if (key.equals("again")) {
 
4457
                                assertEquals("two", val);
 
4458
                        }
 
4459
                }
 
4460
                
 
4461
                rslt.close();
 
4462
                attConn.close();
 
4463
                
 
4464
                for (String key : matchedCounts.keySet()) {
 
4465
                        if(matchedCounts.get(key) != 1) {
 
4466
                                fail("Incorrect number of entries for key \"" + key + "\": " + matchedCounts.get(key));
 
4467
                        }
 
4468
                }
 
4469
                
 
4470
                props.setProperty("connectionAttributes", "none");
 
4471
                attConn = super.getConnectionWithProps(props);
 
4472
                rslt = attConn.createStatement().executeQuery(
 
4473
                                "SELECT * FROM performance_schema.session_connect_attrs WHERE processlist_id = CONNECTION_ID()"
 
4474
                                );
 
4475
                if(rslt.next()){
 
4476
                        fail("Expected no connection attributes.");
 
4477
                }
 
4478
                
 
4479
                
 
4480
        }       
 
4481
        
 
4482
 
 
4483
        /**
 
4484
         * Tests fix for BUG#16224249 - Deadlock on concurrently used LoadBalancedMySQLConnection
 
4485
         *
 
4486
         * @throws Exception
 
4487
         */
 
4488
        public void testBug16224249() throws Exception {
 
4489
 
 
4490
                Properties props = new NonRegisteringDriver().parseURL(dbUrl, null);
 
4491
                String host = props.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, "localhost");
 
4492
                String port = props.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306");
 
4493
                String hostSpec = host;
 
4494
                if (!NonRegisteringDriver.isHostPropertiesList(host)) {
 
4495
                        hostSpec = host + ":" + port;
 
4496
                }
 
4497
 
 
4498
                String database = props.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);
 
4499
                removeHostRelatedProps(props);
 
4500
                props.remove(NonRegisteringDriver.DBNAME_PROPERTY_KEY);
 
4501
 
 
4502
                StringBuilder configs = new StringBuilder();
 
4503
                for (@SuppressWarnings("rawtypes")
 
4504
                Map.Entry entry : props.entrySet()) {
 
4505
                        configs.append(entry.getKey());
 
4506
                        configs.append("=");
 
4507
                        configs.append(entry.getValue());
 
4508
                        configs.append("&");
 
4509
                }
 
4510
 
 
4511
                String loadbalanceUrl = String.format("jdbc:mysql:loadbalance://%s,%s/%s?%s", hostSpec, hostSpec, database, configs.toString());
 
4512
                String failoverUrl = String.format("jdbc:mysql://%s,%s/%s?%s", hostSpec, "127.0.0.1:"+port, database, configs.toString());
 
4513
 
 
4514
                Connection[] loadbalancedconnection = new Connection[] {
 
4515
                                new NonRegisteringDriver().connect(loadbalanceUrl, null),
 
4516
                                new NonRegisteringDriver().connect(loadbalanceUrl, null),
 
4517
                                new NonRegisteringDriver().connect(loadbalanceUrl, null)
 
4518
                                };
 
4519
 
 
4520
                Connection[] failoverconnection = new Connection[] {
 
4521
                                new NonRegisteringDriver().connect(failoverUrl, null),
 
4522
                                new NonRegisteringDriver().connect(failoverUrl, null),
 
4523
                                new NonRegisteringDriver().connect(failoverUrl, null)
 
4524
                                };
 
4525
 
 
4526
                // WebLogic-style test
 
4527
                Class<?> mysqlCls = null;
 
4528
                Class<?> jcls = failoverconnection[0].getClass(); // the driver-level connection, a Proxy in this case...
 
4529
                ClassLoader jcl = jcls.getClassLoader();
 
4530
                if (jcl != null) {
 
4531
                        mysqlCls = jcl.loadClass("com.mysql.jdbc.Connection");
 
4532
                } else {
 
4533
                        mysqlCls = Class.forName("com.mysql.jdbc.Connection", true, null);
 
4534
                }
 
4535
 
 
4536
                if ( (mysqlCls != null) && (mysqlCls.isAssignableFrom(jcls))) {
 
4537
                        Method abort = mysqlCls.getMethod("abortInternal", new Class[]{});
 
4538
                        boolean hasAbortMethod = abort != null;
 
4539
                        assertTrue("abortInternal() method should be found for connection class " + jcls , hasAbortMethod);
 
4540
                } else {
 
4541
                        fail("com.mysql.jdbc.Connection interface IS NOT ASSIGNABE from connection class " + jcls );
 
4542
                }
 
4543
                //-------------
 
4544
 
 
4545
                // Concurrent test
 
4546
                System.out.println("Warming up");
 
4547
                for (int i = 0; i < failoverconnection.length; i++) {
 
4548
                        this.stmt = failoverconnection[i].createStatement();
 
4549
                        this.pstmt = failoverconnection[i].prepareStatement("SELECT 1 FROM DUAL");
 
4550
                        for (int j = 0; j < 10000; j++) {
 
4551
                                this.pstmt.executeQuery();
 
4552
                                this.stmt.executeQuery("SELECT 1 FROM DUAL");
 
4553
                        }
 
4554
                }
 
4555
 
 
4556
                ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(12);
 
4557
 
 
4558
                ScheduledFuture<?> f1 = scheduler.schedule(new PollTask(failoverconnection[0], 1), 500, TimeUnit.MILLISECONDS);
 
4559
                ScheduledFuture<?> f2 = scheduler.schedule(new PollTask(failoverconnection[1], 2), 500, TimeUnit.MILLISECONDS);
 
4560
                ScheduledFuture<?> f3 = scheduler.schedule(new PollTask(failoverconnection[2], 3), 500, TimeUnit.MILLISECONDS);
 
4561
                ScheduledFuture<?> f4 = scheduler.schedule(new PollTask(loadbalancedconnection[0], 4), 500, TimeUnit.MILLISECONDS);
 
4562
                ScheduledFuture<?> f5 = scheduler.schedule(new PollTask(loadbalancedconnection[1], 5), 500, TimeUnit.MILLISECONDS);
 
4563
                ScheduledFuture<?> f6 = scheduler.schedule(new PollTask(loadbalancedconnection[2], 6), 500, TimeUnit.MILLISECONDS);
 
4564
 
 
4565
                ScheduledFuture<?> f7 = scheduler.schedule(new CancelTask(failoverconnection[0], 7), 600, TimeUnit.MILLISECONDS);
 
4566
                ScheduledFuture<?> f8 = scheduler.schedule(new CancelTask(failoverconnection[1], 8), 600, TimeUnit.MILLISECONDS);
 
4567
                ScheduledFuture<?> f9 = scheduler.schedule(new CancelTask(failoverconnection[2], 9), 600, TimeUnit.MILLISECONDS);
 
4568
                ScheduledFuture<?> f10 = scheduler.schedule(new CancelTask(loadbalancedconnection[0], 10), 600, TimeUnit.MILLISECONDS);
 
4569
                ScheduledFuture<?> f11 = scheduler.schedule(new CancelTask(loadbalancedconnection[1], 11), 600, TimeUnit.MILLISECONDS);
 
4570
                ScheduledFuture<?> f12 = scheduler.schedule(new CancelTask(loadbalancedconnection[2], 12), 600, TimeUnit.MILLISECONDS);
 
4571
 
 
4572
                try {
 
4573
                        while (f1.get(5, TimeUnit.SECONDS) != null || f2.get(5, TimeUnit.SECONDS) != null || 
 
4574
                                        f3.get(5, TimeUnit.SECONDS) != null || f4.get(5, TimeUnit.SECONDS) != null || 
 
4575
                                        f5.get(5, TimeUnit.SECONDS) != null || f6.get(5, TimeUnit.SECONDS) != null ||
 
4576
                                        f7.get(5, TimeUnit.SECONDS) != null || f8.get(5, TimeUnit.SECONDS) != null ||
 
4577
                                        f9.get(5, TimeUnit.SECONDS) != null || f10.get(5, TimeUnit.SECONDS) != null ||
 
4578
                                        f11.get(5, TimeUnit.SECONDS) != null || f12.get(5, TimeUnit.SECONDS) != null
 
4579
                                        ) {
 
4580
                                System.out.println("waiting");
 
4581
                        }
 
4582
                } catch (Exception e) {
 
4583
                        System.out.println(e.getMessage());
 
4584
                }
 
4585
 
 
4586
                if (this.testServerPrepStmtDeadlockCounter < 12) {
 
4587
                        Map<Thread, StackTraceElement[]> tr = Thread.getAllStackTraces();
 
4588
                        for (StackTraceElement[] el : tr.values()) {
 
4589
                                System.out.println();
 
4590
                                for (StackTraceElement stackTraceElement : el) {
 
4591
                                        System.out.println(stackTraceElement);
 
4592
                                }
 
4593
                        }
 
4594
                }
 
4595
 
 
4596
                for (int i = 0; i < failoverconnection.length; i++) {
 
4597
                        try {
 
4598
                                rs = failoverconnection[i].createStatement().executeQuery("SELECT 1");
 
4599
                        } catch (Exception e1) {
 
4600
                                try {
 
4601
                                        rs = failoverconnection[i].createStatement().executeQuery("SELECT 1");
 
4602
                                        fail("Connection should be explicitly closed.");
 
4603
                                } catch (Exception e2) {
 
4604
                                        assertTrue(true);
 
4605
                                }
 
4606
                        }
 
4607
                }
 
4608
                
 
4609
                scheduler.shutdown();
 
4610
 
 
4611
        }
 
4612
        /**
 
4613
         * Tests fix for BUG#68763, ReplicationConnection.isMasterConnection() returns false always
 
4614
         *  
 
4615
         * @throws Exception
 
4616
         *             if the test fails.
 
4617
         */
 
4618
        public void testBug68763() throws Exception {
 
4619
                
 
4620
                        ReplicationConnection replConn = null;
 
4621
 
 
4622
                        replConn = (ReplicationConnection) getMasterSlaveReplicationConnection();
 
4623
                        replConn.setReadOnly(true);
 
4624
                        assertFalse("isMasterConnection() should be false for slave connection", replConn.isMasterConnection());
 
4625
                        replConn.setReadOnly(false);
 
4626
                        assertTrue("isMasterConnection() should be true for master connection", replConn.isMasterConnection());
 
4627
 
 
4628
        }
 
4629
        
 
4630
 
 
4631
        /**
 
4632
         * Tests fix for BUG#68733, ReplicationConnection does not ping all underlying
 
4633
         * active physical connections to slaves.
 
4634
         * 
 
4635
         * @throws Exception
 
4636
         *             if the test fails.
 
4637
         */
 
4638
        public void testBug68733() throws Exception {
 
4639
                Properties props = new Properties();
 
4640
                props.setProperty("loadBalanceStrategy",
 
4641
                                ForcedLoadBalanceStrategy.class.getName());
 
4642
                props.setProperty("loadBalancePingTimeout", "100");
 
4643
                props.setProperty("autoReconnect", "true");
 
4644
                
 
4645
 
 
4646
                String portNumber = new NonRegisteringDriver().parseURL(dbUrl, null)
 
4647
                                .getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY);
 
4648
 
 
4649
                if (portNumber == null) {
 
4650
                        portNumber = "3306";
 
4651
                }
 
4652
 
 
4653
                ForcedLoadBalanceStrategy.forceFutureServer("slave1:" + portNumber, -1);
 
4654
                // throw Exception if slave2 gets ping
 
4655
                UnreliableSocketFactory.downHost("slave2");
 
4656
                
 
4657
                Connection conn2 = this.getUnreliableReplicationConnection(
 
4658
                                new String[] { "master", "slave1", "slave2" }, props);
 
4659
                ((ReplicationConnection) conn2).isMasterConnection();
 
4660
                assertTrue("Is not actually on master!", ((ReplicationConnection) conn2).isMasterConnection());
 
4661
 
 
4662
                
 
4663
                conn2.setAutoCommit(false);
 
4664
 
 
4665
                conn2.commit();
 
4666
                // go to slaves:
 
4667
                conn2.setReadOnly(true);
 
4668
                
 
4669
                // should succeed, as slave2 has not yet been activated:
 
4670
                conn2.createStatement().execute("/* ping */ SELECT 1");
 
4671
                // allow connections to slave2:
 
4672
                UnreliableSocketFactory.dontDownHost("slave2");
 
4673
                // force next re-balance to slave2:
 
4674
                ForcedLoadBalanceStrategy.forceFutureServer("slave2:" + portNumber, -1);
 
4675
                // re-balance:
 
4676
                conn2.commit();
 
4677
                // down slave1 (active but not selected slave connection):
 
4678
                UnreliableSocketFactory.downHost("slave1");
 
4679
                // should succeed, as slave2 is currently selected:
 
4680
                conn2.createStatement().execute("/* ping */ SELECT 1");
 
4681
                
 
4682
                
 
4683
        
 
4684
                // make all hosts available
 
4685
                UnreliableSocketFactory.flushAllHostLists();
 
4686
                
 
4687
                // peg connection to slave2:
 
4688
                ForcedLoadBalanceStrategy.forceFutureServer("slave2:" + portNumber, -1);
 
4689
                conn2.commit();
 
4690
 
 
4691
                rs = conn2.createStatement().executeQuery("SELECT CONNECTION_ID()");
 
4692
                rs.next();
 
4693
                int slave2id = rs.getInt(1);
 
4694
 
 
4695
                // peg connection to slave1 now:
 
4696
                ForcedLoadBalanceStrategy.forceFutureServer("slave1:" + portNumber, -1);
 
4697
                conn2.commit();
 
4698
                
 
4699
                
 
4700
                // this is a really hacky way to confirm ping was processed
 
4701
                // by an inactive load-balanced connection, but we lack COM_PING
 
4702
                // counters on the server side, and need to create infrastructure
 
4703
                // to capture what's being sent by the driver separately.
 
4704
                
 
4705
                Thread.sleep(2000);
 
4706
                conn2.createStatement().execute("/* ping */ SELECT 1");
 
4707
                rs = conn2.createStatement().executeQuery("SELECT time FROM information_schema.processlist WHERE id = " + slave2id);
 
4708
                rs.next();
 
4709
                assertTrue("Processlist should be less than 2 seconds due to ping", rs.getInt(1) < 2);
 
4710
                
 
4711
                // peg connection to slave2:
 
4712
                ForcedLoadBalanceStrategy.forceFutureServer("slave2:" + portNumber, -1);
 
4713
                conn2.commit();
 
4714
                // leaving connection tied to slave2, bring slave2 down and slave1 up:
 
4715
                UnreliableSocketFactory.downHost("slave2");
 
4716
                
 
4717
                try {
 
4718
                        conn2.createStatement().execute("/* ping */ SELECT 1");
 
4719
                        fail("Expected failure because current slave connection is down.");
 
4720
                } catch (SQLException e) { }
 
4721
                
 
4722
                conn2.close();
 
4723
                
 
4724
                ForcedLoadBalanceStrategy.forceFutureServer("slave1:" + portNumber, -1);
 
4725
                UnreliableSocketFactory.flushAllHostLists();
 
4726
                conn2 = this.getUnreliableReplicationConnection(
 
4727
                                new String[] { "master", "slave1", "slave2" }, props);
 
4728
                conn2.setAutoCommit(false);
 
4729
                // go to slaves:
 
4730
                conn2.setReadOnly(true);
 
4731
 
 
4732
                // on slave1 now:
 
4733
                conn2.commit();
 
4734
                
 
4735
                ForcedLoadBalanceStrategy.forceFutureServer("slave2:" + portNumber, -1);
 
4736
                // on slave2 now:
 
4737
                conn2.commit();
 
4738
                
 
4739
                // disable master:
 
4740
                UnreliableSocketFactory.downHost("master");
 
4741
                
 
4742
                // ping should succeed, because we're still attached to slaves:
 
4743
                conn2.createStatement().execute("/* ping */ SELECT 1");
 
4744
                
 
4745
                // bring master back up:
 
4746
                UnreliableSocketFactory.dontDownHost("master");
 
4747
 
 
4748
                // get back to master, confirm it's recovered:
 
4749
                conn2.commit();
 
4750
                conn2.createStatement().execute("/* ping */ SELECT 1");
 
4751
                try{
 
4752
                        conn2.setReadOnly(false);
 
4753
                } catch (SQLException e) {}
 
4754
                
 
4755
                conn2.commit();
 
4756
                
 
4757
                // take down both slaves:
 
4758
                UnreliableSocketFactory.downHost("slave1");
 
4759
                UnreliableSocketFactory.downHost("slave2");
 
4760
                
 
4761
                
 
4762
                // should succeed, as we're still on master:
 
4763
                conn2.createStatement().execute("/* ping */ SELECT 1");         
 
4764
                
 
4765
                UnreliableSocketFactory.dontDownHost("slave1");
 
4766
                UnreliableSocketFactory.dontDownHost("slave2");
 
4767
                UnreliableSocketFactory.downHost("master");
 
4768
                
 
4769
                try {
 
4770
                        conn2.createStatement().execute("/* ping */ SELECT 1"); 
 
4771
                        fail("should have failed because master is offline");
 
4772
                } catch (SQLException e) {
 
4773
                        
 
4774
                }
 
4775
                
 
4776
                UnreliableSocketFactory.dontDownHost("master");
 
4777
                conn2.createStatement().execute("/* ping */ SELECT 1"); 
 
4778
                // continue on slave2:
 
4779
                conn2.setReadOnly(true);
 
4780
                
 
4781
                // should succeed, as slave2 is up:
 
4782
                conn2.createStatement().execute("/* ping */ SELECT 1"); 
 
4783
                
 
4784
                UnreliableSocketFactory.downHost("slave2");
 
4785
                
 
4786
                try {
 
4787
                        conn2.createStatement().execute("/* ping */ SELECT 1"); 
 
4788
                        fail("should have failed because slave2 is offline and the active chosen connection.");
 
4789
                } catch (SQLException e) {}
 
4790
                        
 
4791
                
 
4792
                conn2.close();
 
4793
        }
 
4794
        
 
4795
        protected int testServerPrepStmtDeadlockCounter = 0;
 
4796
 
 
4797
        class PollTask implements Runnable {
 
4798
 
 
4799
                private Connection c;
 
4800
                private int num = 0;
 
4801
                
 
4802
                private Statement st1 = null;
 
4803
                private PreparedStatement pst1 = null;
 
4804
 
 
4805
                PollTask(Connection cn, int n) throws SQLException {
 
4806
                        this.c = cn;
 
4807
                        this.num = n;
 
4808
                        
 
4809
                        this.st1 = c.createStatement();
 
4810
                        this.pst1 = c.prepareStatement("SELECT 1 FROM DUAL");
 
4811
                }
 
4812
 
 
4813
                public void run() {
 
4814
                        System.out.println(this.num + ". Start polling at "+new Date().getTime());
 
4815
                        boolean connectionClosed = false;
 
4816
 
 
4817
                        for (int i = 0; i < 20000; i++) {
 
4818
                                try {
 
4819
                                        this.st1.executeQuery("SELECT 1 FROM DUAL").close();
 
4820
                                        this.pst1.executeQuery().close();
 
4821
                                } catch (Exception ex1) {
 
4822
                                        if (!connectionClosed) {
 
4823
                                                System.out.println(this.num + "." + i + " "+ex1.getMessage());
 
4824
                                                connectionClosed = true;
 
4825
                                        } else {
 
4826
                                                break;
 
4827
                                        }
 
4828
                                }
 
4829
                        }
 
4830
 
 
4831
                        ConnectionRegressionTest.this.testServerPrepStmtDeadlockCounter++;
 
4832
                        System.out.println(this.num + ". Done!");
 
4833
                }
 
4834
                
 
4835
        }
 
4836
 
 
4837
        class CancelTask implements Runnable {
 
4838
 
 
4839
                private Connection c;
 
4840
                private int num = 0;
 
4841
                
 
4842
                CancelTask(Connection cn, int n) throws SQLException {
 
4843
                        this.c = cn;
 
4844
                        this.num = n;
 
4845
                }
 
4846
 
 
4847
                public void run() {
 
4848
                        System.out.println(this.num + ". Start cancelling at "+new Date().getTime());
 
4849
 
 
4850
                        if (Proxy.isProxyClass(c.getClass())) {
 
4851
                                try {
 
4852
                                        if (this.num == 7 || this.num == 10) {
 
4853
                                                Proxy.getInvocationHandler(c).invoke(c, Connection.class.getMethod("close", new Class[]{}), null);
 
4854
                                        } else if (this.num == 8 || this.num == 11) {
 
4855
                                                Proxy.getInvocationHandler(c).invoke(c, MySQLConnection.class.getMethod("abortInternal", new Class[]{}), null);
 
4856
                                        } else if (this.num == 9 || this.num == 12) {
 
4857
                                                Proxy.getInvocationHandler(c).invoke(c, com.mysql.jdbc.Connection.class.getMethod("abort", new Class[]{Executor.class}), new Object[]{ new ThreadPerTaskExecutor()});
 
4858
                                        }
 
4859
                                        
 
4860
                                        ConnectionRegressionTest.this.testServerPrepStmtDeadlockCounter++;
 
4861
                                        System.out.println(this.num + ". Done!");
 
4862
                                } catch (Throwable e) {
 
4863
                                        e.printStackTrace();
 
4864
                                }
 
4865
                        }
 
4866
                }
 
4867
                
 
4868
        }
 
4869
        
 
4870
        class ThreadPerTaskExecutor implements Executor {
 
4871
                public void execute(Runnable r) {
 
4872
                        new Thread(r).start();
 
4873
                }
 
4874
        }
 
4875
 
3134
4876
}
 
 
b'\\ No newline at end of file'