Search in sources :

Example 1 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testPooledSessions.

@SuppressWarnings("unchecked")
@Test
public void testPooledSessions() throws Exception {
    final ClientFactory cf = new ClientFactory();
    final String url = this.baseUrl;
    final Properties props = new Properties();
    /*
         * UT8/1: Verify that setting an incorrect value in the client options defined in the Pooling options in the HLS throw an exception with the expected
         * message.
         */
    // pooling.enabled
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.enabled' does not support value 'sure'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty(ClientProperty.POOLING_ENABLED.getKeyName(), "sure");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.enabled' does not support value 'sure'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"enabled\": \"sure\"}}");
            return null;
        }
    });
    // pooling.maxSize
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxSize' does not support value '0'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "0");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxSize' does not support value '0'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"maxSize\": 0}}");
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxSize' does not support value 'one'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"maxSize\": \"one\"}}");
            return null;
        }
    });
    // pooling.maxIdleTime
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxIdleTime' does not support value '-1'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "-1");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxIdleTime' does not support value '-1'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"maxIdleTime\": -1}}");
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.maxIdleTime' does not support value 'one'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"maxIdleTime\": \"one\"}}");
            return null;
        }
    });
    // pooling.queueTimeout
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.queueTimeout' does not support value '-1'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "-1");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.queueTimeout' does not support value '-1'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"queueTimeout\": -1}}");
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.queueTimeout' does not support value 'one'\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"queueTimeout\": \"one\"}}");
            return null;
        }
    });
    // Unknown pooling option.
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.foo' is not recognized as valid\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty("pooling.foo", "bar");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'pooling\\.foo' is not recognized as valid\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"pooling\": {\"foo\": \"bar\"}}");
            return null;
        }
    });
    // Unknown clientProps option.
    props.clear();
    assertThrows(XDevAPIError.class, "Client option 'foo' is not recognized as valid\\.", new Callable<Void>() {

        public Void call() throws Exception {
            props.setProperty("foo", "bar");
            cf.getClient(url, props);
            return null;
        }
    });
    assertThrows(XDevAPIError.class, "Client option 'foo' is not recognized as valid\\.", new Callable<Void>() {

        public Void call() throws Exception {
            cf.getClient(url, "{\"foo\": {\"bar\": \"baz\"}}");
            return null;
        }
    });
    /*
         * UT9/1: Verify that when no pooling properties passed their values set to defaults: pooling.maxSize=25, pooling.maxIdleTime=0, pooling.queueTimeout=0.
         */
    props.clear();
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, props), 25, 0, 0);
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, (Properties) null), 25, 0, 0);
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, "{}"), 25, 0, 0);
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, (String) null), 25, 0, 0);
    /*
         * UT9/2: Verify that when all pooling properties passed via Properties object the Client is configured according to their values.
         */
    props.setProperty(ClientProperty.POOLING_ENABLED.getKeyName(), "true");
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "5");
    props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "6");
    props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "7");
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, props), 5, 6, 7);
    /*
         * UT9/3: Verify that when all pooling properties passed via json string ({"pooling" : {"enabled" : true, "maxSize" : 8, "maxIdleTime" : 9,
         * "queueTimeout" : 10} }) the Client is configured according to their values.
         */
    testPooledSessions_checkClientProperties(cf.getClient(this.baseUrl, "{\"pooling\" : {\"enabled\" : true, \"maxSize\" : 8, \"maxIdleTime\" : 9, \"queueTimeout\" : 10} }"), 8, 9, 10);
    /*
         * UT3/2: Start a client with pooling enabled, call Client.getSession() twice and verify that the objects returned are different and the internal
         * connection instances are different too.
         */
    Client cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true}}");
    Session s0 = cli0.getSession();
    Session s1 = cli0.getSession();
    assertNotEquals(s0, s1);
    Field fProtocol = CoreSession.class.getDeclaredField("protocol");
    fProtocol.setAccessible(true);
    assertNotEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT3/3: Start a client with pooling enabled, call Client.getSession() twice, closing the first session before getting the second one, and verify that
         * the objects returned are different and that the internal connection instances are the same.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true}}");
    s0 = cli0.getSession();
    s0.close();
    s1 = cli0.getSession();
    s1.sql("SELECT 1").execute();
    assertNotEquals(s0, s1);
    assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT3/4: Start a client with pooling disabled, call Client.getSession() twice and verify that the objects returned are different and the internal
         * connection instances are different too.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": false}}");
    s0 = cli0.getSession();
    s1 = cli0.getSession();
    assertNotEquals(s0, s1);
    assertNotEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT3/5: Start a client with pooling disabled, call Client.getSession() twice, closing the first session before getting the second one, and verify that
         * the objects returned are different and that the internal connection instances are different too.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": false}}");
    s0 = cli0.getSession();
    s0.close();
    s1 = cli0.getSession();
    assertNotEquals(s0, s1);
    assertNotEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT5/1: Having a full pool and queueTimeout = 0, verify that a new Client.getSession() waits until a Session is released.
         * UT6/1: Verify that that a client object can not open/create more sessions that the specified in the maxSize option.
         */
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "3");
    props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "1000");
    props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "1000");
    Client cli1 = cf.getClient(this.baseUrl, props);
    s1 = cli1.getSession();
    Session s2 = cli1.getSession();
    Session s3 = cli1.getSession();
    testPooledSessions_assertFailureTimeout(cli1, 1000, 2000, XDevAPIError.class, "Session can not be obtained within 1000 milliseconds.");
    cli1.close();
    /*
         * UT12/1: Having a pool with a single connection, close the Session, get another Session with Client.getSession(). Verify that the received Session
         * object is new and uses the same internal connection (MysqlxSession) instance.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 1}}");
    s0 = cli0.getSession();
    s0.close();
    s1 = cli0.getSession();
    s1.sql("SELECT 1").execute();
    assertNotEquals(s0, s1);
    assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT12/2: Having a pool with a number of connections greater than 1 and lower than maxPoolSize, close on Session, get another Session with
         * Client.getSession(). Verify that the received Session object is new and uses the same internal connection (MysqlxSession) instance.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 3}}");
    s0 = cli0.getSession();
    s0.close();
    s1 = cli0.getSession();
    s1.sql("SELECT 1").execute();
    assertNotEquals(s0, s1);
    assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    cli0.close();
    /*
         * UT12/3: Having a full pool with all sessions in active state, close one Session, get another Session with Client.getSession(). Verify that the
         * received Session object is new and uses the same internal connection (MysqlxSession) instance.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 3}}");
    s0 = cli0.getSession();
    s1 = cli0.getSession();
    s2 = cli0.getSession();
    s0.close();
    s3 = cli0.getSession();
    s3.sql("SELECT 1").execute();
    assertNotEquals(s0, s3);
    assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s3).getSession()));
    cli0.close();
    /*
         * UT11/2: Having a pool with a single idle connection and maxIdleTime = n, verify that after n milliseconds a Client.getSession() call will remove all
         * expired sessions from pool and return a new Session object that uses a new MysqlxSession instance.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 3, \"maxIdleTime\" : 1000}}");
    s0 = cli0.getSession();
    s0.close();
    Thread.sleep(2000);
    s1 = cli0.getSession();
    assertNotEquals(s0, s1);
    assertNotEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s1).getSession()));
    Field fIdleSessions = ClientImpl.class.getDeclaredField("idleProtocols");
    fIdleSessions.setAccessible(true);
    assertTrue(((BlockingQueue<PooledXProtocol>) fIdleSessions.get(cli0)).isEmpty());
    /*
         * UT4/1: Verify that all idle and active sessions are closed after Client.close() call.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 3}}");
    s0 = cli0.getSession();
    s1 = cli0.getSession();
    s0.close();
    Field fActiveSessions = ClientImpl.class.getDeclaredField("activeProtocols");
    fActiveSessions.setAccessible(true);
    assertEquals(1, ((BlockingQueue<PooledXProtocol>) fIdleSessions.get(cli0)).size());
    assertEquals(1, ((Set<WeakReference<PooledXProtocol>>) fActiveSessions.get(cli0)).size());
    cli0.close();
    assertEquals(0, ((BlockingQueue<PooledXProtocol>) fIdleSessions.get(cli0)).size());
    assertEquals(0, ((Set<WeakReference<PooledXProtocol>>) fActiveSessions.get(cli0)).size());
    final Session ses = s1;
    assertThrows(CJCommunicationsException.class, new Callable<Void>() {

        public Void call() throws Exception {
            ses.getSchemas();
            return null;
        }
    });
    /*
         * UT4/2: Verify that after Client was closed the Client.getSession() throws an XDevAPIError with the message "Client is closed."
         */
    Client cli2 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true}}");
    cli2.close();
    assertThrows(XDevAPIError.class, "Client is closed.", new Callable<Void>() {

        public Void call() throws Exception {
            cli2.getSession();
            return null;
        }
    });
    /*
         * UT11/1: Having a pool with a single active and maxIdleTime = 0, verify that if closing the session then after any long inactivity time a new Session
         * object returned by Client.getSession() uses the same internal MysqlxSession object.
         */
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "2");
    props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "0");
    props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "20000");
    Client cli3 = cf.getClient(this.baseUrl, props);
    s0 = cli3.getSession();
    s1 = cli3.getSession();
    assertEquals(2, ((Set<WeakReference<PooledXProtocol>>) fActiveSessions.get(cli3)).size());
    s0.close();
    Thread.sleep(10000);
    s2 = cli3.getSession();
    s2.sql("SELECT 1").execute();
    assertNotEquals(s0, s2);
    assertEquals(fProtocol.get(((SessionImpl) s0).getSession()), fProtocol.get(((SessionImpl) s2).getSession()));
    cli3.close();
    /*
         * UT5/1: Having a full pool and queueTimeout = 0, verify that a new Client.getSession() waits until a Session is released.
         */
    props.setProperty(ClientProperty.POOLING_MAX_SIZE.getKeyName(), "2");
    props.setProperty(ClientProperty.POOLING_MAX_IDLE_TIME.getKeyName(), "1000");
    props.setProperty(ClientProperty.POOLING_QUEUE_TIMEOUT.getKeyName(), "0");
    cli3 = cf.getClient(this.baseUrl, props);
    s1 = cli3.getSession();
    Session s6 = cli3.getSession();
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                Thread.sleep(10000);
                s6.close();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    });
    long begin = System.currentTimeMillis();
    t.start();
    s1 = cli3.getSession();
    long end = System.currentTimeMillis() - begin;
    s1.sql("SELECT 1").execute();
    assertTrue(end >= 10000, "Expected wait time 10000 ms but was " + end);
    assertEquals(fProtocol.get(((SessionImpl) s1).getSession()), fProtocol.get(((SessionImpl) s6).getSession()));
    /*
         * TS10_2 Verify that RuntimProperty objects are reset to initial values when Session returned to pool.
         */
    assertEquals(2, ((Set<WeakReference<PooledXProtocol>>) fActiveSessions.get(cli3)).size());
    ((SessionImpl) s1).getSession().getPropertySet().getStringProperty(PropertyKey.connectionAttributes).setValue("orig:s1");
    s1.close();
    assertEquals(1, ((Set<WeakReference<PooledXProtocol>>) fActiveSessions.get(cli3)).size());
    s2 = cli3.getSession();
    s2.sql("SELECT 1").execute();
    assertEquals(fProtocol.get(((SessionImpl) s1).getSession()), fProtocol.get(((SessionImpl) s2).getSession()));
    assertNotEquals("orig:s1", ((SessionImpl) s1).getSession().getPropertySet().getStringProperty(PropertyKey.connectionAttributes).getValue());
    assertEquals(((SessionImpl) s1).getSession().getPropertySet().getStringProperty(PropertyKey.connectionAttributes).getInitialValue(), ((SessionImpl) s1).getSession().getPropertySet().getStringProperty(PropertyKey.connectionAttributes).getValue());
    /*
         * UT10/1: Get the max sessions allowed in the pool, create the same variables and temp tables in all the sessions,
         * save ((SessionImpl) sN).getSession().getServerSession().getThreadId() values.
         * Then close all the sessions and get a new one: the variables and the temp tables must not exist,
         * ((SessionImpl) sN).getSession().getServerSession().getThreadId() must return values equal to saved ones.
         */
    cli0 = cf.getClient(this.baseUrl, "{\"pooling\": {\"enabled\": true, \"maxSize\" : 2}}");
    s0 = cli0.getSession();
    s1 = cli0.getSession();
    long id0 = ((SessionImpl) s0).getSession().getServerSession().getCapabilities().getThreadId();
    long id1 = ((SessionImpl) s1).getSession().getServerSession().getCapabilities().getThreadId();
    s0.sql("SET @a='s0'").execute();
    s0.sql("CREATE TEMPORARY TABLE testpooledsessionstmps0(x int)").execute();
    s1.sql("SET @a='s1'").execute();
    s1.sql("CREATE TEMPORARY TABLE testpooledsessionstmps1(x int)").execute();
    SqlResult res = s0.sql("SELECT @a as a").execute();
    assertTrue(res.hasNext());
    assertEquals("s0", res.next().getString(0));
    res = s0.sql("SHOW CREATE TABLE testpooledsessionstmps0").execute();
    assertTrue(res.hasNext());
    assertEquals("testpooledsessionstmps0", res.next().getString(0));
    res = s1.sql("SELECT @a as a").execute();
    assertTrue(res.hasNext());
    assertEquals("s1", res.next().getString(0));
    res = s1.sql("SHOW CREATE TABLE testpooledsessionstmps1").execute();
    assertTrue(res.hasNext());
    assertEquals("testpooledsessionstmps1", res.next().getString(0));
    s0.close();
    s1.close();
    Session s0_new = cli0.getSession();
    Session s1_new = cli0.getSession();
    assertEquals(id0, ((SessionImpl) s0_new).getSession().getServerSession().getCapabilities().getThreadId());
    assertEquals(id1, ((SessionImpl) s1_new).getSession().getServerSession().getCapabilities().getThreadId());
    res = s0_new.sql("SELECT @a as a").execute();
    assertTrue(res.hasNext());
    assertNull(res.next().getString(0));
    assertThrows(XProtocolError.class, ".*testpooledsessionstmps0' doesn't exist", new Callable<Void>() {

        public Void call() throws Exception {
            s0_new.sql("SHOW CREATE TABLE testpooledsessionstmps0").execute();
            return null;
        }
    });
    res = s1_new.sql("SELECT @a as a").execute();
    assertTrue(res.hasNext());
    assertNull(res.next().getString(0));
    assertThrows(XProtocolError.class, ".*testpooledsessionstmps1' doesn't exist", new Callable<Void>() {

        public Void call() throws Exception {
            s1_new.sql("SHOW CREATE TABLE testpooledsessionstmps1").execute();
            return null;
        }
    });
    cli0.close();
}
Also used : SqlResult(com.mysql.cj.xdevapi.SqlResult) PooledXProtocol(com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) JsonString(com.mysql.cj.xdevapi.JsonString) Properties(java.util.Properties) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) FileNotFoundException(java.io.FileNotFoundException) FeatureNotAvailableException(com.mysql.cj.exceptions.FeatureNotAvailableException) ExecutionException(java.util.concurrent.ExecutionException) CJPacketTooBigException(com.mysql.cj.exceptions.CJPacketTooBigException) Field(java.lang.reflect.Field) WeakReference(java.lang.ref.WeakReference) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) Client(com.mysql.cj.xdevapi.Client) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Example 2 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method testSessionAttributes.

@Test
public void testSessionAttributes() throws Exception {
    assumeTrue(mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.16")), "MySQL 8.0.16+ is required to run this test.");
    ClientFactory cf = new ClientFactory();
    Map<String, String> userAttributes = new HashMap<>();
    // TSFR1/TSFR2/TSFR3 Create a Session with xdevapi.connection-attributes in the connection string, verify that
    // the session is successfully established. Create a Session using a connection string containing the properties
    // as listed below, verify that the session is successfully established and the server contains the defined session attributes.
    // xdevapi.connection-attributes=[key1=value1]
    // xdevapi.connection-attributes=[key1=value1,key2=value2]
    // xdevapi.connection-attributes=key1=value1
    // xdevapi.connection-attributes=key1=value1,key2=value2
    userAttributes.clear();
    userAttributes.put("key1", "value1");
    String baseUrlLocal = this.baseUrl + (this.baseUrl.contains("?") ? "&" : "?");
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1]", true), userAttributes);
    userAttributes.put("key2", "value2");
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,key2=value2", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1,key2=value2]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,key2=value2", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1,key2=value2]", true), userAttributes);
    // TSFR4/TSFR5/TSFR6 Create a Session without xdevapi.connection-attributes in the connection string, verify that all predefined attributes
    // exist and contain the correct values. Verify that only connection attributes starting with "_" were set for current session.
    userAttributes.clear();
    testSessionAttributes_checkSession(this.baseUrl, userAttributes);
    testSessionAttributes_checkClient(this.baseUrl, userAttributes);
    // TSFR7 Create a Session using a connection string containing the properties as listed below, verify that a WrongArgumentException exception is thrown
    // with the message Key names in "xdevapi.connection-attributes" cannot start with "_".
    // xdevapi.connection-attributes=[_key1=value1]
    // xdevapi.connection-attributes=[key1=value1,_key2=value2]
    // xdevapi.connection-attributes=_key1=value1
    // xdevapi.connection-attributes=key1=value1,_key2=value2
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[_key1=value1]", true));
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        Client cli1 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[_key1=value1]", true), new Properties());
        cli1.getSession();
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1,_key2=value2]", true));
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        Client cli1 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=value1,_key2=value2]", true), new Properties());
        cli1.getSession();
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "_key1=value1", true));
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        Client cli1 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "_key1=value1", true), new Properties());
        cli1.getSession();
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,_key2=value2", true));
        return null;
    });
    assertThrows(WrongArgumentException.class, "Key names in \"xdevapi.connection-attributes\" cannot start with \"_\".", () -> {
        Client cli1 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,_key2=value2", true), new Properties());
        cli1.getSession();
        return null;
    });
    // TSFR9 Create a Session using a connection string containing the properties as listed below, verify
    // that the user-defined connection attribute key1 has an empty value.
    // xdevapi.connection-attributes=[key1]
    // xdevapi.connection-attributes=[key1,key2=value2]
    // xdevapi.connection-attributes=[key1=]
    // xdevapi.connection-attributes=[key1=,key2=value2]
    // xdevapi.connection-attributes=key1
    // xdevapi.connection-attributes=key1,key2=value2
    // xdevapi.connection-attributes=key1=
    // xdevapi.connection-attributes=key1=,key2=value2
    userAttributes.clear();
    userAttributes.put("key1", "");
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1]", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=]", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=", true), userAttributes);
    userAttributes.put("key2", "value2");
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1,key2=value2]", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=,key2=value2]", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1,key2=value2", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=,key2=value2", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1,key2=value2]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[key1=,key2=value2]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1,key2=value2", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=,key2=value2", true), userAttributes);
    // TSFR10 Create a Session with xdevapi.connection-attributes=false in the connection string, verify
    // that no connection attribute was set for current session.
    Session s10 = this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "false", true));
    SqlResult res = s10.sql("SELECT * FROM performance_schema.session_connect_attrs WHERE processlist_id = CONNECTION_ID()").execute();
    assertFalse(res.hasNext(), "Expected no connection attributes.");
    s10.close();
    Client c10 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "false", true), new Properties());
    s10 = c10.getSession();
    res = s10.sql("SELECT * FROM performance_schema.session_connect_attrs WHERE processlist_id = CONNECTION_ID()").execute();
    assertFalse(res.hasNext(), "Expected no connection attributes.");
    s10.close();
    c10.close();
    // TSFR11 Create a Session using a connection string containing the properties as listed below, verify
    // that only the client-defined connection attributes were set for the current session.
    // xdevapi.connection-attributes
    // xdevapi.connection-attributes=
    // xdevapi.connection-attributes=true
    // xdevapi.connection-attributes=[]
    userAttributes.clear();
    testSessionAttributes_checkSession(baseUrlLocal + PropertyKey.xdevapiConnectionAttributes.getKeyName(), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + PropertyKey.xdevapiConnectionAttributes.getKeyName() + "=", userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "true", true), userAttributes);
    testSessionAttributes_checkSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[]", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + PropertyKey.xdevapiConnectionAttributes.getKeyName(), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + PropertyKey.xdevapiConnectionAttributes.getKeyName() + "=", userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "true", true), userAttributes);
    testSessionAttributes_checkClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "[]", true), userAttributes);
    // TSFR13 Create a Session with xdevapi.connection-attributes=[key1=value1,key1=value2] in the connection string, verify that
    // a WrongArgumentException exception is thrown with the message Duplicate key "key1" used in "xdevapi.connection-attributes".
    assertThrows(WrongArgumentException.class, "Duplicate key \"key1\" used in \"xdevapi.connection-attributes\".", () -> {
        this.fact.getSession(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,key1=value2", true));
        return null;
    });
    assertThrows(WrongArgumentException.class, "Duplicate key \"key1\" used in \"xdevapi.connection-attributes\".", () -> {
        Client cli1 = cf.getClient(baseUrlLocal + makeParam(PropertyKey.xdevapiConnectionAttributes, "key1=value1,key1=value2", true), new Properties());
        cli1.getSession();
        return null;
    });
}
Also used : SqlResult(com.mysql.cj.xdevapi.SqlResult) HashMap(java.util.HashMap) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) JsonString(com.mysql.cj.xdevapi.JsonString) Client(com.mysql.cj.xdevapi.Client) Properties(java.util.Properties) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Example 3 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method pooledSessionFailoverByPrioritiesAndNoPooling.

@Test
public void pooledSessionFailoverByPrioritiesAndNoPooling() {
    UnreliableSocketFactory.flushAllStaticData();
    final String testUriPattern = "mysqlx://%s:%s@[%s]/%s?" + PropertyKey.xdevapiConnectTimeout.getKeyName() + "=100&" + PropertyKey.socketFactory.getKeyName() + "=" + UnreliableSocketFactory.class.getName();
    String testHosts = IntStream.range(1, 6).mapToObj(i -> "host" + i).peek(h -> UnreliableSocketFactory.mapHost(h, getTestHost())).map(h -> "(address=" + h + ":" + getTestPort() + ",priority=%d)").collect(Collectors.joining(","));
    String testUriPatternPriorities = String.format(testUriPattern, getTestUser() == null ? "" : getTestUser(), getTestPassword() == null ? "" : getTestPassword(), testHosts, getTestDatabase());
    String testUri = String.format(testUriPatternPriorities, 60, 80, 100, 20, 40);
    int[] hostsOrder = new int[] { 3, 2, 1, 5, 4 };
    final ClientFactory cf = new ClientFactory();
    Client client = cf.getClient(testUri, "{\"pooling\" : {\"enabled\" : true, \"maxSize\" : 10} }");
    for (int i = 0; i < hostsOrder.length; i++) {
        int h = hostsOrder[i];
        // Don't pool this connection.
        client.getSession();
        assertTrue(UnreliableSocketFactory.isConnected());
        String lastHost = UnreliableSocketFactory.getHostFromLastConnection();
        assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + h), lastHost);
        List<String> connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
        assertEquals(i == 0 ? 1 : 2, connectionAttempts.size());
        for (int a = 0; a < connectionAttempts.size() - 1; a++) {
            assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[i - 1 + a]), connectionAttempts.get(a));
        }
        UnreliableSocketFactory.downHost("host" + h);
        UnreliableSocketFactory.flushConnectionAttempts();
    }
    // None of the hosts is available by now.
    assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", () -> {
        client.getSession();
        return null;
    });
    // Final connection tried the last known to be good host (host4) and then the remaining hosts by their priority
    List<String> connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    for (int i = 0; i < hostsOrder.length; i++) {
        assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[(i + 4) % 5]), connectionAttempts.get(i));
    }
    UnreliableSocketFactory.dontDownHost("host" + hostsOrder[1]);
    UnreliableSocketFactory.flushConnectionAttempts();
    client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    assertEquals(2, connectionAttempts.size());
    assertEquals(UnreliableSocketFactory.getHostFailedStatus("host" + hostsOrder[0]), connectionAttempts.get(0));
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + hostsOrder[1]), connectionAttempts.get(1));
    UnreliableSocketFactory.flushConnectionAttempts();
    client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    connectionAttempts = UnreliableSocketFactory.getHostsFromAllConnections();
    assertEquals(1, connectionAttempts.size());
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host" + hostsOrder[1]), connectionAttempts.get(0));
    client.close();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) XDevAPIError(com.mysql.cj.xdevapi.XDevAPIError) RowResult(com.mysql.cj.xdevapi.RowResult) JsonNumber(com.mysql.cj.xdevapi.JsonNumber) ServerMessages(com.mysql.cj.x.protobuf.Mysqlx.ServerMessages) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) Random(java.util.Random) Collection(com.mysql.cj.xdevapi.Collection) ByteBuffer(java.nio.ByteBuffer) Constants(com.mysql.cj.Constants) Future(java.util.concurrent.Future) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) SqlStatement(com.mysql.cj.xdevapi.SqlStatement) Map(java.util.Map) ClientImpl(com.mysql.cj.xdevapi.ClientImpl) CoreSession(com.mysql.cj.CoreSession) ServerVersion(com.mysql.cj.ServerVersion) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) Warning(com.mysql.cj.xdevapi.Warning) SocketFactory(com.mysql.cj.protocol.SocketFactory) Set(java.util.Set) BlockingQueue(java.util.concurrent.BlockingQueue) XdevapiSslMode(com.mysql.cj.conf.PropertyDefinitions.XdevapiSslMode) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) Executors(java.util.concurrent.Executors) PropertyDefinitions(com.mysql.cj.conf.PropertyDefinitions) Test(org.junit.jupiter.api.Test) ByteOrder(java.nio.ByteOrder) List(java.util.List) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) FeatureNotAvailableException(com.mysql.cj.exceptions.FeatureNotAvailableException) SqlMultiResult(com.mysql.cj.xdevapi.SqlMultiResult) InjectedSocketFactory(testsuite.InjectedSocketFactory) FindStatement(com.mysql.cj.xdevapi.FindStatement) Assertions.fail(org.junit.jupiter.api.Assertions.fail) IntStream(java.util.stream.IntStream) MysqlErrorNumbers(com.mysql.cj.exceptions.MysqlErrorNumbers) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) CompletableFuture(java.util.concurrent.CompletableFuture) JsonString(com.mysql.cj.xdevapi.JsonString) Schema(com.mysql.cj.xdevapi.Schema) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) Client(com.mysql.cj.xdevapi.Client) ClientProperty(com.mysql.cj.xdevapi.Client.ClientProperty) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) WeakReference(java.lang.ref.WeakReference) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) ExecutorService(java.util.concurrent.ExecutorService) Session(com.mysql.cj.xdevapi.Session) Properties(java.util.Properties) Frame(com.mysql.cj.x.protobuf.MysqlxNotice.Frame) Iterator(java.util.Iterator) DbDoc(com.mysql.cj.xdevapi.DbDoc) DocResult(com.mysql.cj.xdevapi.DocResult) Field(java.lang.reflect.Field) Compression(com.mysql.cj.conf.PropertyDefinitions.Compression) XProtocolError(com.mysql.cj.protocol.x.XProtocolError) SessionFactory(com.mysql.cj.xdevapi.SessionFactory) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Row(com.mysql.cj.xdevapi.Row) SqlResult(com.mysql.cj.xdevapi.SqlResult) MessageLite(com.google.protobuf.MessageLite) AfterEach(org.junit.jupiter.api.AfterEach) SelectStatement(com.mysql.cj.xdevapi.SelectStatement) PooledXProtocol(com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol) PropertyKey(com.mysql.cj.conf.PropertyKey) CJPacketTooBigException(com.mysql.cj.exceptions.CJPacketTooBigException) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) JsonString(com.mysql.cj.xdevapi.JsonString) Client(com.mysql.cj.xdevapi.Client) Test(org.junit.jupiter.api.Test)

Example 4 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SessionTest method pooledSessionFailoverRandomSortAndNoPooling.

@Test
public void pooledSessionFailoverRandomSortAndNoPooling() {
    UnreliableSocketFactory.flushAllStaticData();
    final String testUriPattern = "mysqlx://%s:%s@[%s]/%s?" + PropertyKey.xdevapiConnectTimeout.getKeyName() + "=100&" + PropertyKey.socketFactory.getKeyName() + "=" + UnreliableSocketFactory.class.getName();
    String testHosts = IntStream.range(1, 6).mapToObj(i -> "host" + i).peek(h -> UnreliableSocketFactory.mapHost(h, getTestHost())).map(h -> h + ":" + getTestPort()).collect(Collectors.joining(","));
    String testUri = String.format(testUriPattern, getTestUser() == null ? "" : getTestUser(), getTestPassword() == null ? "" : getTestPassword(), testHosts, getTestDatabase());
    final ClientFactory cf = new ClientFactory();
    Client client = cf.getClient(testUri, "{\"pooling\" : {\"enabled\" : true, \"maxSize\" : 10} }");
    Set<String> downHosts = new HashSet<>();
    for (int i = 1; i <= 5; i++) {
        // Don't pool this connection.
        client.getSession();
        assertTrue(UnreliableSocketFactory.isConnected());
        String lastHost = UnreliableSocketFactory.getHostFromLastConnection();
        for (String h : downHosts) {
            assertNotEquals(h, lastHost);
        }
        downHosts.add(lastHost);
        UnreliableSocketFactory.downHost(lastHost.substring(1));
        UnreliableSocketFactory.flushConnectionAttempts();
    }
    // None of the hosts is available by now.
    assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", () -> {
        client.getSession();
        return null;
    });
    UnreliableSocketFactory.dontDownHost("host3");
    UnreliableSocketFactory.flushConnectionAttempts();
    client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host3"), UnreliableSocketFactory.getHostFromLastConnection());
    UnreliableSocketFactory.flushConnectionAttempts();
    client.getSession();
    assertTrue(UnreliableSocketFactory.isConnected());
    assertEquals(UnreliableSocketFactory.getHostConnectedStatus("host3"), UnreliableSocketFactory.getHostFromLastConnection());
    client.close();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) XDevAPIError(com.mysql.cj.xdevapi.XDevAPIError) RowResult(com.mysql.cj.xdevapi.RowResult) JsonNumber(com.mysql.cj.xdevapi.JsonNumber) ServerMessages(com.mysql.cj.x.protobuf.Mysqlx.ServerMessages) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) Random(java.util.Random) Collection(com.mysql.cj.xdevapi.Collection) ByteBuffer(java.nio.ByteBuffer) Constants(com.mysql.cj.Constants) Future(java.util.concurrent.Future) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) SqlStatement(com.mysql.cj.xdevapi.SqlStatement) Map(java.util.Map) ClientImpl(com.mysql.cj.xdevapi.ClientImpl) CoreSession(com.mysql.cj.CoreSession) ServerVersion(com.mysql.cj.ServerVersion) WrongArgumentException(com.mysql.cj.exceptions.WrongArgumentException) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) Warning(com.mysql.cj.xdevapi.Warning) SocketFactory(com.mysql.cj.protocol.SocketFactory) Set(java.util.Set) BlockingQueue(java.util.concurrent.BlockingQueue) XdevapiSslMode(com.mysql.cj.conf.PropertyDefinitions.XdevapiSslMode) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) Executors(java.util.concurrent.Executors) PropertyDefinitions(com.mysql.cj.conf.PropertyDefinitions) Test(org.junit.jupiter.api.Test) ByteOrder(java.nio.ByteOrder) List(java.util.List) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) FeatureNotAvailableException(com.mysql.cj.exceptions.FeatureNotAvailableException) SqlMultiResult(com.mysql.cj.xdevapi.SqlMultiResult) InjectedSocketFactory(testsuite.InjectedSocketFactory) FindStatement(com.mysql.cj.xdevapi.FindStatement) Assertions.fail(org.junit.jupiter.api.Assertions.fail) IntStream(java.util.stream.IntStream) MysqlErrorNumbers(com.mysql.cj.exceptions.MysqlErrorNumbers) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) CompletableFuture(java.util.concurrent.CompletableFuture) JsonString(com.mysql.cj.xdevapi.JsonString) Schema(com.mysql.cj.xdevapi.Schema) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) Client(com.mysql.cj.xdevapi.Client) ClientProperty(com.mysql.cj.xdevapi.Client.ClientProperty) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) WeakReference(java.lang.ref.WeakReference) SessionImpl(com.mysql.cj.xdevapi.SessionImpl) ExecutorService(java.util.concurrent.ExecutorService) Session(com.mysql.cj.xdevapi.Session) Properties(java.util.Properties) Frame(com.mysql.cj.x.protobuf.MysqlxNotice.Frame) Iterator(java.util.Iterator) DbDoc(com.mysql.cj.xdevapi.DbDoc) DocResult(com.mysql.cj.xdevapi.DocResult) Field(java.lang.reflect.Field) Compression(com.mysql.cj.conf.PropertyDefinitions.Compression) XProtocolError(com.mysql.cj.protocol.x.XProtocolError) SessionFactory(com.mysql.cj.xdevapi.SessionFactory) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Row(com.mysql.cj.xdevapi.Row) SqlResult(com.mysql.cj.xdevapi.SqlResult) MessageLite(com.google.protobuf.MessageLite) AfterEach(org.junit.jupiter.api.AfterEach) SelectStatement(com.mysql.cj.xdevapi.SelectStatement) PooledXProtocol(com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol) PropertyKey(com.mysql.cj.conf.PropertyKey) CJPacketTooBigException(com.mysql.cj.exceptions.CJPacketTooBigException) UnreliableSocketFactory(testsuite.UnreliableSocketFactory) ClientFactory(com.mysql.cj.xdevapi.ClientFactory) JsonString(com.mysql.cj.xdevapi.JsonString) Client(com.mysql.cj.xdevapi.Client) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test)

Example 5 with Client

use of com.mysql.cj.xdevapi.Client in project aws-mysql-jdbc by awslabs.

the class SecureSessionTest method testXdevapiTlsVersionsAndCiphersuites.

@Test
public void testXdevapiTlsVersionsAndCiphersuites() throws Exception {
    assumeTrue(supportsTestCertificates(this.session), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
    assumeTrue(supportsTestCertificates(this.session), "This test requires the server with RSA support.");
    // newer GPL servers, like 8.0.4+, are using OpenSSL and can use RSA encryption, while old ones compiled with yaSSL cannot
    Session sess = this.fact.getSession(this.sslFreeBaseUrl);
    String highestCommonTlsVersion = getHighestCommonTlsVersion(sess);
    sess.close();
    Properties props = new Properties(this.sslFreeTestProperties);
    props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), PropertyDefinitions.XdevapiSslMode.VERIFY_CA.toString());
    props.setProperty(PropertyKey.xdevapiSslTrustStoreUrl.getKeyName(), this.trustStoreUrl);
    props.setProperty(PropertyKey.xdevapiSslTrustStorePassword.getKeyName(), this.trustStorePassword);
    Session testSession;
    final ClientFactory cf = new ClientFactory();
    // TS.FR.1_1. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-versions with a single TLS protocol.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_version for details).
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "TLS protocols TLSv1 and TLSv1.1 are not supported. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1")));
    // TS.FR.1_2. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-versions with a valid list of TLS protocols.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_version for details).
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2,TLSv1.1,TLSv1"));
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.1_3. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with a single TLS protocol.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_version for details).
    // 
    // UPD: Behaviour was changed by WL#14805.
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "TLSv1");
    assertThrows(SSLParamsException.class, "TLS protocols TLSv1 and TLSv1.1 are not supported. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(props));
    // TS.FR.1_4. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with a valid list of TLS protocols.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_version for details).
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "TLSv1.2,TLSv1.1,TLSv1");
    testSession = this.fact.getSession(props);
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.1_5. Repeat the tests TS.FR.1_1 and TS.FR.1_2 using a ClientFactory instead of a SessionFactory.
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "TLS protocols TLSv1 and TLSv1.1 are not supported. Accepted values are TLSv1.2 and TLSv1.3.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    Client cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2,TLSv1.1,TLSv1"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    cli.close();
    // TS.FR.2_1. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-versions without any value.
    // Assess that the code terminates with a WrongArgumentException containing the defined message.
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "")));
    // TS.FR.2_2. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions without any value.
    // Assess that the code terminates with a WrongArgumentException containing the defined message.
    // 
    // UPD: Behaviour was changed by WL#14805.
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "");
    assertThrows(SSLParamsException.class, "Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(props));
    // TS.FR.2_3. Repeat the test TS.FR.2_1 using a ClientFactory instead of a SessionFactory.
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "Specified list of TLS versions is empty. Accepted values are TLSv1.2 and TLSv1.3.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, ""), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    // TS.FR.3_1. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-versions with
    // an invalid value, for example SSLv3. Assess that the code terminates with a WrongArgumentException containing the defined message.
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "SSLv3")));
    // TS.FR.3_2. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with
    // an invalid value, for example SSLv3. Assess that the code terminates with a WrongArgumentException containing the defined message.
    // 
    // UPD: Behaviour was changed by WL#14805.
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "SSLv3");
    assertThrows(SSLParamsException.class, "Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(props));
    // TS.FR.3_3. Repeat the test TS.FR.3_1 using a ClientFactory instead of a SessionFactory.
    // 
    // UPD: Behaviour was changed by WL#14805.
    assertThrows(SSLParamsException.class, "Specified list of TLS versions only contains non valid TLS protocols. Accepted values are TLSv1.2 and TLSv1.3.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "SSLv3"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    // TS.FR.4_1. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-ciphersuites with a single valid cipher-suite.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"));
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.4_2. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-ciphersuites with a valid list of cipher-suites.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA,AES256-SHA256"));
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.4_3   Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-ciphersuites with a list of valid and invalid cipher-suites,
    // starting with an invalid one. Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5,TLS_DHE_RSA_WITH_AES_128_CBC_SHA"));
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.4_4. Create an X DevAPI session using a connection string containing the connection property xdevapi.tls-ciphersuites with a single invalid cipher-suite.
    // Assess that the connection property is initialized with the correct values and that the connection fails with an SSL error.
    Throwable ex = assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", () -> {
        this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5"));
        return null;
    });
    assertNotNull(ex.getCause());
    assertEquals("javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)", ex.getCause().getMessage());
    // TS.FR.4_5. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with a single valid cipher-suite.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    props.remove(PropertyKey.xdevapiTlsVersions.getKeyName());
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
    testSession = this.fact.getSession(props);
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    testSession.close();
    // TS.FR.4_6. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with a valid list of cipher-suites.
    // Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_DHE_RSA_WITH_AES_128_CBC_SHA,AES256-SHA256");
    testSession = this.fact.getSession(props);
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    testSession.close();
    // TS.FR.4_7. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-versions with a list of valid and invalid cipher-suites,
    // starting with an invalid one. Assess that the connection property is initialized with the correct values and that the correct protocol was used (consult status variable ssl_cipher for details).
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5,TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
    testSession = this.fact.getSession(props);
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    testSession.close();
    // TS.FR.4_8. Create an X DevAPI session using a connection properties map containing the connection property xdevapi.tls-ciphersuites with a single invalid cipher-suite.
    // Assess that the connection property is initialized with the correct values and that the connection fails with an SSL error.
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5");
    assertThrows(CJCommunicationsException.class, "javax.net.ssl.SSLHandshakeException: No appropriate protocol \\(protocol is disabled or cipher suites are inappropriate\\)", () -> {
        this.fact.getSession(props);
        return null;
    });
    // TS.FR.4_9. Repeat the tests TS.FR.4_1 to TS.FR.4_4 using a ClientFactory instead of a SessionFactory.
    cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA,AES256-SHA256"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5,TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    ex = assertThrows(CJCommunicationsException.class, "Unable to connect to any of the target hosts\\.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    assertNotNull(ex.getCause());
    assertEquals("javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)", ex.getCause().getMessage());
    // TS.FR.5_1. Create an X DevAPI session using a connection string without the connection properties xdevapi.tls-versions and xdevapi.tls-ciphersuites.
    // Assess that the session is created successfully and the connection properties are initialized with the expected values.
    testSession = this.fact.getSession(this.sslFreeBaseUrl);
    assertSecureSession(testSession);
    assertTlsVersion(testSession, highestCommonTlsVersion);
    testSession.close();
    // TS.FR.5_2. Create an X DevAPI session using a connection string with the connection property xdevapi.tls-versions but without xdevapi.tls-ciphersuites.
    // Assess that the session is created successfully and the connection property xdevapi.tls-versions is initialized with the expected values.
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2"));
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.5_3. Create an X DevAPI session using a connection string with the connection property xdevapi.tls-ciphersuites but without xdevapi.tls-versions.
    // Assess that the session is created successfully and the connection property xdevapi.tls-ciphersuites is initialized with the expected values.
    testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"));
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.5_4. Create an X DevAPI session using a connection properties map without the connection properties xdevapi.tls-versions and xdevapi.tls-ciphersuites.
    // Assess that the session is created successfully and the connection properties are initialized with the expected values.
    props.remove(PropertyKey.xdevapiTlsVersions.getKeyName());
    props.remove(PropertyKey.xdevapiTlsCiphersuites.getKeyName());
    testSession = this.fact.getSession(props);
    assertSecureSession(testSession);
    assertTlsVersion(testSession, highestCommonTlsVersion);
    testSession.close();
    // TS.FR.5_5. Create an X DevAPI session using a connection properties map with the connection property xdevapi.tls-versions but without xdevapi.tls-ciphersuites.
    // Assess that the session is created successfully and the connection property xdevapi.tls-versions is initialized with the expected values.
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "TLSv1.2");
    testSession = this.fact.getSession(props);
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    testSession.close();
    // TS.FR.5_6. Create an X DevAPI session using a connection properties map with the connection property xdevapi.tls-ciphersuites but without xdevapi.tls-versions.
    // Assess that the session is created successfully and the connection property xdevapi.tls-ciphersuites is initialized with the expected values.
    props.remove(PropertyKey.xdevapiTlsVersions.getKeyName());
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
    testSession = this.fact.getSession(props);
    assertTlsVersion(testSession, "TLSv1.2");
    assertSessionStatusEquals(testSession, "mysqlx_ssl_cipher", "DHE-RSA-AES128-SHA");
    testSession.close();
    // TS.FR.5_7. Repeat the tests TS.FR.5_1 to TS.FR.5_3 using a ClientFactory instead of a SessionFactory.
    cli = cf.getClient(this.sslFreeBaseUrl, "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSecureSession(testSession);
    assertTlsVersion(testSession, highestCommonTlsVersion);
    cli.close();
    cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    cli.close();
    cli = cf.getClient(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), "{\"pooling\": {\"enabled\": true}}");
    testSession = cli.getSession();
    assertSecureSession(testSession);
    assertTlsVersion(testSession, "TLSv1.2");
    cli.close();
    // TS.FR.6_1. Create an X DevAPI session using a connection string with the connection property xdevapi.ssl-mode=DISABLED and both the connection properties
    // xdevapi.tls-versions and xdevapi.tls-ciphersuites. Assess that the code terminates with a WrongArgumentException containing the defined message.
    String xdevapiSSLMode = makeParam(PropertyKey.xdevapiSslMode, PropertyDefinitions.XdevapiSslMode.DISABLED.toString());
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2") + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA")));
    // TS.FR.6_2. Create an X DevAPI session using a connection string with the connection property xdevapi.ssl-mode=DISABLED and the connection property xdevapi.tls-versions
    // but not xdevapi.tls-ciphersuites. Assess that the code terminates with a WrongArgumentException containing the defined message.
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2")));
    // 
    // TS.FR.6_3. Create an X DevAPI session using a connection string with the connection property xdevapi.ssl-mode=DISABLED and the connection property xdevapi.tls-ciphersuites
    // but not xdevapi.tls-versions. Assess that the code terminates with a WrongArgumentException containing the defined message.
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsCiphersuites.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA")));
    // 
    // TS.FR.6_4. Create an X DevAPI session using a connection properties map with the connection property xdevapi.ssl-mode=DISABLED and both the connection properties xdevapi.tls-versions
    // and xdevapi.tls-ciphersuites. Assess that the code terminates with a WrongArgumentException containing the defined message.
    props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), PropertyDefinitions.XdevapiSslMode.DISABLED.toString());
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "TLSv1.2");
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(props));
    // TS.FR.6_5. Create an X DevAPI session using a connection properties map with the connection property xdevapi.ssl-mode=DISABLED and the connection property xdevapi.tls-versions
    // but not xdevapi.tls-ciphersuites. Assess that the code terminates with a WrongArgumentException containing the defined message.
    props.setProperty(PropertyKey.xdevapiTlsVersions.getKeyName(), "TLSv1.2");
    props.remove(PropertyKey.xdevapiTlsCiphersuites.getKeyName());
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(props));
    // TS.FR.6_6. Create an X DevAPI session using a connection properties map with the connection property xdevapi.ssl-mode=DISABLED and the connection property xdevapi.tls-ciphersuites
    // but not xdevapi.tls-versions. Assess that the code terminates with a WrongArgumentException containing the defined message.
    props.remove(PropertyKey.xdevapiTlsVersions.getKeyName());
    props.setProperty(PropertyKey.xdevapiTlsCiphersuites.getKeyName(), "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsCiphersuites.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> this.fact.getSession(props));
    // TS.FR.6_7. Repeat the tests TS.FR.6_1 to TS.FR.6_3 using a ClientFactory instead of a SessionFactory.
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsVersions.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsVersions, "TLSv1.2") + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
    assertThrows(WrongArgumentException.class, "Option '" + PropertyKey.xdevapiTlsCiphersuites.getKeyName() + "' can not be specified when SSL connections are disabled.", () -> {
        Client cli1 = cf.getClient(this.sslFreeBaseUrl + xdevapiSSLMode + makeParam(PropertyKey.xdevapiTlsCiphersuites, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), "{\"pooling\": {\"enabled\": true}}");
        cli1.getSession();
        return null;
    });
}
Also used : ClientFactory(com.mysql.cj.xdevapi.ClientFactory) Properties(java.util.Properties) Client(com.mysql.cj.xdevapi.Client) CJCommunicationsException(com.mysql.cj.exceptions.CJCommunicationsException) CoreSession(com.mysql.cj.CoreSession) Session(com.mysql.cj.xdevapi.Session) Test(org.junit.jupiter.api.Test)

Aggregations

Client (com.mysql.cj.xdevapi.Client)11 ClientFactory (com.mysql.cj.xdevapi.ClientFactory)11 Properties (java.util.Properties)11 CoreSession (com.mysql.cj.CoreSession)10 Session (com.mysql.cj.xdevapi.Session)10 Test (org.junit.jupiter.api.Test)10 CJCommunicationsException (com.mysql.cj.exceptions.CJCommunicationsException)7 JsonString (com.mysql.cj.xdevapi.JsonString)7 CJPacketTooBigException (com.mysql.cj.exceptions.CJPacketTooBigException)6 FeatureNotAvailableException (com.mysql.cj.exceptions.FeatureNotAvailableException)6 WrongArgumentException (com.mysql.cj.exceptions.WrongArgumentException)6 SessionImpl (com.mysql.cj.xdevapi.SessionImpl)6 FileNotFoundException (java.io.FileNotFoundException)6 Field (java.lang.reflect.Field)6 ExecutionException (java.util.concurrent.ExecutionException)6 PooledXProtocol (com.mysql.cj.xdevapi.ClientImpl.PooledXProtocol)5 FindStatement (com.mysql.cj.xdevapi.FindStatement)5 Row (com.mysql.cj.xdevapi.Row)5 RowResult (com.mysql.cj.xdevapi.RowResult)5 MessageLite (com.google.protobuf.MessageLite)4